技術的背景
プロジェクトで使用されるフレームワークはvue2であり、ビルドツールはwebpackです。
質問
プロジェクトは頻繁に繰り返されます。起動するたびに、システムを使用する前にシステムを手動で更新するように営業スタッフ(ユーザー)に通知する必要があります。そうしないと、古いバージョンが常に使用され、予期しないエラーが発生します。
理由
Vueフレームワークの開発はシングルページWebアプリケーション(SPA)です
人気の説明
Webページが初期化されるときに、対応するHTML、JavaScript、およびCSSをロードするだけです。ページがロードされると、SPAはユーザーの操作によってページをリロードまたはジャンプしません。代わりに、ルーティングメカニズムを使用して、HTMLコンテンツ、UI、およびユーザーインタラクションの変更を実装し、ページのリロードを回避します。
アドバンテージ
ユーザーエクスペリエンスは良好で高速であり、コンテンツの変更はページ全体をリロードする必要がないため、不要なジャンプや繰り返しのレンダリングを回避できます。上記の点でも、SPAはサーバーに比較的小さなプレッシャーをかけます。フロントエンドとバックエンドの責任分離され、構造が明確で、フロントエンドが実行されます。インタラクションロジック、バックエンドがデータ処理を担当します
欠点
初期読み込みには時間がかかります。シングルページWebアプリケーションの機能と表示効果を実現するには、ページの読み込み時にJavaScriptとCSSを均一に読み込み、オンデマンドで一部のページを読み込み、転送と管理を行う必要があります。後方ルーティング。
要約する
これは単一ページのアプリケーションであるため、ユーザーがWebサイトにアクセスするとすぐに、ブラウザーのキャッシュメカニズムを使用してHTMLと対応するリソースがローカルに保存されます。これはまた、プロジェクトバージョンのイテレーション後、ユーザーはキャッシュメカニズムのために古いイテレーションバージョンを引き続き使用し、ユーザーはサーバーを手動で更新して新しいHTMLに新しいイテレーションを使用するように要求する必要があるという事実にもつながります。バージョン。
ユーザーは手動で更新して新しいバージョンのhtmlを取得します(nginxで構成し、nginx.confファイルで設定を行って、index.htmlがキャッシュされないようにする必要があります)
必要
プロジェクトが繰り返されると、ユーザーはバージョンを更新するか、自動的に更新するように求められます。これにより、ユーザーはバージョンのアップグレードを認識できます。
プログラム
概略図
版本号为打包是自动创建的当前时间戳
接口获取的版本号:是webpack在构建的时候自动创建的版本号,生成 一个版本接口文件
静态页版本号:webpack构建过程中自动创建的版本号,自动写入index.html页面meta信息中
复制代码
コード
nginx
構成-index.htmlがキャッシュされないように、nginx.confファイルで設定を行います
location = /index.html {
root /usr/share/nginx/html;
add_header Cache-Control "no-cache, no-store";
}
复制代码
version.js
バージョンファイルを作成する
const fs = require('fs') // 引入文件模块
const Timestamp = new Date().getTime()
fs.writeFile('public/version.json', '{"version":' + Timestamp + '}\n', function (err) {
if (err) {
return console.log(err)
}
})
复制代码
package.json
vueビルドコマンド:
"build:prodb": "node version.js && vue-cli-service build --mode prodb"
复制代码
version.js 为版本号自动生成的文件,为请求接口所用。
vue.config.js
vue2-配置文件-vue.config.js
// 获取版本号数据
const bpmVersion = process.env.NODE_ENV === 'production'
|| process.env.NODE_ENV === 'prodb' ? require('./public/version.json') : {
version: 'dev'
}
module.exports = {
pages: {
index: {
// page 的入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
version: bpmVersion.version, // 版本号
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
}
}
复制代码
index.html
index.html-页面配置版本号字段存储
<meta name="version" content="<%= htmlWebpackPlugin.options.version%>" />
复制代码
generate-asset-webpack-plugin
也可以通过generate-asset-webpack-plugin
插件创建
const GeneraterAssetPlugin = require('generate-asset-webpack-plugin');
const {
name
} = require('./package.json');
const timestamp = new Date().getTime();
const version = `v${timestamp}`;
const createJson = function () {
const data = {
app: {
name,
version
}
};
return JSON.stringify(data);
};
plugins: [
// 生成版本标识
new GeneraterAssetPlugin({
filename: 'app.json',
fn: (compilation, cb) => {
cb(null, createJson());
}
})
],
chainWebpack: (config) => {
config
.plugin('html')
.tap(args => {
args[0].name = name;
args[0].version = timestamp;
return args
});
}
复制代码
生成 app.json 文件内容如下:
{"app":{"name":"app-name","version":"v1649818515910"}}
复制代码
目前是页面的版本号与接口的版本号,都已经准备就绪。剩下来就是两个版本比对。 关于比对,为了避免不必要的接口比对,特意将比对时机定格在进入路由-加载页面完成之后,这样用户体验效果会好些(纯粹个人体会)。
router.js
比对代码
router.js
router.afterEach(async (to, form) => {
// 生产环境提示升级
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'prodb') {
const checkVersion = await store.dispatch('checkVersion')
if (!checkVersion) { // 获取的版本号不等时
Message.warning('正在自动升级新版本...', 2, () => {
window.location.reload() // 版本不同 刷新 获取最新版本
})
}
}
})
复制代码
store.js
store.js
actions: {
checkVersion ({ commit, state }) {
return new Promise(resolve => {
Axios.get('/version.json?v=' + new Date().getTime(),
{ headers: { 'Cache-Control': 'no-cache' },
baseURL: window.location.origin })
//反正就是要请求到json文件的内容, 并且禁止缓存
.then(res => {
const version = res.version
const clientVersion = Number(document.querySelector('#BPMVersion').content
|| '')
resolve(version === clientVersion)
})
})
}
}
复制代码
优化
功能目前是可以达到需求要求,但我们还可以加入版本号的查看,方便知道目前使用的是哪个版本 以及什么时候上线的
store.js
checkVersion ({ commit, state }) {
return new Promise(resolve => {
Axios.get('/version.json?v=' + new Date().getTime(),
{ headers: { 'Cache-Control': 'no-cache' },
baseURL: window.location.origin })
// 反正就是要请求到json文件的内容, 并且禁止缓存
.then(res => {
const version = res.version
const clientVersion = Number(document.querySelector('#BPMVersion')
.content || '')
// 以下是查看版本号上线时间 - start
console.info('%c Environment ' + '%c ' + process.env.NODE_ENV + ' ',
'padding: 1px; border-radius: 3px 0 0 3px;
color: #fff; background:#606060',
'padding: 1px; border-radius: 0 3px 3px 0;
color: #fff; background:#42c02e')
console.info('%c Build Date ' + '%c ' +
dateFtt('yyyy-MM-dd hh:mm:ss',
new Date(clientVersion)) + ' ',
'padding: 1px; border-radius: 3px 0 0 3px;
color: #fff; background:#606060',
'padding: 1px; border-radius: 0 3px 3px 0;
color: #fff; background:#1475b2')
console.info('%c Last Build Date ' + '%c ' +
dateFtt('yyyy-MM-dd hh:mm:ss',
new Date(version)) + ' ',
'padding: 1px; border-radius: 3px 0 0 3px;
color: #fff; background:#606060',
'padding: 1px; border-radius: 0 3px 3px 0;
color: #fff; background:#1475b2')
// -end
resolve(version === clientVersion)
})
})
}
复制代码
版本号查看效果
页面提示
控制台输出
下期预告
针对目前项目中使用 webpack 打包速度越来越慢,希望自己在 vite 工具做多一些尝试,等踩完坑之后。4 月底会出 vite 与 webpack 的对比文章及实例,以及踩到的所有坑分享给大家
写到最后
目前代码只适用于 vue2 版本,其里面原理可以借鉴到其他框架。因方案全程只是前端自己参与,所以在每次切换路由的时候,会造成需要请求一次版本号接口的比对,会造成接口的些许浪费吧,目前暂时没有想到更好的办法来解决这个问题,期待后续会有优化这方面的方案吧。
团队介绍
高灯科技交易合规前端团队(GFE), 隶属于高灯科技(北京)交易合规业务事业线研发部,是一个富有激情、充满创造力、坚持技术驱动全面成长的团队, 团队平均年龄27岁,有在各自领域深耕多年的大牛, 也有刚刚毕业的小牛, 我们在工程化、编码质量、性能监控、微服务、交互体验等方向积极进行探索, 追求技术驱动产品落地的宗旨,打造完善的前端技术体系。
- 愿景: 成为最值得信任、最有影响力的前端团队
- 使命: 坚持客户体验第一, 为业务创造更多可能性
- 文化: 勇于承担、深入业务、群策群力、简单开放
Github:github.com/gfe-team
团队邮箱:[email protected]
作者:GFE团队
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。