背景
做项目的时候,不知大家是否会遇到如下场景:后端或者测试人员经常询问是否重新部署过前端页面;重新部署过后无法确定用户是否在使用最新页面,只得让他们多刷新几次;许久未维护的项目不清楚上次的部署时间。 为解决以上问题,我们可以将打包时间作为版本号并显示在页面上,让每个使用者清晰知道当前项目的打包时间。
思路
- 定义一个变量用于存储打包时间;
- 前端页面读取并显示这个变量的值;
- 每次打包时,使用当前时间覆写该变量的值;
第1,2点很好实现。第3点我们使用gulp
实现。gulp
是基于nodejs
的自动化构建工具,可以使用它在项目开发过程中自动执行任务。我们只需在执行打包脚本前,先执行覆写打包变量的脚本即可
实现
-
运行
node -v
,确定已安装nodejs
环境; -
全局安装
gulp
,这边以npm
安装为例。bash# 全局安装gulp npm install -g gulp-cli # 检查是否安装成功 gulp --verison
-
在项目中安装
gulp
相关依赖:npm install gulp gulp-clean ts-node date-fns fs-extra chalk --save-dev
。gulp
gulp-clean
为gulp依赖;ts-node
让我们可以在nodejs
下直接运行typescript
文件;date-fns
是一个日期处理库,此处用于格式化当前时间;fs-extra
为fs
包的功能补充包;chalk
用于在命令行中使用指定颜色显示文字信息。如果想了解更多信息,请至npmjs.com
下自行查阅相关资料。 -
在项目根目录下新建配置文件
gulpfile.js
,文件内容如下:jsconst path = require('path'); const projectDir = __dirname; const tsconfigPath = path.join(projectDir, 'scripts/gulp/tsconfig.json'); if (projectDir.includes(' ')) { console.error('Error: Cannot run the build tasks if the project is ' + 'located in a directory with spaces in between. Please rename your project directory.'); process.exit(1); } console.log('compiling...'); require('ts-node').register({ project: tsconfigPath }) // 引入typescript编写的文件 require('./scripts/gulp/gulpfile');
-
新建
scripts/gulp/gulpfile.ts
,内容如下:typescriptimport { task, series } from 'gulp'; import './tasks/index'; import { format } from 'date-fns'; import * as fs from 'fs-extra'; import * as path from 'path'; import * as chalk from 'chalk'; const appVersionPath = 'src/app'; task('set-app-version', (done) => { const version = `Ver ${format(new Date(Date.now()), 'YY.MM.DD.HHmm')}`; // eslint-disable-next-line no-console console.log(chalk.yellow(`当前版本号:${version}`)); fs.writeFileSync(path.join(appVersionPath, 'app-version.ts'), `export const APP_VERSION = '${version}';`); done(); }); task('init-site', execNodeTask('@angular/cli', 'ng', ['build', '--prod'])); task('build:site', series('set-app-version', 'init-site'));
在同级目录位置下新建
tsconfig.json
,内容如下:json{ "compilerOptions": { "experimentalDecorators": true, "noUnusedParameters": true, "noUnusedLocals": true, "lib": ["es2015", "dom"], "module": "commonjs", "moduleResolution": "node", "outDir": "../../dist", "strictNullChecks": true, "strictFunctionTypes": true, "noImplicitThis": true, "noEmitOnError": true, "noImplicitAny": true, "target": "es5", "types": ["node"], "baseUrl": "." }, "files": ["gulpfile.ts"] }
如上所示我们在
gulpfile.ts
下新建了build:site
任务,里面包含两个子任务:set-app-version
和init-site
,分别对应设置程序版本号(此处使用打包时间为程序版本号,格式为:Ver 23.08.12.2145
)和angular
打包任务。-
set-app-version
(设置版本号):将当前日期信息作为版本作为版本信息写入src/app/app-version.ts
文件,最终app-version.ts
文件内容如下:typescriptexport const APP_VERSION = 'Ver 23.08.13.1354';
最终页面组件只需导入
APP_VERSION
变量并显示在合适位置即可。 -
init-site
,使用execNodeTask
方法调用对应框架(此处调用angular
框架的ng build
命令)的打包方法即可。execNodeTask
函数实现如下:typescriptimport * as child_process from 'child_process'; import * as gulp from 'gulp'; import * as os from 'os'; /** * 运行指定的npm包命令 * @param packageName npm包名 * @param executable 可执行命令 * @param args 参数 * @param env 环境变量 */ export function execNodeTask(packageName: string, executable: string | string[], args?: string[], env: any = {}): gulp.TaskFunction { if (!args) { // tslint:disable-next-line:no-parameter-reassignment args = executable as string[]; // tslint:disable-next-line:no-parameter-reassignment executable = ''; } // tslint:disable-next-line:no-any return (done: (err: any) => void) => { // tslint:disable-next-line:no-any resolveBin(packageName, { executable: executable }, (err: any, binPath: string) => { if (err) { done(err); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion execTask('node', ['--max_old_space_size=8000', binPath].concat(args!), env)(done); } }); }; } export function execTask(binPath: string, args: string[], env: any = {}): any { return (done: (err?: string) => void) => { // https://github.com/angular/angular-cli/issues/10922 // tslint:disable-next-line:no-any (process.stdout as any)._handle.setBlocking(true); // tslint:disable-next-line:no-any (process.stdout as any)._handle.setBlocking(true); const bin = os.platform() === 'win32' && binPath === 'ng' ? `${binPath}.cmd` : binPath; const childProcess = child_process.spawn(bin, args, { env: { ...process.env, ...env }, cwd: process.cwd(), stdio: 'inherit' }); childProcess.on('close', (code: number) => { // tslint:disable-next-line:triple-equals code != 0 ? done(`Process failed with code ${code}`) : done(); }); }; }
-
在
package.json
下新建build
脚本,内容如下:json"scripts":{ ... "build": "gulp build:site", ... }
后续每次打包只需执行
npm run build
脚本,即可实时更新版本号(打包时间)并同步更新页面了。
-