项目的开发和测试和生产环境一般都不是同一个,有时候就会产生需要前端项目需要根据不同的环境进行不同的配置的情况。比较经典的情况就是后端的接口 hostname 的问题。在开发环境的时候可能使用的是 dev.api.xx.com,测试环境需要使用 test.api.xx.com,而线上环境需要使用 api.xx.com。那么如何根据环境来动态的在文件中变更这个值而不用我们手动的在服务器上修改代码呢?我们可以利用 webpack module shim 的一些方法。

就拿上文中的例子,我们如何在不同环境编译的时候使用不同的 API 地址。webpack shim module 一共有好几种方法,我们来看下都可以怎么解决。

ProvidePlugin

ProvidePlugin 可以让变量直接在模块里加载而不需要使用 require 等方法。所以我们可以预先定义一些模块根据不同的环境装载不同的模块:

//development.js
module.exports = { baseUrl: 'http://dev.api.xx.com' };

//production.js
module.exports = { baseUrl: 'http://api.xx.com' };

//test.js
module.exports = { baseUrl: 'http://test.api.xx.com' };

//webpack.config.js
var webpack = require("webpack");
module.exports = {
    entry: "main.js",
    output: {path: "./", filename: "bundle.js"},
    plugins: [
        new webpack.ProvidePlugin({
            ENV: "./env/"+ (process.env.NODE_ENV || "development")
        })
    ]
};

然后我们在环境变量中定义 NODE_ENV 变量帮助 node 识别环境,例如:

//Windows
set NODE_ENV=test
//Linux or OSX
export NODE_ENV=test

这样在 webpack 编译的时候就能判别出是 test 环境使用 test 的环境变量了,我们直接在代码中使用 ENV.baseUrl 即可。

imports-loader

如果觉得使用 ProvidePlugin 略微麻烦的话我们也可以使用 imports-loader 来实现我们需要的功能。imports-loader 的作用是将变量注入到模块中,首先我们需要 npm install imports-loader 安装这个 loader。在 webpack.config.js 中我们进行如下操作:

var API = {
    test: 'http://test.api.xx.com',
    production: 'http://api.xx.com',
    development: 'http://dev.api.xx.com'
};

module.exports = {
    entry: "main.js",
    output: {path: "./", filename:"bundle.js"},
    module: {
        loaders: [
            {
                test: require.resolve('ajax'),
                loader: "imports-loader?baseUrl=>"+ JSON.stringify( API[ process.env.NODE_ENV || "development" ] )
            }
        ]
    }
};

这样我们在引用 ajax 这个模块的时候就会触发这个 laoder 将 baseUrl 这个变量注入到 ajax 模块中,所以我们可以直接在 ajax 模块中使用 baseUrl 变量即可。当前也不要忘记了和上面一样设置一下 NODE_ENV 环境变量哦!

其它

当然像 http://stackoverflow.com/ques... 这个问题的回答中直接使用 DefinePlugin 也是可以的。

参考资料:

03-05 22:38