目次
3.2 履歴を保存し、index.html コンテンツを構築する
3.3 シミュレーション サーバーはフロントエンド アプリケーションをホストします
3.5 フロントエンドビジュアルページ開発の迅速なロールバック
I.はじめに
プロジェクトの迅速なロールバックは、フロントエンド エンジニアリングの非常に重要な部分です。プロジェクトがオンラインでデプロイされた後、エラーが発生したり、その他の理由で前のバージョンにロールバックする必要がある場合、ロールバックの速度が特に重要になります。現時点では。
通常のロールバック手順:以前のバージョンのコードを元に戻し、再パッケージ化してオンラインにするには、git replace rollback code またはgit rervetが必要です。コードの撤回と再パッケージ化には時間がかかり、オンライン時間に数分間影響します。第 2 レベルのロールバックを実現するためのより高速なソリューション。
Dockerは優れた実装ソリューションですが、すべての企業がフロントエンド アプリケーションのデプロイにDockerを使用しているわけではなく、ほとんどのアプリケーションはnginxを通じてローカルにホストされるか、 OSSにアップロードされてCDNを通じて静的リソースにアクセスします。
この記事では、フロントエンド プロジェクトの第 2 レベルのロールバックのデモを実装する手順を段階的に説明します。この記事は、記事と一緒に手動で入力するのに適しています。プロセス全体の実装をよりよく理解し、すぐに適用できます。あなたの会社のプロジェクト。
この記事の例の完全なコードは、github.com/guojiongwei…にアップロードされています。
2. アイデア
シングルページ アプリケーションがパッケージ化されると、index.htmlエントリ ファイルが作成されます。パッケージ化された各index.htmlには、このバージョンで必要な静的リソースが含まれます。以前のバージョンの静的リソースを削除できない (または、静的リソースをoss ) が作成され、プロジェクトがパッケージ化されるたびに、パッケージ化された情報とindex.htmlコンテンツが保存され、配列リスト データが保存されます。
バージョンをロールバックする必要がある場合、フロントエンドのビジュアル インターフェイスを介してプロジェクトのブランチ内のビルド レコードを選択すると、迅速にロールバックできます。具体的な実装原則は、現在のプロジェクトで現在使用されているindex.htmlコンテンツを、ロールバック バージョンに保存されているindex.htmlコンテンツに置き換えることです。index.htmlコンテンツを置き換えた後、インポートされた静的リソースは、によってパッケージ化された静的リソース パスになります。このバージョンでは、迅速なロールバックを実現します。
静的リソースは通常、 ossに 配置でき、これはCDN高速化にも便利ですが、この記事では機能を説明するために、毎回パッケージ化された静的リソースをプロジェクトのローカルdistに配置し、リビルドしても元のリソースは削除されません。
このソリューションは、react や vue、webpack や vite に関係なく、すべてのシングルページ アプリケーション プロジェクトに適用できます。全体的なアイデアは、css、js、履歴に組み込まれた画像などの静的リソースを保存し、それぞれのインデックス.html コンテンツを保存することです。ビルドしてロールバックする 現在のコンテンツを対応するバージョンのindex.htmlコンテンツに置き換えて、実際の第2レベルのロールバックを実現します。
3. 練習する
3.1 シングルページアプリケーションプロジェクトの準備
まず単一ページのアプリケーション プロジェクトを準備します。react + vite を例として、コマンド ラインでコマンドを実行してプロジェクトを作成します。
# npm 6.x
npm create vite@latest quick_rollback --template react-ts
# npm 7+, 需要加双--
npm create vite@latest quick_rollback -- --template react-ts
プロジェクトが作成されたら、プロジェクトを入力して依存関係をインストールします。
cd quick_rollback
npm install
デフォルトでは、 vite はビルド時に元のdistフォルダーを削除します。各ビルドの静的リソースがdistに保持されるように、vite がビルド時に元のdistファイルを削除しないように構成を変更する必要があります( webpackにも同様のものがあります)構成)。
vite.config.ts構成を変更し、ビルド構成を追加します。
build: {
emptyOutDir: false, // 每次打包后不删除输出目录
}
注: 実際のプロジェクトは通常、フロントエンドの静的リソースをossにアップロードします。CDNアクセスが使用される場合、この項目を設定する必要はありません。この項目は主に、この記事のデモデモンストレーションの便宜のために設定されています。
会社のフロントエンド プロジェクトの静的リソースがossにアップロードされていないが、基本的に現在のサーバーのプロジェクトdistファイルに配置され、 nginxでホストされている場合でも、この項目を設定する必要があります。構築リソース。第 2 レベルのロールバックを実現します。
テストしてみましょう。まず最初のパッケージ化を実行します。
npm run build
プロジェクト内にdistフォルダが生成される
src/App.tsxのコードを変更し、次のように置き換えます。
<h1>Vite + React</h1>
// 替换为
<h1>Vite + React + 秒级回滚</h1>
置き換えが完了したら、再度npm run buildを実行してパッケージ化します。
再パッケージ化時にdistフォルダーが空にならず、最後のビルドのIndex.js が保持されていることがわかります。
次に行うことは、ビルドが成功するたびに、 index.htmlの値を記録して保存し、ロールバック時にその値を使用して置き換えることです。
3.2 履歴を保存し、index.html コンテンツを構築する
新しいスクリプト ファイルbuild.mjs をプロジェクトのルート ディレクトリに追加し ( ES モジュール構文を使いやすくするために .mjs を使用します)、コードを追加します。
// build.mjs
console.log('打包记录历史构建index.html内容')
そして、npm run buildの後にファイルを実行し、 package.jsonを変更します。
"build": "tsc && vite build && node build.mjs",
これで、ノードの build.mjsファイルがパッケージ化されるたびに実行され、パッケージ化されたindex.htmlコンテンツが取得されて保存されます。
保存されたビルド レコードの内容は保存する必要があり、データベースに保存できます。この記事では、単純なシミュレーションのために、 history.jsonファイルを プロジェクトのルート ディレクトリに保存します。
build.jmsを変更します。
// build.js
import path from 'path'
import fs from 'fs'
function start() {
// 设置存储构建的history.json文件路径
const historyPath = path.resolve('history.json')
// 如果json文不存在就创建一个,初始值为 { list: [] }
if(!fs.existsSync(historyPath)) {
fs.writeFileSync(historyPath, JSON.stringify({ list: [] }))
}
// 读取本次打包后的dist/index.html内容
const html = fs.readFileSync(path.resolve('./dist/index.html'), 'utf-8')
// 获取到当前histyory.json的内容
const history = JSON.parse(fs.readFileSync(historyPath, 'utf-8'))
// 将当前打包的信息push到history的list中,包含构建时间和index.html内容还有id
// 实际应用中还可以添加其他的很多信息
history.list.push({
time: new Date().toLocaleString('zh-cn'),
html,
// 模拟生成一个随机的id
id: Math.random().toString(16).substr(2),
// ... 分支信息,commit信息,构建时间,构建人,构建环境等字段
})
// 将最新的构建记录内容写入到history.json中
fs.writeFileSync(historyPath, JSON.stringify(history, null, 2))
}
start()
具体的なロジック:
- まず、ビルドを保存するhistory.jsonファイルのパスを設定します。
- json ファイルが存在しない場合は作成します。初期値は { list: [] }です。
- 今回はパッケージ化後にdist/index.htmlの内容を読んでください。
- 現在のhistory.jsonファイルの内容を取得します。
- ビルド時間、index.htmlコンテンツとID (およびその他の情報)を含む、現在パッケージ化されている情報をlistにプッシュします。
- 最新のビルド レコード データをhistory.jsonファイルに書き込みます。
変更が完了したら、最初にパッケージを実行します。
npm run build
次に、src/App.tsxを変更し、先ほどの変更を元に戻します。
<h1>Vite + React + 秒级回滚</h1>
// 替换为
<h1>Vite + React</h1>
交換が完了したら、再度梱包します。
npm run build
パッケージ化が完了したら、history.jsonファイルを確認すると、 2 つのビルドのindex.html情報が保存されていることがわかります。
建設履歴レコードを保存した後、ロールバック ロジックを実装するために、ノードサービスとフロントエンドのビジュアル ロールバック ページを 作成する必要があります。実装手順は次のとおりです。
- フロントエンド視覚化ページでビルド レコードを選択した後、ID をノードサーバーに渡します。
- サーバーはidに従って対応するHTMLコンテンツを見つけ、dist/index.htmlのコンテンツをHTMLコンテンツに置き換えます。
- 置換が完了すると、ユーザーはページにアクセスしたときに対応するバージョンのコンテンツにアクセスできるようになり、第 2 レベルのロールバックが実現します。
3.3 シミュレーション サーバーはフロントエンド アプリケーションをホストします
フロントエンド プロジェクトがhtml、css、およびjs静的リソースにパッケージ化された後、通常、外部ネットワーク アクセスを実現するためにnginxによってホストされます。この記事では、パッケージ化されたリソースをホストするためにフロントエンド静的リソース サーバーを使用します。
最初にグローバルにインストールします ( Mac には sudo を追加する必要があります):
npm i serve -g
インストールが完了したら、クイック ロールバックQuick_rollbackプロジェクトに移動し、serveコマンドを実行して、distフォルダーの静的リソースをホストします。
serve -s dist
起動が成功すると、ターミナルにホストされたアクセス アドレスが表示され、ブラウザーでそのアドレスを開いて、プロジェクトがすでにアクセス可能であることを確認できます。
3.4 迅速なロールバック ノード サーバー コードの開発
まず、server.mjsを作成して、サーバー側のコード、サーバー側で行うことを記述します。
- ポート3001でサービスを開始します。
- ルート パスにアクセスすると、フロントエンドのビジュアル ロールバック ページが返されます。
- フロントエンド ページに過去の建設記録データを提供する/historyインターフェイスを提供します 。
- /rollbackインターフェイスは、フロントエンド ページをロールバックするバージョンのインターフェイスを提供するために提供されています 。
- /rollbackロジックを処理し 、対応するバージョンのHTMLコンテンツを見つけて、dist/index.htmlファイルのコンテンツを置き換えます。
1. プロジェクトのルートディレクトリに新しいserver.mjsを作成します。
まず、httpを使用して基本的なサーバーを作成します。
import http from 'http';
import url from 'url';
import fs from 'fs';
import path from 'path';
const server = http.createServer((req, res) => {
// 获取请求的路径
const { pathname } = url.parse(req.url, true);
// 获取请求的方法
const method = req.method.toLowerCase();
// ... 后续的代码都会写在这里
})
server.listen(3001, () => {
console.log('server is running on http://localhost:3001')
});
2. ルート パス インターフェイスを追加し、rollback.html ビジュアル ロールバック ページに戻ります。
フロントエンドでビジュアルページ操作をロールバックするとより便利です。プロジェクトのルートディレクトリにrollback.htmlファイルを作成し、簡単なコードを追加します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>rollback</title>
</head>
<body>
</body>
</html>
次に、server.mjsファイルを変更し、ルート パス インターフェイスを追加します。
// server.mjs
// 如果请求的是根路径,就返回rollback.html
if(pathname === '/' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'text/html' }, 'utf-8')
res.end(fs.readFileSync(path.resolve('./rollback.html'), 'utf-8'))
}
このようにして、ノードserver.mjsがサーバーを起動してhttp://localhost:3001アドレスにアクセスすると、 rollback.htmlページにアクセスします。
3. 工事記録を取得するためのインターフェースを追加
rollback.html視覚化ページ では、ロールバック操作を容易にするために過去の建設記録を取得する必要があります。history.jsonファイルの内容を返し、 server.mjsファイルを変更し、コードを追加します:
// 如果请求的是history,就返回history.json的内容
if(pathname === '/history' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'application/json' }, 'utf-8')
res.end(JSON.stringify({
code: 200,
mssage: '操作成功',
data: JSON.parse(fs.readFileSync(path.resolve('./history.json'), 'utf-8'))
}))
}
4. インターフェースにクイックロールバックを追加する
視覚化ページで建設履歴レコードにアクセスした後、ロールバックする履歴バージョンを選択できるため、サーバーはロールバック インターフェイスを提供し、server.mjsを変更し、コードを追加する必要があります。
// 如果请求的是rollback,就将对应版本的html内容写入到dist/index.html中
if(pathname === '/rollback' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'application/json' }, 'utf-8')
const { query } = url.parse(req.url, true);
const { id } = query;
const history = JSON.parse(fs.readFileSync(path.resolve('./history.json'), 'utf-8'));
const html = history.list.find(item => item.id === id).html;
fs.writeFileSync(path.resolve('./dist/index.html'), html);
res.end(JSON.stringify({
code: 200,
mssage: '操作成功',
data: {}
}));
}
コードのロジックは比較的単純です。
- 取得リクエスト /ロールバックインターフェイスを提供します。
- クエリパラメータidを受け取ります。
- 歴史の建築実績データを取得します。
- IDを過去のビルド レコード データと比較して、対応するビルド レコードを見つけます。
- 対応するindex.htmlコンテンツを取得し、 ./dist/index.htmlを変更して迅速なロールバック操作を実現します。
- 次に、フロントエンドに応答します。
この時点で、サーバーの基本ロジックが記述され、クイック ロールバック視覚化ページrollback.htmlのコードが開始されます。
完全なserver.mjsコード:
import http from 'http';
import url from 'url';
import fs from 'fs';
import path from 'path';
const server = http.createServer((req, res) => {
// 获取请求的路径
const { pathname } = url.parse(req.url, true);
// 获取请求的方法
const method = req.method.toLowerCase();
// 如果请求的是根路径,就返回rollback.html
if(pathname === '/' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'text/html' }, 'utf-8')
res.end(fs.readFileSync(path.resolve('./rollback.html'), 'utf-8'))
}
// 如果请求的是history,就返回history.json的内容
if(pathname === '/history' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'application/json' }, 'utf-8')
res.end(JSON.stringify({
code: 200,
mssage: '操作成功',
data: JSON.parse(fs.readFileSync(path.resolve('./history.json'), 'utf-8'))
}))
}
// 如果请求的是rollback,就将对应版本的html内容写入到dist/index.html中
if(pathname === '/rollback' && method === 'get') {
res.writeHead(200, { 'Content-Type': 'application/json' }, 'utf-8')
const { query } = url.parse(req.url, true);
const { id } = query;
const history = JSON.parse(fs.readFileSync(path.resolve('./history.json'), 'utf-8'));
const html = history.list.find(item => item.id === id).html;
fs.writeFileSync(path.resolve('./dist/index.html'), html);
res.end(JSON.stringify({
code: 200,
mssage: '操作成功',
data: {}
}));
}
})
server.listen(3001, () => {
console.log('server is running on http://localhost:3001')
});
3.5 フロントエンドビジュアルページ開発の迅速なロールバック
フロントエンド ページも比較的シンプルで、インターフェイスにはロールバック バージョンを選択するための選択ボックスと、ロールバック操作を確認するための[OK] ボタンが用意されています。
dom操作から解放されるために、ここでは与田さんが開発したpetite-vueを利用してフロントエンドページを開発していきます。
petite-vue は、プログレッシブ エンハンスメント向けに最適化されたVueの代替ディストリビューション です 。標準のVueと 同じテンプレート構文とリアクティブ モデルを提供します 。
- サイズはわずか5.8kb
- Vue 互換テンプレートの構文
- DOM に基づいて、インプレース変換
- 反応の良いドライバー
rollback.htmlを変更し、select要素とbutton要素を追加して、インスタンス化のためにpetite-vue cdnファイルをインポートします。
- インスタンスの初期化直後に構築レコードのリストの取得をリクエストし、this.historyListに代入します。
- ページ上の構築レコードの走査により、選択オプションoptionが生成され、v-modelバインディング値はthis.currentItemです。
- ボタンボタンはロールバック確認ボタンで、クリック後、まずロールバックバージョンが選択されているかどうかを判断します。
- 選択肢がない場合はプロンプトを表示し、確認を 2 回使用して確認することを選択します。
- 確認後、サーバー側ロールバックインターフェースを呼び出してidを渡し、応答内容に従って実行結果を取得します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>rollback</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/petite-vue/0.4.1/petite-vue.umd.min.js"></script>
<div id="app" @vue:mounted="onMounted">
<select v-model="currentItem">
<option value="">请选择回滚版本</option>
<option v-for="item in historyList" :key="item.id" :value="item">发版时间:{
{ item.time }}</option>
</select>
<button @click="onRollback">回滚</button>
</div>
</body>
<script>
/** vue实例 */
PetiteVue.createApp({
historyList: [], // 构建记录列表
currentItem: undefined, // 当前选中的项目
onMounted() {
this.getHistory();
},
/** 获取构建记录列表 */
getHistory() {
fetch("/history").then(res => res.json()).then(res => {
if (res.code === 200) {
this.historyList = res.data.list;
}
});
},
/** 代码回滚 */
onRollback() {
if (!this.currentItem) return alert("请选择回滚目标版本!");
const isRollback = confirm(`确认项目回滚到${this.currentItem.time}版本!`);
if (isRollback) {
fetch(`/rollback?id=${this.currentItem.id}`).then(res => res.json()).then(res => {
if (res.code === 200) {
alert("快速回滚成功!");
}
});
}
},
}).mount("#app");
</script>
</html>
3.6 クイックロールバックテスト
上記のパッケージは 2 つのビルド バージョン ページを生成し、2 つのバージョン ページの h1 タグにはそれぞれVite + React
と が表示されます。Vite + React + 快速回滚
まず、serveを使用して現在のdistフォルダーの静的リソースをホストし、実行します。
serve -s dist
プロジェクト アドレス ブラウザを開いて、現在のコンテンツを確認します。
新しいターミナルを開き、サーバー コードを開始します。
node server.mjs
次にhttp://localhost:3001 ページを開きます
リリース時刻が古いバージョンを選択すると、そのバージョンに対応するページが表示されますVite + React + 快速回滚
。選択が完了したら、[ロールバック] をクリックして 2 回目の確認を行います。次のプロンプトが表示された場合は、ロールバックが成功したことを意味します。
この時点で、フロントエンド反応プロジェクト ページに戻り、ブラウザを更新すると、ページのコンテンツがロールバック バージョンに変更されていることがわかります。
この時点で、第 2 レベルのロールバックのコア機能が完了しました。
4. まとめ
過去のビルド コードを保存するこの方法により、次の 2 つの一般的な問題も回避できます。
- distファイルはフロントエンドの構築時にクリアされ、この時点ではフロントエンド アクセス プロジェクトにアクセスできなくなります。
- ルーティングの遅延読み込みが使われており、新バージョンがリリースされると元のファイルが消えてリソースを要求するページに飛んでしまい、404となってページが異常になってしまいます。
多目的に使用できると言えますが、現時点ではまだ問題があり、履歴構築ファイルが削除されないため、ファイルはどんどん蓄積され、ストレージ リソースの無駄が発生します。
解決策は、build.mjsファイルを変更し、最後の5 つのビルド結果のみを保持し、5 回以外のビルド リソースを削除して、リソースをあまり浪費せずに第 2 レベルのロールバックを実現することです。
いくつかの実装アイデアを次に示します。
- ビルドするたびに、このビルドによって生成されるすべての静的リソース ファイルを取得します。
- 取得後、現在のビルド レコードに保存されます。
- 同時に、ファイル名をfiles.jsonファイルに保存し、ファイル パスをキーとして保存します。
- 各ビルド後に、現在のビルドの合計数が5を超えているかどうかを判断します。
- 最も古いビルドによって生成された静的リソース ファイルのリストを取得します。
- ファイル全体での比較には、最初に生成された静的リソース ファイルを使用してfiles.jsonします。
- 最初のビルドで生成されたファイルが次の 5 つのビルドで使用されない場合、そのファイルは削除できます。
通常、ロールバックは前のバージョンにロールバックすることですが、5 つ以上のバージョンにロールバックすることはまれです。その場合は、再パッケージ化してビルドします。
この記事では、フロントエンド オンライン プロジェクトの第 2 レベルのロールバックのアイデアのみを提供します。これは、すべてのシングル ページ アプリケーション プロジェクトに適しています。現在、私が働いている会社ではこのソリューションを使用していますが、実際に使用するにはより複雑であり、次のことを行う必要があります。プロジェクトはプロジェクトから分離されるため、各プロジェクトが使いやすくなります。
建設記録は、プロジェクトごとにデータベースまたはoss jsonファイルに保存する必要があります。ビジュアル管理プラットフォームはすべてのプロジェクトを制御し、個々のプロジェクトのそれぞれのブランチを迅速にロールバックできます。
この方法に加えて、第 2 レベルのロールバックを実現する方法は他にも多数あり、この方法は実装が比較的簡単で、コストも低く、広く使用されています。
後で、プロジェクトの迅速なロールバックを実現するためのdocker の使用に関する別の記事が予定されています。万能ソリューション、フロントエンドのシングルページ、マルチページ、およびサーバーサイドのプロジェクトはすべて、docker を使用して迅速なロールバックを実現できます。