从 Grunt 任务设置 NODE_ENV

Set NODE_ENV from Grunt task

我想在一个Grunt任务开始时设置NODE_ENV变量为developmentproduction,但看起来并没有我想的那么简单。

我喜欢这个的原因是我使用 grunt-webpack,它期望 NODE_ENV 正确设置为 "development" 或 "production"。但如果可能的话,我也想专门从 grunt 初始化我的任务。

我使用 grunt-shell and cross-env 模块创建了以下测试 Gruntfile:

function log(err, stdout, stderr, cb, e) {
    if (err) {
        cb(err);
        return;
    }

    console.log(process.env.NODE_ENV);
    console.log(stdout);
    cb();
}

module.exports = function(grunt) {

    grunt.initConfig({
        shell: {
            dev: {
                command : 'cross-env NODE_ENV="development"',
                options: {
                    callback: log
                }
            },
            dist: {
                command : 'cross-env NODE_ENV="production"',
                options: {
                    callback: log
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-shell');

};

log() 的第 6 行应该回显 process.env.NODE_ENV 的实际值,但它一直显示 undefined,即使我在节点控制台中手动检查它也是如此。

如果我从终端手动设置它,比如 set NODE_ENV=productionset 用于 Windows),到处都会回显值 production,正如我希望的那样到.

您的测试将无法运行,因为 grunt-shell runs a child_process 和您的回调 运行 在它结束后并在主进程下。
cross-env.

也会发生同样的事情

如果你想传递一个环境变量给grunt-shell,你应该使用options configuration according to the documentation.
例如:

grunt.initConfig({
    shell: {
        dev: {
            command : 'echo %NODE_ENV%', //windows syntax
            options: {
                execOptions: {
                    env: {
                        'NODE_ENV': 'dev'
                    }
                },
                callback: log
            }
        }
    }
});

这仍然会为 process.env.NODE_ENV 打印 undefined,但是 NODE_ENV 的值将在 stdout 中可用,因为 echo

附带说明一下,听起来您正在尝试 运行 一个进程 (grunt-shell),而 运行 是一个进程 (cross-env),这运行是一个进程(webpackgrunt-webpack)。
为什么不直接使用 cross-env example usage?它看起来非常接近您的需要。
或者您可以只在任务 config 本身中定义变量并丢失所有这些包装器。

LifeQuery 的回答对我找出问题所在有很大帮助。我首先意识到 webpack.DefinePlugin() 实际上 doesn't change anythingprocess.env.NODE_ENV 上(无论如何都为时已晚,因为它在所有加载器之后转换由 webpack 解析的代码)。

在此之后我创建了一个解决方案,它可以满足我的要求。这就是我的定制 Gruntfile.js 开始的方式:

'use strict';

const path = require('path');
const webpack = require('webpack');

module.exports = function (grunt) {

    // Setting the node environment based on the tasks's name or target
    let set_NODE_ENV = function () {
        const devTasks = ['webpack-dev-server', 'dev', 'hmr', 'watch'],
            devTargets = [':dev'],
            task = grunt.cli.tasks[0], // The name of the (first) task we initialized grunt with ('webpack-dev-server' if started 'grunt webpack-dev-server)
            target = ':'+grunt.option('target'),
            devEnv = (devTasks.indexOf(task) > -1 || devTargets.indexOf(target) > -1);

        process.env.NODE_ENV = devEnv ? 'development' : 'production';
    }();

    const webpackConfig = require('../assets/webpack.config');

    grunt.initConfig({
        // ...usual Gruntfile content
    });

};

我在设置 process.env.NODE_ENV 时创建了一个 grunt 任务名称和目标的白名单。由于它位于 grunt.initConfig() 之前,配置对象可以使用具有所需状态的 process.env.NODE_ENV

如果确定开始 webpack-dev-serverdevhmrwatch 任务或任何其他任务,它将 NODE_ENV 设置为 "development" :dev 目标的任务。