在webpack中传递依赖于环境的变量

kpg*_*kpg 286 javascript webpack

我正在尝试将一个角度应用程序从gulp转换为webpack.在gulp我使用gulp-preprocess来替换html页面中的一些变量(例如数据库名称),具体取决于NODE_ENV.使用webpack实现类似结果的最佳方法是什么?

Juh*_*nen 408

有两种基本方法可以实现这一目标.

DefinePlugin

new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
Run Code Online (Sandbox Code Playgroud)

请注意,这只会"按原样"替换匹配项.这就是字符串的格式.你可以有一个更复杂的结构,比如那里有一个对象,但是你明白了.

EnvironmentPlugin

new webpack.EnvironmentPlugin(['NODE_ENV'])
Run Code Online (Sandbox Code Playgroud)

EnvironmentPluginDefinePlugin内部使用并将环境值映射到它的代码.更简洁的语法.

别号

或者,您可以通过别名模块使用配置.从消费者的角度来看,它看起来像这样:

var config = require('config');
Run Code Online (Sandbox Code Playgroud)

配置本身可能如下所示:

resolve: {
    alias: {
        config: path.join(__dirname, 'config', process.env.NODE_ENV)
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们说process.env.NODE_ENVdevelopment.它将映射到./config/development.js那时.它映射到的模块可以导出如下配置:

module.exports = {
    testing: 'something',
    ...
};
Run Code Online (Sandbox Code Playgroud)

  • 如果你正在使用ES2015,你也可以使用字符串插值 - "'process.env.NODE_ENV':\`"$ {process.env.NODE_ENV ||'development'}"\`` (4认同)
  • 感谢您指出它"按原样"替换匹配的事实.我挣扎了一段时间才弄清楚为什么我的代码抛出错误而这是因为我没有将值包装在`JSON.stringify()中 (3认同)
  • 不得不说,决心“把戏”是辉煌的。我将 resolve 用于硬编码的本地包,但从未想过将其用于外部输入。现在我可以动态传入外部配置目录。谢谢! (3认同)

zer*_*ain 106

只是另一种选择,如果你只想使用cli接口,只需使用definewebpack选项.我在我的脚本中添加以下脚本package.json:

"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"
Run Code Online (Sandbox Code Playgroud)

所以我只需要跑npm run build-production.

  • 对于webpack @ 2," - p"已经是--optimize-minimize --define process.env.NODE_ENV ="production"的快捷方式 (5认同)
  • 有这方面的文件吗?我不能谷歌--define :( (2认同)
  • 此处引用了CLI选项:https://webpack.github.io/docs/cli.html并链接到DefinePlugin https://webpack.github.io/docs/list-of-plugins.html#defineplugin (2认同)

the*_*ist 69

我研究了几个关于如何设置特定于环境的变量的选项,并最终得到了这个:

我目前有2个webpack配置:

webpack.production.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('production'),
    'API_URL': JSON.stringify('http://localhost:8080/bands')
  }
}),
Run Code Online (Sandbox Code Playgroud)

webpack.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('development'),
    'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
  }
}),
Run Code Online (Sandbox Code Playgroud)

在我的代码中,我以这种(简短的)方式获得API_URL的值:

const apiUrl = process.env.API_URL;

编辑2016年11月3日

Webpack文档有一个例子:https://webpack.js.org/plugins/define-plugin/#usage

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true),
    VERSION: JSON.stringify("5fa3b9"),
    BROWSER_SUPPORTS_HTML5: true,
    TWO: "1+1",
    "typeof window": JSON.stringify("object")
})
Run Code Online (Sandbox Code Playgroud)

使用ESLint,如果您有no-undef规则,则需要在代码中专门允许未定义的变量.http://eslint.org/docs/rules/no-undef是这样的:

/*global TWO*/
console.log('Running App version ' + TWO);
Run Code Online (Sandbox Code Playgroud)

编辑2017年9月7日(特定于Create-React-App)

如果您没有配置太多,请查看Create-React-App:Create-React-App - 添加自定义环境变量.引擎盖CRA无论如何都使用Webpack.

  • 您是否发现这阻止了在运行时传递的任何环境变量?如果你替换整个`process.env`然后不是`process.env.PORT`例如在webpack构建期间解析为`undefined`,这意味着你不能再从环境中覆盖端口了? (2认同)

Kuh*_*ess 22

您可以直接使用EnvironmentPluginavailable in webpack来在转换期间访问任何环境变量.

您只需在webpack.config.js文件中声明插件:

var webpack = require('webpack');

module.exports = {
    /* ... */
    plugins = [
        new webpack.EnvironmentPlugin(['NODE_ENV'])
    ]
};
Run Code Online (Sandbox Code Playgroud)

请注意,您必须明确声明要使用的环境变量的名称.

  • 这个用例在webpack文档中有一个例子.https://github.com/webpack/docs/wiki/list-of-plugins#environmentplugin (4认同)

and*_*uso 22

你可以通过任何命令行参数,无需额外的插件使用--env以来的WebPack 2:

webpack --config webpack.config.js --env.foo=bar
Run Code Online (Sandbox Code Playgroud)

使用webpack.config.js中的变量:

module.exports = function(env) {
    if (env.foo === 'bar') {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

资源

  • 请注意,[--env 语法](https://webpack.js.org/guides/environment-variables/) 似乎在 webpack 5 中的某个时刻发生了变化:`npx webpack --env goal=local` (6认同)

Gob*_*ord 13

要个人添加一堆答案,我更喜欢以下内容:

const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;

module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin({
      process: {
        env: {
          NODE_ENV: prod? `"production"`: '"development"'
        }
      }
    }),
    ...
  ]
};
Run Code Online (Sandbox Code Playgroud)

使用它没有任何时髦的env变量或跨平台问题(使用env vars).您所做的只是分别运行正常webpackwebpack -p开发或生产.

参考:Github问题


Abh*_*eet 13

由于thevangelist上述帖子中的编辑未获批准,因此发布了其他信息.

如果你想从package.json中选择值,就像定义的版本号一样,并通过Javascript中的DefinePlugin访问它.

{"version": "0.0.1"}
Run Code Online (Sandbox Code Playgroud)

然后,在各个webpack.config中导入package.json,使用import变量访问该属性,然后使用DefinePlugin中的属性.

const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json
Run Code Online (Sandbox Code Playgroud)

例如,webpack.config上的某些配置使用METADATA进行DefinePlugin:

const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
  host: HOST,
  port: PORT,
  ENV: ENV,
  HMR: HMR,
  RELEASE_VERSION:_version//Version attribute retrieved from package.json
});

new DefinePlugin({
        'ENV': JSON.stringify(METADATA.ENV),
        'HMR': METADATA.HMR,
        'process.env': {
          'ENV': JSON.stringify(METADATA.ENV),
          'NODE_ENV': JSON.stringify(METADATA.ENV),
          'HMR': METADATA.HMR,
          'VERSION': JSON.stringify(METADATA.RELEASE_VERSION)//Setting it for the Scripts usage.
        }
      }),
Run Code Online (Sandbox Code Playgroud)

在任何打字稿文件中访问它:

this.versionNumber = process.env.VERSION;
Run Code Online (Sandbox Code Playgroud)

最聪明的方式是这样的:

// webpack.config.js
plugins: [
    new webpack.DefinePlugin({
      VERSION: JSON.stringify(require("./package.json").version)
    })
  ]
Run Code Online (Sandbox Code Playgroud)

感谢Ross Allen


pro*_*sti 11

只是另一个答案类似于@ zer0chain的答案.但是,有一个区别.

设置webpack -p就足够了.

它与:

--define process.env.NODE_ENV="production"
Run Code Online (Sandbox Code Playgroud)

这与以下相同

// webpack.config.js
const webpack = require('webpack');

module.exports = {
  //...

  plugins:[
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ]
};
Run Code Online (Sandbox Code Playgroud)

所以在package.jsonNode文件中你可能只需要这样的东西:

{
  "name": "projectname",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "debug": "webpack -d",
    "production": "webpack -p"
  },
  "author": "prosti",
  "license": "ISC",
  "dependencies": {    
    "webpack": "^2.2.1",
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

来自DefinePlugin的一些提示:

DefinePlugin允许您创建可在编译时配置的全局常量.这对于允许开发构建和发布构建之间的不同行为非常有用.例如,您可以使用全局常量来确定是否进行日志记录; 也许您在开发构建中执行日志记录,但在发布版本中不执行.这就是DefinePlugin促成的那种场景.


这样你可以检查你是否输入 webpack --help

Config options:
  --config  Path to the config file
                         [string] [default: webpack.config.js or webpackfile.js]
  --env     Enviroment passed to the config, when it is a function

Basic options:
  --context    The root directory for resolving entry point and stats
                                       [string] [default: The current directory]
  --entry      The entry point                                          [string]
  --watch, -w  Watch the filesystem for changes                        [boolean]
  --debug      Switch loaders to debug mode                            [boolean]
  --devtool    Enable devtool for better debugging experience (Example:
               --devtool eval-cheap-module-source-map)                  [string]
  -d           shortcut for --debug --devtool eval-cheap-module-source-map
               --output-pathinfo                                       [boolean]
  -p           shortcut for --optimize-minimize --define
               process.env.NODE_ENV="production" 

                      [boolean]
  --progress   Print compilation progress in percentage                [boolean]
Run Code Online (Sandbox Code Playgroud)


rud*_*dra 5

我发现以下解决方案最容易为 Webpack 2 设置环境变量:

例如我们有一个 webpack 设置:

var webpack = require('webpack')

let webpackConfig = (env) => { // Passing envirmonment through
                                // function is important here
    return {
        entry: {
        // entries
        },

        output: {
        // outputs
        },

        plugins: [
        // plugins
        ],

        module: {
        // modules
        },

        resolve: {
        // resolves
        }

    }
};

module.exports = webpackConfig;
Run Code Online (Sandbox Code Playgroud)

在 Webpack 中添加环境变量:

plugins: [
    new webpack.EnvironmentPlugin({
       NODE_ENV: 'development',
       }),
]
Run Code Online (Sandbox Code Playgroud)

定义插件变量并将其添加到plugins

    new webpack.DefinePlugin({
        'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
    }),
Run Code Online (Sandbox Code Playgroud)

现在在运行 webpack 命令时,env.NODE_ENV作为参数传递:

webpack --env.NODE_ENV=development

// OR

webpack --env.NODE_ENV development
Run Code Online (Sandbox Code Playgroud)

现在您可以NODE_ENV在代码中的任何位置访问变量。