Angularアプリをgulpからwebpackに変換しようとしています。gulpでは、gulp-preprocessを使用して、HTMLページのいくつかの変数(データベース名など)をNODE_ENVに応じて置き換えます。Webpackで同様の結果を得る最良の方法は何ですか?
Angularアプリをgulpからwebpackに変換しようとしています。gulpでは、gulp-preprocessを使用して、HTMLページのいくつかの変数(データベース名など)をNODE_ENVに応じて置き換えます。Webpackで同様の結果を得る最良の方法は何ですか?
回答:
これを達成するには、2つの基本的な方法があります。
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
パターンを使用しており、機能します。
もう1つのオプションとして、CLIインターフェイスのみを使用するdefine
場合は、webpack のオプションを使用します。次のスクリプトをmyに追加します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 docsに例があります: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-Adding Custom Environment Variablesを確認してください。内部的には、CRAはとにかくWebpackを使用します。
process.env
ません。つまり、環境からポートを上書きできなくなりますか?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
devまたは製品用です。
参照: Githubの問題
'process.env.NODE_ENV': JSON.stringify('production')
しprocess: { env: { NODE_ENV: JSON.stringify('production') } }
ます。後者を使用すると、プロセスオブジェクトが上書きされ、プロセスオブジェクトの他の値が定義されることを期待する一部のモジュールとの互換性が失われる可能性があります。
伝道者による上記の投稿に対する私の編集が承認されなかったため、追加情報を投稿しました。
定義されたバージョン番号のようにpackage.jsonから値を選択し、JavaScript内のDefinePluginを介してそれにアクセスする場合。
{"version": "0.0.1"}
次に、インポートpackage.jsonそれぞれの内部webpack.configは、その後に属性を使用して、インポート変数を使用して属性にアクセスDefinePlugin。
const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json
たとえば、webpack.configの特定の構成は、DefinePluginに METADATAを使用しています。
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.
}
}),
typescriptファイル内でこれにアクセスします。
this.versionNumber = process.env.VERSION;
最も賢い方法は次のようになります:
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require("./package.json").version)
})
]
@ zer0chainの回答と同様の別の回答です。ただし、1つの違いがあります。
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]
回答の束に追加するには:
DefinePluginの代わりにExtendedDefinePluginを使用する
npm install extended-define-webpack-plugin --save-dev.
ExtendedDefinePluginの方がはるかに使いやすく、文書化されています:-) リンク
DefinePluginには優れたドキュメントがないため、実際にはc#の#DEFINEのように機能すると言って、手助けしたいと思います。
#if (DEBUG)
Console.WriteLine("Debugging is enabled.");
#endif
したがって、DefinePluginの仕組みを理解したい場合は、c##define doucmentationをお読みください。リンク
次の解決策は、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
で、コードのどこからでも変数にアクセスできます。
Webpack v4以降mode
、Webpack構成で設定するNODE_ENV
だけで(を介してDefinePlugin
)が設定されます。ドキュメントはこちら。
これは私にとってうまくいき、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にウェブパックを追加しない限り🤷♀️より良い解決策があります
基本的にこの構成では、コードをコンパイルすると、すべてのプロセス環境変数がコード全体から削除されtransform-inline-environment-variables
ます。終了したくない場合は、BabelプラグインPSのおかげで単一のprocess.env.VAR はありません。 undefinesがたくさんある場合は、webpackがbabel-loaderを呼び出す前にenv.jsを呼び出してください。これが、webpackが最初に呼び出す理由です。babel.config.jsファイル内の変数の配列は、env.js上のオブジェクトと一致する必要があります。今やるべきことは、刈り取り作業が1つだけです。.env
ファイルを追加し、そこにすべての環境変数を配置します。ファイルはプロジェクトのルートにあるか、必要な場所に自由に追加する必要があります。env.jsファイルに同じ場所を設定し、それを追加してください。 gitignore
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
全体のバベル+ Webpack + TSを表示したい場合は、heawから取得します
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を使用する必要はありません。単純なハードコードされたソリューションが一部の人に役立つ場合があります。