通过 DefinePlugin 在 Webpack 中传递 NODE_ENV 值

13
我正在尝试使用webpackDefinePluginNODE_ENV值注入到我的代码中。我检查过一个几乎相同的问题,但仍无法使其正常工作。
具体来说,这是我的设置。
package.json中:
"scripts": {
    "build": "rimraf dist && cross-env NODE_ENV=production webpack",
    "dev": "cross-env NODE_ENV=development && node webpack-dev-server.js"
},
webpack.config.js文件中:
"use strict";

/* requiring the modules */
const webpack = require("webpack");
const path = require("path");

/* defining the source and distribution paths */
const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");

const DEVELOPMENT = process.env.NODE_ENV === "development";
const PRODUCTION = process.env.NODE_ENV === "production";
// const PRODUCTION = !!process.argv.find((element) => element === '--production');
// const DEVELOPMENT = !!process.argv.find((element) => element === '--development');


/* defining the entries*/
const productionEntries = {
    home: SRC_DIR + "/_home.js",
    about: SRC_DIR + "/_about.js",
};
const developmentEntries = Object.assign({}, productionEntries, {webpackDevServer: ["webpack/hot/dev-server", "webpack-dev-server/client?http://localhost:8080"]});
const entries = PRODUCTION ? productionEntries : developmentEntries;


/* defining the output */
const output = {
    filename: "[name].js",
    path: DIST_DIR,
    publicPath: "/dist/",
    pathinfo: true,
    library: "MyLibraryName"
};


/* defining the plugins */
const plugins = PRODUCTION
    ? [
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.AggressiveMergingPlugin(),
        new webpack.optimize.UglifyJsPlugin({comments: false}),
    ]
    :  [
        new webpack.HotModuleReplacementPlugin(),
    ];

plugins.push(
    new webpack.optimize.CommonsChunkPlugin({name: "vendor.bundle", minChunks: 2}),
    new webpack.DefinePlugin({
        PRODUCTION: PRODUCTION,
        DEVELOPMENT: DEVELOPMENT,
    })
);


/* defining the modules -> rules -> loaders */
const modules = {
    rules:
        [
            {
                test: /\.(js|jsx)$/,
                include: SRC_DIR,
                exclude: /node_modules/,
                loader: "babel-loader",
                options:
                    {
                        presets: ["react", ["es2015", {modules: false}], "stage-2"]
                    }
            }
        ]
};



/* building the webpack config object */
const config = {
    entry: entries,
    output: output,
    module: modules,
    plugins: plugins,
    devtool: "source-map",
    target: "web",
    stats: "verbose"
};

/* exporting the webpack config */
module.exports = config;

最后,在_about.js中我有以下内容:

// output after using: npm run dev
console.log(process.env.NODE_ENV); // prints undefined
console.log(PRODUCTION); // prints false
console.log(DEVELOPMENT); // prints false

if (module.hot) {
    module.hot.accept();
}

问题:

  • npm run dev 成功运行(即服务器启动并且插件和入口已充分选择),我不明白为什么console.log(DEVELOPMENT)的输出是false,以及为什么console.log(process.env.NODE_ENV)打印了undefined
  • webpack.config.js内执行的条件检查中,正确选择了NODE_ENV值,否则插件、入口和开发服务器将无法工作。然而,我无法使用DefinePlugin将该值传递到_about.js中。
  • 我还尝试了EnvironmentPlugin,但结果相同。

我的问题: 您能帮助我理解出现问题的地方吗?


编辑1:

我尝试了以下方法,但没有任何改进:

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(PRODUCTION),
    DEVELOPMENT: JSON.stringify(DEVELOPMENT)
})

我正在 Windows 10 上运行 node.js


编辑2:

尝试过:

const DEVELOPMENT = process.env.NODE_ENV === "development";
const PRODUCTION = process.env.NODE_ENV === "production";

// with this inside plugins:
new webpack.DefinePlugin({
    "process.env.PRODUCTION": JSON.stringify(PRODUCTION),
    "process.env.DEVELOPMENT": JSON.stringify(DEVELOPMENT)
})

并且(使用npm run dev)我获得以下输出:

console.log(process.env.PRODUCTION); // false
console.log(process.env.DEVELOPMENT); // false
console.log(process.env.NODE_ENV); // undefined
console.log(PRODUCTION); // Uncaught ReferenceError: PRODUCTION is not defined
console.log(DEVELOPMENT); // Uncaught ReferenceError: DEVELOPMENT is not defined
很遗憾没有任何改进。

编辑3:

我的devDependencies是:


"devDependencies": {
    "babel-core": "^6.21.0",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-react": "^6.16.0",
    "babel-preset-stage-2": "^6.18.0",
    "cross-env": "^3.1.4",
    "rimraf": "^2.5.4",
    "webpack": "^2.2.0-rc.4",
    "webpack-dev-server": "^2.2.0-rc.0"
}

编辑4:(已解决)

@Cleiton发现了问题。 它与使用cross-env构建npm脚本有关。 请参见下面的完整答案。

2个回答

19

问题出在你错误地使用了 cross-env。它只会改变当前环境变量的上下文,因此当你使用 '&&' 运行 webpack 时,它已经消失了,而 webpack 没有看到任何东西。

所以你必须这样写:

"scripts": {
    "build": "rimraf dist && cross-env NODE_ENV=production webpack",
    "dev": "cross-env NODE_ENV=development node webpack-dev-server.js"
},

请注意,您已经正确地编写了“build”脚本。

另一个问题是,如果您想在代码库中引用“process.env.PRODUCTION”,则应编写:

   new webpack.DefinePlugin({
        "process.env.PRODUCTION": JSON.stringify(PRODUCTION),
        "proccess.env.DEVELOPMENT": JSON.stringify(DEVELOPMENT),
    });

谢谢@Cleiton。我正在尝试中。几分钟后会提供反馈。 - Mihai
我尝试了你的答案,在 _about.js 中,console.log(process.env.PRODUCTION)console.log(process.env.DEVELOPMENT) 的输出结果是 false。而 console.log(PRODUCTION)console.log(DEVELOPMENT) 则会输出 Uncaught ReferenceError: PRODUCTION is not defined - Mihai
谢谢 @Cleiton。迫不及待要去看看! - Mihai
太棒了!谢谢@Cleiton。它起作用了!我简直不敢相信问题是什么。你让我的一天!只要允许,我会将您的帖子标记为已接受的答案。 - Mihai
将来的搜索中,这是来自webpack的文档 - Rafael Moreno

3
DefinePlugin期望接收字符串,因此你需要对传递给它的任何值进行JSON.stringify()处理。
new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(PRODUCTION),
    DEVELOPMENT: JSON.stringify(DEVELOPMENT)
})

谢谢,@Soviut。我已经尝试过了,但没有改善。我将编辑我的问题,以融入你的答案。 - Mihai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接