javascript下条件编译的实现基于webpack的jsconditionalcompileloader插件

6次阅读

共计 1668 个字符,预计需要花费 5 分钟才能阅读完成。

条件编译,是指 用同一套代码和同样的编译构建过程,根据设置的条件,选择性地编译指定的代码,从而输出不同程序的过程。一般用在 C ++、Java、C# 这样的编译执行语言。对于 javascript,我们也可以使用基于 webpackjs-conditional-compile-loader插件实现类似的条件编译功能。

我们经常会遇到类似这样的需求:

  • 代码需要根据 运行环境 ,运行 不同的代码。比如,测试环境可以控制台输出一些信息,生产环境则不提示;同时又不希望输出的代码中存在判断环境的 if-else 代码使程序包体积增大。
  • 项目交付给 多个客户 使用,而某些客户会有一些 定制模块。这些定制模块只给特定用户使用,不希望也一起打包在不相干客户的程序包中,但也不希望给定制客户单独维护一个特殊项目而增加维护成本。

使用条件编译的方法,可以优雅地解决这样的问题,同时代码维护方便,发布的程序包中也不会有多余的代码存在。

插件原理

js-conditional-compile-loader 插件是一个 webpack 的 loader 插件,它会在 webpack 处理 js 代码之前,将 js 代码根据设置的条件进行修改,去掉当前条件下不需要的代码,保留需要的代码,从而实现条件编译的功能。

使用步骤

可参考这里的中文文档。

1. 安装

npm i -D js-conditional-compile-loader

2. 配置 webpack

在 rules 中为 js 文件添加 loader,作为第一步处理 js 文件,并配置编译条件。

module: {
    rules: [
        {
            test: /\.js$/,
            include: [resolve('src'), resolve('test')],
            use: [
                //step-2
                'babel-loader?cacheDirectory',
                //step-1
                {
                    loader: 'js-conditional-compile-loader',
                    options: {
                        isDebug: process.env.NODE_ENV === 'development', // optional, this is default
                        myFlag: process.env.ENV_COMPANY === 'ALI', // any name, used for /* IFTRUE_myFlag ...js code... FITRUE_myFlag */
                    }
                },
            ]
        },
        //other rules
    ]
}

3. 项目代码中使用

插件支持 IFDEBUG 和 IFTRUE 两个条件编译指令。用法是:在 js 代码的任意地方以 /*IFDEBUG/*IFTRUE_xxx开头,以 FIDEBUG*/FITRUE_xxx*/结尾,中间是被包裹的 js 代码。xxx 是在 webpack 中指定的条件属性名,如上面的 myFlag。

举个例子,我们用这样的源代码:

/* IFTRUE_forAlibaba */
var aliCode = require('./ali/alibaba-business.js')
aliCode.doSomething()
/* FITRUE_forAlibaba */

$state.go('win', {dir: menu.winId /*IFDEBUG , reload: true FIDEBUG*/})

当 webpack 中插件的 options 配置为 {isDebug: true, forAlibaba: true} 时,构建后输出的内容:

var aliCode = require('./ali/alibaba-business.js')
aliCode.doSomething()

$state.go('win', {dir: menu.winId, reload: true})

当 webpack 中插件的 options 配置为 {isDebug: false, forAlibaba: false} 时,构建后输出的内容为:

$state.go('win', {dir: menu.winId})

如此便实现了条件编译。结合命令参数关联到环境变量,可以用命令参数指定不同的编译条件。实际项目中可以按照你的需要尽情发挥。

这里是个完整项目的例子,可供参考。

正文完
 0