webpack配置如何根据环境更改插件

8

你好,是否可以根据环境在webpack配置中创建插件?

plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.LoaderOptionsPlugin({
            debug: true
        }),
        new CopyWebpackPlugin([
            {from: 'src/www/'}
        ])
        // new BundleAnalyzerPlugin(),
        // new CompressionPlugin({
        //     algorithm: 'gzip',
        //     test: /\.js$|\.css$|\.html$/
        // }),
        // new UglifyJsPlugin({
        //     test: /\.js(\?.*)?$/i
        // })
    ]

只有在我使用 NODE_ENV=production 打包时,才应该使用被注释的部分。

提前感谢。


1
你可以创建多个Webpack配置文件,每个文件对应一个你想要支持的环境。 - Hyyan Abo Fakher
你可以为每个环境拥有一个配置文件。 - Kris D. J.
5个回答

12

根据您的要求,在环境为生产时添加插件,否则返回false,并根据布尔值过滤数组,但更好的做法是为不同的环境创建不同的文件,这样会更加简洁。

plugins: [
    new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.LoaderOptionsPlugin({
            debug: true
        }),
        new CopyWebpackPlugin([
            {from: 'src/www/'}
        ])
        NODE_ENV==='production' ? new BundleAnalyzerPlugin() : false,
        NODE_ENV==='production' ? new CompressionPlugin({
             algorithm: 'gzip',
             test: /\.js$|\.css$|\.html$/
        }) : false,
        NODE_ENV==='production' ?  new UglifyJsPlugin({
             test: /\.js(\?.*)?$/i
        }) : false
 ].filter(Boolean)

当我运行这个程序时,出现了错误 NODE_ENV 未定义 - Felix
在您的 package.json 文件中应该有一个脚本,用于设置 NODE_ENV 变量,类似于以下内容:"scripts": { "build": "NODE_ENV=production webpack --config webpack/prod.config.js", } - Joseph
我肯定是这样运行的:"build": "node_modules/.bin/cross-env NODE_ENV=production NODE_OPTIONS=--max_old_space_size=4096 webpack --config webpack.config.js --optimize-minimize --optimize-dedupe",但终端返回NODE_ENV未定义。 - Felix
请使用process.env.NODE_ENV替换NODE_ENV检查,例如process.env.NODE_ENV==='production' ? new BundleAnalyzerPlugin() : false。 - Joseph
太好了!这对我有用,但答案不完整。您应该在 package.json 的 “scripts” 部分中添加类似于以下内容的东西:"build": "cross-env NODE_ENV=production webpack --mode production --hide-modules --progress"。并且在您的 webpack.config.json 中添加类似于以下内容的东西:const isProduction = process.env.NODE_ENV === "production"或只需使用 process.env.NODE_ENV 即可。 - borkafight

2
使用您的示例,我更喜欢以下方式:
plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.LoaderOptionsPlugin({
        debug: true
    }),
    new CopyWebpackPlugin([
        {from: 'src/www/'}
    ])
    NODE_ENV === 'production' && new BundleAnalyzerPlugin(),
    NODE_ENV === 'production' && new CompressionPlugin({
        algorithm: 'gzip',
        test: /\.js$|\.css$|\.html$/
    }),
    NODE_ENV === 'production' && new UglifyJsPlugin({
        test: /\.js(\?.*)?$/i
    })
].filter(n => n)

或者如果您更喜欢ES5:

plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.LoaderOptionsPlugin({
        debug: true
    }),
    new CopyWebpackPlugin([
        {from: 'src/www/'}
    ])
    NODE_ENV === 'production' && new BundleAnalyzerPlugin(),
    NODE_ENV === 'production' && new CompressionPlugin({
        algorithm: 'gzip',
        test: /\.js$|\.css$|\.html$/
    }),
    NODE_ENV === 'production' && new UglifyJsPlugin({
        test: /\.js(\?.*)?$/i
    })
].filter(function (plugin) { return plugin; })

这段代码的作用是将一个条件判断 (NODE_ENV === 'production') 添加到数组中,这只是告诉JS编译器将false或右侧代码写入该数组。另一方面,filter函数仅表示过滤掉值为 false 或类似 false 的内容。

假设我们在 NODE_ENV='development' 环境下,我们的插件将如下所示:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, false, false, false].filter(...)

在过滤器完成其工作后,我们得到了如下结果:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin]

如果我们现在假设 NODE_ENV = 'production',我们的插件将如下所示:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, BundleAnalyzerPlugin, CompressionPlugin, UglifyJsPlugin].filter(...)

在筛选功能完成后,我们得到了这个结果:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, BundleAnalyzerPlugin, CompressionPlugin, UglifyJsPlugin]

1
我会选择使用rest操作符以获得更清晰的外观:
const isDev = process.env.NODE_ENV !== 'production';

const plugins = isDev ? [
  new ForkTsCheckerWebpackPlugin(),
] : [
  new BundleAnalyzerPlugin({
    openAnalyzer: process.env.OPEN_ANALYZER === 'true',
  }),
  new webpack.EnvironmentPlugin({
    NODE_ENV: 'production',
    DEBUG_PROD: false,
    START_MINIMIZED: false,
  }),
]

然后在配置文件中:

plugins: [
     ...plugins,
     new CopyWebpackPlugin({
      patterns: [
        {
          from: 'source',
          to: 'destination',
        },
      ],
    }),
  ],

现在我们不需要那些讨厌的比较了。


1

这是我只在生产环境中使用插件的方法。

// Load this plugin only when running webpack in a production environment
if (process.env.NODE_ENV == 'production') {
  module.exports.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerPort: 4000
    }),
  );
}

1
你可以针对每个环境拥有一个配置文件。
webpack
├── base.config.js
└── prod.config.js

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

module.exports = {
  plugins: [
    new webpack.EnvironmentPlugin([
      'NODE_ENV',
    ]),
  ],
};

// prod.config.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const baseConfig = require('./base.config.js');

module.exports = merge(baseConfig, {
  ....
  plugins: [
    // Minify JS
    new UglifyJsPlugin({
      sourceMap: false,
      compress: true,
    })
  ],
});

然后在您的 package.json 文件中。
"scripts": {
  "build": "NODE_ENV=production webpack --config webpack/prod.config.js",
  "start": "NODE_ENV=development webpack-dev-server --config webpack/dev.config.js"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接