什么是Feature Flags
Feature Flags是一种允许控制线上功能开启或者关闭的方式,通常会采取配置文件的方式来控制。
例如,在开发组件库或者插件,经常会需要区分多种环境构建,从而实现:
- 提供各种「体积」版本:全量版、精简版、基础版等;
- 提供各种「环境」版本:web 版、nodejs 版等等;
- 提供各种「规范」版本:esm 规范版本、cjs 规范版本、UMD 规范版本等等。
这种时候就可以使用feature flags
Vue 源码实现 Feature Flags
源码例子
// packages/compiler-core/src/errors.ts
export function defaultOnWarn(msg: CompilerError) {
__DEV__ && console.warn(`[Vue warn] ${msg.message}`)
}
DEV就是一个Feature Flags
在 Vue3 源码中还存在很多其他特性标志,比如:
- COMMIT
- TEST
- GLOBAL
- …
Vue3如何定义Feature Flags
Vue3 中使用了 @rollup/replace 依赖,实现构建时,替换文件中目标字符串内容,比如构建开发环境的包的过程中,将 DEV替换为 true。 还是以上面示例代码为例介绍:``javascript // 本地开发环境 __DEV__ 为 true,经过 @rollup/replace 依赖打包后如下: export function defaultOnWarn(msg: CompilerError) { true && console.warn(
[Vue warn] ${msg.message}`) }
// 生成环境中 DEV 为 false,经过 @rollup/replace 依赖打包后如下: export function defaultOnWarn(msg: CompilerError) { }
构建后 defaultOnWarn方法内的 console.warn语句就被 Tree Shaking 移除掉了。
<a name="rgjyV"></a>
## 上手Feature Flags
<a name="krL9H"></a>
### rollup实现
```javascript
npm install @rollup/plugin-replace --save-dev
import replace from '@rollup/plugin-replace';
export default {
input: 'index.js',
output: {
file: './dist/index.js',
format: 'cjs'
},
plugins: [
replace({
__DEV__: true // 构建时将__DEV__替换成true
})
]
};
webpack实现
webpack 中自带了 DefinePlugin可以实现该功能,具体可以看 DefinePlugin 文档,下面看看 webpack.config.js配置:
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
mode: 'production',
plugins: [
new webpack.DefinePlugin({
__DEV__: JSON.stringify(true),
})
],
};
vite实现
Vite 默认也是支持自定义全局变量,实现该功能,可以看文档 define option。
/**
* Define global variable replacements. 定义全局变量替换
* Entries will be defined on `window` during dev and replaced during build.
*/
define?: Record<string, any>
export default defineConfig({
plugins: [vue()],
define: {
__DEV__: true
}
})
总结三者使用
- webpack: 使用 DefinePlugin
- Rollup: 使用 @rollup/plugin-replace
- Vite:默认配置,但可以使用define选项覆盖。
参考:
Vue3 如何实现瘦身?