When developing component libraries or plug-ins, it is often necessary to differentiate between multiple environment builds to achieve:

  • Provide a variety of volume version: full version, compact version, basic version, etc.
  • Provide various environment versions: Web version, NodeJS version, and so on;
  • Various specification versions are available: ESM specification version, CJS specification version, UMD specification version, and so on.

So how can facilitate the implementation of the above functions? This scenario is suitable for Feature Flags, which dynamically sets the process of building code by turning on and off switches during the build process to achieve Tree Shaking.

Tree Shaking is a way to optimize volume by eliminating unused code from final files.

This article will start with the process of building Feature Flags used in the Vue source code (version 3.0.11), then learn through simple examples, and finally introduce the implementation in Rollup, WebPack, and Vite.

What is Feature Flags

Feature Flag(also known as Feature Toggle, Flip, etc.) is a way to enable or disable functions on the control line, usually in the form of a configuration file.

Fex.baidu.com/blog/2014/0…

This can be interpreted as adding a switch to code. When the switch is on, the logic will continue, otherwise it will not be executed. This code is usually represented by an if statement.

const flags = true;
const test = () = > flags && console.log('Hello Feature Flags');
Copy the code

Output is executed when flags is true, otherwise not. Now we want to control whether the log will be output by changing the flags value and leaving the test logic unchanged.

😺 can translate Feature Flag into Feature Flag.

Vue source code implementation Feature Flags

2.1 Usage Example

After the introduction of the feature flag in the previous section, you should have some idea about it. Here is an example of its use from the Vue3 source code:

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

__DEV__ is a Feature Flag. If the value of __DEV__ is true, subsequent logs will be output. Otherwise, none will be output. There are many other features in the Vue3 source code, such as:

  • __COMMIT__
  • __TEST__
  • __GLOBAL__
  • .

There are many, interested partners can look for Vue3 source.

2.2 How do I Define feature Labels

The above has just shown you how to use it in the source code, so let’s look at how the __DEV__ feature flags are defined. Vue3 uses the @rollup/replace dependency to replace the target string content in the file when building, such as __DEV__ to true when building a package for the development environment. Or take the above example code as an example:

// The local development environment __DEV__ is true, with the @rollup/replace dependency packaged as follows:
export function defaultOnWarn(msg: CompilerError) {
  true && console.warn(`[Vue warn] ${msg.message}`)}// In the build environment __DEV__ is false, packaged with the @rollup/replace dependency as follows:
export function defaultOnWarn(msg: CompilerError) {}Copy the code

The console.warn statement in the defaultOnWarn method is removed by Tree Shaking after the build.

3, Overhand Feature Flags

This section will implement three Feature Flags demos using rollup, Webpack, and Vite respectively. The core principle is that during the construction phase, the contents of the specified Feature Flags values are replaced with specific values, and then Tree Shaking is performed. The full code for the three examples can be viewed in the following repository:

First we create an index.js file and enter the following test contents:

// index.js 

const name = 'pingan8787';
const age = 18;

const featureFlags = () = > {
    console.warn(name)
    __DEV__ && console.log(name)
}

featureFlags();
Copy the code

The goal we need to achieve is that when the __DEV__ variable is true, the index.js package will not contain the __DEV__ && console.log(name) line of code. So let’s start by looking at how:

3.1 a rollup implementation

In rollup, we need to use the @rollup/replace package to replace text at build time, which we install first:

npm install @rollup/plugin-replace --save-dev
Copy the code

Then use it in rollup.config.js:

import replace from '@rollup/plugin-replace';

export default {
    input: 'index.js'.output: {
        file: './dist/index.js'.format: 'cjs'
    },
    plugins: [
        replace({
        	__DEV__: true}})];Copy the code

Next, through the rollup package command, you can see the following output:

const name = 'pingan8787';
const age = 18;

const featureFlags = () = > {
    console.warn(name)
    __DEV__ && console.log(name)
}

featureFlags();
Copy the code

If __DEV__ is true, it is not Tree Shaking. If __DEV__ is true, it is not Tree Shaking.

'use strict';

const name = 'pingan8787';

const featureFlags = () = > {
    console.warn(name);
};

featureFlags();
Copy the code

The __DEV__ && console.log(name) is removed. Following the same principle, look at the implementation of WebPack and Vite:

3.2 webpack implementation

DefinePlugin is shipped with Webpack to do this. See the DefinePlugin documentation and the webpack.config.js configuration below:

// 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),})]};Copy the code

Since this is using mode: ‘production’, the packaged code is compressed:

(() = >{const n="pingan8787";console.warn(n),console.log(n)})();
Copy the code

If __DEV__ is not present, console.log(n) is still present. Change __DEV__ to false.

console.warn("pingan8787");
Copy the code

This is the only one left, and the rest is not Shaking from Tree.

3.3 Vite implementation

Vite also supports custom global variables by default. For this function, see the document define Option. Create a simple Vite project with PNPM Create vite, remove the excess content, and add our test code to main.js:

import { createApp } from 'vue'
import App from './App.vue'

const name = 'pingan8787';
const age = 18;

const featureFlags = () = > {
    console.warn(name)
    __DEV__ && console.log(name)
}

featureFlags();

createApp(App).mount('#app')
Copy the code

And set __DEV__ in viet.config. js:

// vite.config.js

export default defineConfig({
  plugins: [vue()],
  define: {
    __DEV__: true}})Copy the code

Then execute PNPM build to build the project and you can see that the compressed code still has __DEV__ && console.log(name).

Next change __DEV__ to false and repackage, you can see that the code is Shaking by Tree:

Feature Flags rollup, WebPack, Vite

Four,

In this article, through simple examples and Vue3 source code, we introduced the concept and simple implementation of Feature Flags, and finally used rollup, Webpack and Vite respectively to achieve a Feature Flags.

In actual business development, we can design various Feature Flags to make the code better for Tree Shaking.