前言
背景
同一份代码包含多个产品实现,核心逻辑相同,只是ui、接口、少量逻辑有差异,通过不同打包命令打包对应产品的代码
旧的实现
通过对应打包命令,注入相应环境变量,获取变量通过js逻辑展示对应资源或逻辑。这种方式虽然能够实现对应产品的展示和逻辑,但是存在多余逻辑和资源。
优化
优化思路
在编译阶段注入环境变量,通过模板语法输出对应产品逻辑和资源,打包之后的代码就很纯净。
优化方案
自定义loader,使用ejs引擎批处理js文件
vue.config.js
chainWebpack: (config) => {
config.resolveLoader.alias.set('my-loader', path.resolve(__dirname, 'myLoader.js'))
config.module.rule('js')
.use('my-loader')
.loader('my-loader')
.options({
ENV : process.env.VUE_APP_EVN,
PRODUCT : process.env.VUE_APP_PRODUCT
})
.end()
}
my-loader.js
'use strict' const loaderUtils = require('loader-utils'); const ejs = require('ejs'); module.exports = function (source) { var options = loaderUtils.getOptions(this) || {} return ejs.render(source, options) }
问题
vue cli3默认添加了cache-loader来提升打包的效率,这也造成在切换产品打包时并不会并不会触发重新打包
解决
- 简单粗暴,每次编译之前删除 node_modules\.cache\babel-loader 目录 , /doge
cross-env rimraf node_module/.cache/babel-loader && vue-cli-service build
- js文件不使用 cache-loader
config.module.rule('js').uses.delete('cache-loader')
这两种方式虽然可以解决问题,但是缺点明显,有点捡了芝麻丢了西瓜的感觉。而且,如果在不切换产品的时候使用cache提升打包速度,显然上诉的做法是无法实现的。最求完美的我们继续探索第3种方法:
- 通过cacheKey判断是否命中缓存文件
config.module.rule('js') .use('cache-loader') .loader('cache-loader') .options({ cacheIdentifier : `${process.env.VUE_APP_PRODUCT}:${process.env.VUE_APP_EVN}` // cacheKey : (options, request) => { // return `${process.env.VUE_APP_PRODUCT}:${process.env.VUE_APP_EVN}:${options}`; // } })