什么是Feature Flags

Feature Flags是一种允许控制线上功能开启或者关闭的方式,通常会采取配置文件的方式来控制。
例如,在开发组件库或者插件,经常会需要区分多种环境构建,从而实现:

  • 提供各种「体积」版本:全量版、精简版、基础版等;
  • 提供各种「环境」版本:web 版、nodejs 版等等;
  • 提供各种「规范」版本:esm 规范版本、cjs 规范版本、UMD 规范版本等等。

这种时候就可以使用feature flags

Vue 源码实现 Feature Flags

源码例子

  1. // packages/compiler-core/src/errors.ts
  2. export function defaultOnWarn(msg: CompilerError) {
  3. __DEV__ && console.warn(`[Vue warn] ${msg.message}`)
  4. }

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) { }

  1. 构建后 defaultOnWarn方法内的 console.warn语句就被 Tree Shaking 移除掉了。
  2. <a name="rgjyV"></a>
  3. ## 上手Feature Flags
  4. <a name="krL9H"></a>
  5. ### rollup实现
  6. ```javascript
  7. npm install @rollup/plugin-replace --save-dev
  1. import replace from '@rollup/plugin-replace';
  2. export default {
  3. input: 'index.js',
  4. output: {
  5. file: './dist/index.js',
  6. format: 'cjs'
  7. },
  8. plugins: [
  9. replace({
  10. __DEV__: true // 构建时将__DEV__替换成true
  11. })
  12. ]
  13. };

webpack实现

webpack 中自带了 DefinePlugin可以实现该功能,具体可以看 DefinePlugin 文档,下面看看 webpack.config.js配置:

  1. const path = require('path')
  2. const webpack = require('webpack')
  3. module.exports = {
  4. entry: './index.js',
  5. output: {
  6. path: path.resolve(__dirname, 'dist'),
  7. filename: 'index.js',
  8. },
  9. mode: 'production',
  10. plugins: [
  11. new webpack.DefinePlugin({
  12. __DEV__: JSON.stringify(true),
  13. })
  14. ],
  15. };

vite实现

Vite 默认也是支持自定义全局变量,实现该功能,可以看文档 define option

  1. /**
  2. * Define global variable replacements. 定义全局变量替换
  3. * Entries will be defined on `window` during dev and replaced during build.
  4. */
  5. define?: Record<string, any>
  1. export default defineConfig({
  2. plugins: [vue()],
  3. define: {
  4. __DEV__: true
  5. }
  6. })

总结三者使用

  • webpack: 使用 DefinePlugin
  • Rollup: 使用 @rollup/plugin-replace
  • Vite:默认配置,但可以使用define选项覆盖。

参考:
Vue3 如何实现瘦身?