Edited at

Webpack内ではprocess.env.NODE_ENVが使えないので

More than 1 year has passed since last update.

困ったねって話。

正式表題「webpack.config.jsの中ではprocess.env.NODE_ENVが未定義なので困ったね」


TL;DR


package.json

{

"scripts": {
"develop": "webpack",
"production": "webpack --env.production"
}
}


webpack.config.js

module.exports = env => {

const path = (env && env.production) ? './prod' : './dist'
return {
entry: {
app: './src/index.js'
},
output: {
filename: 'bundle.js',
path: path
}
}
}


使えないの?

使えないんだってさ、初めて知った。知ってた?


Technically, NODE_ENV is a system environment variable that Node.js exposes into running scripts. It is used by convention to determine dev-vs-prod behavior by server tools, build scripts, and client-side libraries. Contrary to expectations, process.env.NODE_ENV is not set to "production" within the build script webpack.config.js, see #2537. Thus, conditionals like process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js' within webpack configurations do not work as expected.

-- https://webpack.js.org/guides/production/#specify-the-environment



困る


package.json

{

"scripts": {
"develop": "webpack",
"production": "webpack -p"
}
}


webpack.config.js

module.exports = {

entry: {
app: './src/index.js'
},
output: {
filename: 'bundle.js',
path: process.env.NODE_ENV === 'production' ? './prod' : './dist'
// ↑常にfalse(undef)なので、`./prod`フォルダに出力されない
}
}

webpack.config.jsを使いまわしつつ出力フォルダを変えたり、Uglify適用させたりしたかったのに使えないとか言われちゃ困るわけですよー。


envオプション

WebpackをCLIから呼び出す際のコマンドオプション一覧に「envオプション」というのがあり、これが一番容易そうだった。以下引用。

Invocation
Resulting environment

webpack --env prod
"prod"

webpack --env.prod
{ prod: true }

webpack --env.prod=1
{ prod: 1 }

webpack --env.prod=foo
{ prod: "foo" }

webpack --env.prod --env.min
{ prod: true, min: true }

webpack --env.prod --env min
[{ prod: true }, "min"]

webpack --env.prod=foo --env.prod=bar
{prod: [ "foo", "bar" ]}

単純なbool判定がしたいだけなので、公開版出力用のnpm-scriptに--env.productionオプションを足すだけで良さそう。

って、webpack.config.jsに引数とれるような関数書く場面あったっけ?


function within webpack.config.js

webpack.config.jsmodule.exportの対象として「設定オブジェクトを返す関数」もとれるらしい。そりゃそうか。

ということで、冒頭のように


webpack.config.js

module.exports = env => {

const path = (env && env.production) ? './prod' : './dist'
return {
entry: {
app: './src/index.js'
},
output: {
filename: 'bundle.js',
path: path
}
}
}

とやってやることで、無事に目的を達成しましたとさ。めでたし。


補足


  • 実際に私が実装した際は、先に開発用設定のオブジェクトを作っておいてから、prod判定後に公開用設定をconcatしたものをreturnしましたので、上記一連のサンプルコードよりはだいぶ纏まって読めます。多分。[参考]

  • 第二引数をとるとargvが返ってくるので、if(argv['p']){}とか書けたりもします。この辺りは好みかと思いましたので割愛。


総括

ドキュメントを読もう。


編集履歴


22 Jan. 2018

if条件文にenv&&追加
envオプションを1つでも使っていないとenvがundef吐くので怒られる懸念があった