我正在尝试将角度应用程序从gulp转换为webpack。在gulp中,我使用gulp-preprocess来替换html页面中的某些变量(例如,数据库名称),具体取决于NODE_ENV。使用webpack达到类似结果的最佳方法是什么?
我正在尝试将角度应用程序从gulp转换为webpack。在gulp中,我使用gulp-preprocess来替换html页面中的某些变量(例如,数据库名称),具体取决于NODE_ENV。使用webpack达到类似结果的最佳方法是什么?
Answers:
有两种基本方法可以实现此目的。
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
请注意,这只会按原样替换匹配项。这就是字符串具有其格式的原因。您可能有一个更复杂的结构,例如那里的一个对象,但您明白了。
new webpack.EnvironmentPlugin(['NODE_ENV'])
EnvironmentPlugin
在DefinePlugin
内部使用并映射环境值以通过它进行编码。Terser语法。
或者,您可以通过别名模块使用配置。从消费者方面来看,它看起来像这样:
var config = require('config');
配置本身可能如下所示:
resolve: {
alias: {
config: path.join(__dirname, 'config', process.env.NODE_ENV)
}
}
假设process.env.NODE_ENV
是development
。它将映射到./config/development.js
那时。它映射到的模块可以这样导出配置:
module.exports = {
testing: 'something',
...
};
JSON.stringify()
'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`
JSON.stringify('development')
可能不是真正有用。相反,JSON.stringify(someVariable)
可以相当!
NODE_ENV
这样做。如何设置取决于您的平台。
process.env.NODE_ENV
模式并且有效。
另一个选择,如果您只想使用cli界面,请使用define
webpack 的选择。我将以下脚本添加到我的package.json
:
"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"
所以我只需要跑步npm run build-production
。
我研究了关于如何设置特定于环境的变量的几个选项,并最终得出以下结论:
我目前有2个webpack配置:
webpack.production.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('production'),
'API_URL': JSON.stringify('http://localhost:8080/bands')
}
}),
webpack.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('development'),
'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
}
}),
在我的代码中,以这种(简要)的方式获取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")
})
使用ESLint,如果有no-undef
规则,则需要专门允许代码中的未定义变量。http://eslint.org/docs/rules/no-undef像这样:
/*global TWO*/
console.log('Running App version ' + TWO);
编辑2017年9月7日(特定于Create-React-App)
如果您不想进行过多配置,请查看Create-React-App:Create-React-App-添加自定义环境变量。CRA仍然在使用Webpack。
process.env
那么在webpack构建期间process.env.PORT
是否无法解决问题,undefined
这意味着您不能再从环境中覆盖端口了?
您可以在转译过程中直接使用EnvironmentPlugin
可用的webpack
访问任何环境变量。
您只需要在webpack.config.js
文件中声明插件:
var webpack = require('webpack');
module.exports = {
/* ... */
plugins = [
new webpack.EnvironmentPlugin(['NODE_ENV'])
]
};
请注意,您必须明确声明要使用的环境变量的名称。
要亲自添加到答案中,我更喜欢以下内容:
const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;
module.exports = {
...
plugins: [
new webpack.DefinePlugin({
process: {
env: {
NODE_ENV: prod? `"production"`: '"development"'
}
}
}),
...
]
};
使用此功能,不会出现时髦的env变量或跨平台问题(使用env vars)。您所要做的就是分别运行常规webpack
或webpack -p
开发或生产。
参考:Github问题
'process.env.NODE_ENV': JSON.stringify('production')
过度process: { env: { NODE_ENV: JSON.stringify('production') } }
。使用后者会覆盖过程对象,这可能会破坏与期望在过程对象上定义其他值的某些模块的兼容性。
由于我对thevangelist的上述帖子的“编辑” 未获批准,因此请发布其他信息。
如果要从package.json中选择值(如定义的版本号),然后通过Javascript中的DefinePlugin访问它。
{"version": "0.0.1"}
然后,将package.json导入各自的webpack.config中,使用import变量访问属性,然后在DefinePlugin中使用属性。
const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json
例如,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.
}
}),
在任何打字稿文件中访问此文件:
this.versionNumber = process.env.VERSION;
最聪明的方法是这样的:
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require("./package.json").version)
})
]
只是与@ zer0chain的答案类似的另一个答案。但是,有一个区别。
webpack -p
就足够了。它与:
--define process.env.NODE_ENV="production"
这和
// webpack.config.js
const webpack = require('webpack');
module.exports = {
//...
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
};
因此,您可能只需要在package.json
Node文件中添加以下内容:
{
"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",
...
}
}
仅来自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]
要添加一堆答案:
使用ExtendedDefinePlugin而不是DefinePlugin
npm install extended-define-webpack-plugin --save-dev.
ExtendedDefinePlugin的使用更加简单,并记录了:-) 链接
因为DefinePlugin 缺少好的文档,所以我想通过说它实际上像c#中的#DEFINE来提供帮助。
#if (DEBUG)
Console.WriteLine("Debugging is enabled.");
#endif
因此,如果您想了解DefinePlugin的工作原理,请阅读c##define文档。链接
我更喜欢将.env文件用于不同的环境。
env.dev
到根文件夹 env.prod
到.env和在代码中
采用
require('dotenv').config();
const API = process.env.API ## which will store the value from .env file
我发现以下解决方案最容易为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;
在Webpack中添加环境变量:
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
]
定义插件变量并将其添加到plugins
:
new webpack.DefinePlugin({
'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
}),
现在,当运行webpack命令时,将其env.NODE_ENV
作为参数传递:
webpack --env.NODE_ENV=development
// OR
webpack --env.NODE_ENV development
现在,您可以NODE_ENV
在代码中的任何位置访问变量。
这是一种对我有用的方法,它允许我通过重用json文件使环境变量保持DRY状态。
const webpack = require('webpack');
let config = require('./settings.json');
if (__PROD__) {
config = require('./settings-prod.json');
}
const envVars = {};
Object.keys(config).forEach((key) => {
envVars[key] = JSON.stringify(config[key]);
});
new webpack.DefinePlugin({
'process.env': envVars
}),
我不是...的忠实粉丝
new webpack.DefinePlugin({
'process.env': envVars
}),
...因为它不提供任何类型的安全性。相反,您最终会增加秘密内容,除非您向gitignore add♀️添加webpack,否则会有更好的解决方案。
基本上,使用此配置,一旦您编译了代码,所有进程环境变量将从整个代码中删除,就不会有单个process.env.VAR了,因为babel插件transform-inline-environment-variables
PS如果您不想结束由于存在很多不确定性,请确保在webpack调用babel-loader之前先调用env.js,这就是为什么它是webpack调用的第一件事。babel.config.js文件中的vars数组必须与env.js上的对象匹配。现在只有一件要做的事情。添加一个.env
文件,将所有env变量放在那里,该文件必须位于项目的根目录或随意将其添加到您想要的任何位置,只需确保在env.js文件上设置相同的位置并将其添加到gitignore
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
如果您想查看整个babel + webpack + ts,请听
https://github.com/EnetoJara/Node-typescript-babel-webpack.git
同样的逻辑适用于反应,其他所有💩
config
---webpack.js
---env.js
src
---source code world
.env
bunch of dotFiles
env.js
"use strict";
/***
I took the main idea from CRA, but mine is more cooler xD
*/
const {realpathSync, existsSync} = require('fs');
const {resolve, isAbsolute, delimiter} = require('path');
const NODE_ENV = process.env.NODE_ENV || "development";
const appDirectory = realpathSync(process.cwd());
if (typeof NODE_ENV !== "string") {
throw new Error("falle and stuff");
}
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
process.env.NODE_PATH = (process.env.NODE_PATH || "")
.split(delimiter)
.filter(folder => folder && isAbsolute(folder))
.map(folder => resolve(appDirectory, folder))
.join(delimiter);
const ENETO_APP = /^ENETO_APP_/i;
module.exports = (function () {
const raw = Object.keys ( process.env )
.filter ( key => ENETO_APP.test ( key ) )
.reduce ( ( env, key ) => {
env[ key ] = process.env[ key ];
return env;
},
{
BABEL_ENV: process.env.ENETO_APP_BABEL_ENV,
ENETO_APP_DB_NAME: process.env.ENETO_APP_DB_NAME,
ENETO_APP_DB_PASSWORD: process.env.ENETO_APP_DB_PASSWORD,
ENETO_APP_DB_USER: process.env.ENETO_APP_DB_USER,
GENERATE_SOURCEMAP: process.env.ENETO_APP_GENERATE_SOURCEMAP,
NODE_ENV: process.env.ENETO_APP_NODE_ENV,
PORT: process.env.ENETO_APP_PORT,
PUBLIC_URL: "/"
} );
const stringyField = {
"process.env": Object.keys(raw).reduce((env, key)=> {
env[key]=JSON.stringify(raw[key]);
return env;
},{}),
};
return {
raw, stringyField
}
})();
没有插件巨魔的webpack文件
"use strict";
require("core-js");
require("./env.js");
const path = require("path");
const nodeExternals = require("webpack-node-externals");
module.exports = env => {
return {
devtool: "source-map",
entry: path.join(__dirname, '../src/dev.ts'),
externals: [nodeExternals()],
module: {
rules: [
{
exclude: /node_modules/,
test: /\.ts$/,
use: [
{
loader: "babel-loader",
},
{
loader: "ts-loader"
}
],
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: "file-loader",
},
],
},
],
},
node: {
__dirname: false,
__filename: false,
},
optimization: {
splitChunks: {
automaticNameDelimiter: "_",
cacheGroups: {
vendor: {
chunks: "initial",
minChunks: 2,
name: "vendor",
test: /[\\/]node_modules[\\/]/,
},
},
},
},
output: {
chunkFilename: "main.chunk.js",
filename: "name-bundle.js",
libraryTarget: "commonjs2",
},
plugins: [],
resolve: {
extensions: ['.ts', '.js']
} ,
target: "node"
};
};
babel.config.js
module.exports = api => {
api.cache(() => process.env.NODE_ENV);
return {
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-transform-classes", {loose: true}],
["@babel/plugin-external-helpers"],
["@babel/plugin-transform-runtime"],
["@babel/plugin-transform-modules-commonjs"],
["transform-member-expression-literals"],
["transform-property-literals"],
["@babel/plugin-transform-reserved-words"],
["@babel/plugin-transform-property-mutators"],
["@babel/plugin-transform-arrow-functions"],
["@babel/plugin-transform-block-scoped-functions"],
[
"@babel/plugin-transform-async-to-generator",
{
method: "coroutine",
module: "bluebird",
},
],
["@babel/plugin-proposal-async-generator-functions"],
["@babel/plugin-transform-block-scoping"],
["@babel/plugin-transform-computed-properties"],
["@babel/plugin-transform-destructuring"],
["@babel/plugin-transform-duplicate-keys"],
["@babel/plugin-transform-for-of"],
["@babel/plugin-transform-function-name"],
["@babel/plugin-transform-literals"],
["@babel/plugin-transform-object-super"],
["@babel/plugin-transform-shorthand-properties"],
["@babel/plugin-transform-spread"],
["@babel/plugin-transform-template-literals"],
["@babel/plugin-transform-exponentiation-operator"],
["@babel/plugin-proposal-object-rest-spread"],
["@babel/plugin-proposal-do-expressions"],
["@babel/plugin-proposal-export-default-from"],
["@babel/plugin-proposal-export-namespace-from"],
["@babel/plugin-proposal-logical-assignment-operators"],
["@babel/plugin-proposal-throw-expressions"],
[
"transform-inline-environment-variables",
{
include: [
"ENETO_APP_PORT",
"ENETO_APP_NODE_ENV",
"ENETO_APP_BABEL_ENV",
"ENETO_APP_DB_NAME",
"ENETO_APP_DB_USER",
"ENETO_APP_DB_PASSWORD",
],
},
],
],
presets: [["@babel/preset-env",{
targets: {
node: "current",
esmodules: true
},
useBuiltIns: 'entry',
corejs: 2,
modules: "cjs"
}],"@babel/preset-typescript"],
};
};
我不知道为什么,但是没有人真正提到最简单的解决方案。这对我来说适用于nodejs和grunt。对于许多人来说,Webpack可能会使您感到困惑,您只需使用以下行:
process.env.NODE_ENV = 'production';
使用上述解决方案,您实际上不需要使用envify或webpack。有时,简单的硬编码解决方案可能对某些人有用。