Webpack 如何构建生产代码以及如何使用它

Webpack how to build production code and how to use it

我是 webpack 的新手,我发现在生产构建中我们可以减少整体代码的大小。 目前 webpack 构建大约 8MB 的文件和 main.js 大约 5MB。 如何减少生产构建中的代码大小? 我从互联网上找到了一个示例 webpack 配置文件,并为我的应用程序进行了配置,然后我 运行 npm run build 开始构建并在 ./dist/ 目录中生成了一些文件。

  1. 这些文件仍然很重(与开发版相同)
  2. 如何使用这些文件?目前我正在使用 webpack-dev-server 来 运行 应用程序。

package.json 文件

{
  "name": "MyAPP",
  "version": "0.1.0",
  "description": "",
  "main": "src/server/server.js",
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [
  ],
  "author": "Iam",
  "license": "MIT",
  "homepage": "http://example.com",
  "scripts": {
    "test": "",
    "start": "babel-node src/server/bin/server",
    "build": "rimraf dist && NODE_ENV=production webpack --config ./webpack.production.config.js --progress --profile --colors"
  },
  "dependencies": {
    "scripts" : "", ...
  },
  "devDependencies": {
    "scripts" : "", ...
  }
}

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "src/frontend";
var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');

module.exports = {
  devtool: 'eval-source-map',
  entry: [
    'webpack-hot-middleware/client?reload=true',
    path.join(__dirname, public_dir , 'main.js')
  ],
  output: {
    path: path.join(__dirname, '/dist/'),
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [
    plugins
  ],
  module: {
    loaders: [loaders]
  }
};

webpack.production.config.js

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var public_dir = "src/frontend";
var ModernizrWebpackPlugin = require('modernizr-webpack-plugin');
console.log(path.join(__dirname, 'src/frontend' , 'index.html'));

module.exports = {
  devtool: 'eval-source-map',
  entry: [
    'webpack-hot-middleware/client?reload=true',
    path.join(__dirname, 'src/frontend' , 'main.js')
  ],
  output: {
    path: path.join(__dirname, '/dist/'),
    filename: '[name].js',
    publicPath: '/'
  },
  plugins: [plugins],
  resolve: {
    root: [path.resolve('./src/frontend/utils'), path.resolve('./src/frontend')],
    extensions: ['', '.js', '.css']
  },

  module: {
    loaders: [loaders]
  }
};

使用这些插件来优化您的生产构建:

  new webpack.optimize.CommonsChunkPlugin('common'),
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.UglifyJsPlugin(),
  new webpack.optimize.AggressiveMergingPlugin()

I recently came to know about compression-webpack-plugin which gzips your output bundle to reduce its size. Add this as well in the above listed plugins list to further optimize your production code.

new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0.8
})

不建议将服务器端动态 gzip 压缩用于提供静态 client-side 文件,因为 CPU 使用率很高。

您可以按照@Vikramaditya 的建议添加插件。 然后生成生产版本。您必须 运行 命令

NODE_ENV=production webpack --config ./webpack.production.config.js

如果使用 babel,您还需要在上述命令前添加 BABEL_ENV=node

在观察了这个问题的观众人数后,我决定总结 Vikramaditya 和 Sandeep 的回答。

要构建生产代码,您必须创建的第一件事是使用优化包的生产配置,

  new webpack.optimize.CommonsChunkPlugin('common.js'),
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.UglifyJsPlugin(),
  new webpack.optimize.AggressiveMergingPlugin()

然后在 package.json 文件中,您可以使用此生产配置配置构建过程

"scripts": {
    "build": "NODE_ENV=production webpack --config ./webpack.production.config.js"
},

现在您必须运行以下命令来启动构建

npm run build

根据我的生产构建配置,webpack 会将源构建到 ./dist 目录。

现在您的 UI 代码将在 ./dist/ 目录中可用。配置您的服务器以将这些文件作为静态资产提供。完成!

您可以使用 argv npm 模块(通过 运行 npm install argv --save 安装)在您的 webpack.config.js 文件和生产你使用 -p 标志 "build": "webpack -p", 你可以在 webpack.config.js 如下文件

plugins: [
    new webpack.DefinePlugin({
        'process.env':{
            'NODE_ENV': argv.p ? JSON.stringify('production') : JSON.stringify('development')
        }
    })
]

就是这样。

这对你有帮助。

plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        // This has effect on the react lib size
        'NODE_ENV': JSON.stringify('production'),
      }
    }),
    new ExtractTextPlugin("bundle.css", {allChunks: false}),
    new webpack.optimize.AggressiveMergingPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      mangle: true,
      compress: {
        warnings: false, // Suppress uglification warnings
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true
      },
      output: {
        comments: false,
      },
      exclude: [/\.min\.js$/gi] // skip pre-minified libs
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), //
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0
    })
  ],

除了 Gilson PJ 回答:

 new webpack.optimize.CommonsChunkPlugin('common.js'),
 new webpack.optimize.DedupePlugin(),
 new webpack.optimize.UglifyJsPlugin(),
 new webpack.optimize.AggressiveMergingPlugin()

"scripts": {
    "build": "NODE_ENV=production webpack -p --config ./webpack.production.config.js"
},

因为它会尝试两次丑化您的代码。有关详细信息,请参阅 https://webpack.github.io/docs/cli.html#production-shortcut-p

您可以通过从插件数组中删除 UglifyJsPlugin 或添加 OccurrenceOrderPlugin 并删除“-p”标志来解决此问题。所以一种可能的解决方案是

 new webpack.optimize.CommonsChunkPlugin('common.js'),
 new webpack.optimize.DedupePlugin(),
 new webpack.optimize.UglifyJsPlugin(),
 new webpack.optimize.OccurrenceOrderPlugin(),
 new webpack.optimize.AggressiveMergingPlugin()

"scripts": {
    "build": "NODE_ENV=production webpack --config ./webpack.production.config.js"
},

如果您的 webpack.dev.config 和 webpack.prod.config 中有很多重复代码,您可以使用布尔值 isProd 仅在某些情况下激活某些功能并且只有单个 webpack.config.js 文件。

const isProd = (process.env.NODE_ENV === 'production');

 if (isProd) {
     plugins.push(new AotPlugin({
      "mainPath": "main.ts",
      "hostReplacementPaths": {
        "environments/index.ts": "environments/index.prod.ts"
      },
      "exclude": [],
      "tsConfigPath": "src/tsconfig.app.json"
    }));
    plugins.push(new UglifyJsPlugin({
      "mangle": {
        "screw_ie8": true
      },
      "compress": {
        "screw_ie8": true,
        "warnings": false
      },
      "sourceMap": false
    }));
  }

顺便说一句: DedupePlugin 插件已从 Webpack 中删除。您应该将其从您的配置中删除。

更新:

加上我之前的回答:

如果您想隐藏发布代码,请尝试 enclosejs.com。它允许您:

  • 在没有源代码的情况下制作您的应用程序的发布版本
  • 创建自解压存档或安装程序
  • 制作闭源 GUI 应用程序
  • 将您的资产放入可执行文件

您可以使用 npm install -g enclose

安装它

自己刚学的。我来回答第二个问题:

  1. 如何使用这些文件?目前我正在使用 webpack-dev-server 运行 应用程序。

不使用 webpack-dev-server,你可以 运行 一个 "express"。使用 npm install "express" 并在项目的根目录中创建一个 server.js,如下所示:

var path = require("path");
var express = require("express");

var DIST_DIR = path.join(__dirname, "build");
var PORT = 3000;
var app = express();

//Serving the files on the dist folder
app.use(express.static(DIST_DIR));

//Send index.html when the user access the web
app.get("*", function (req, res) {
  res.sendFile(path.join(DIST_DIR, "index.html"));
});

app.listen(PORT);

然后,在package.json中添加一个脚本:

"start": "node server.js"

最后,运行 应用:npm run start 启动服务器

详细示例见: https://alejandronapoles.com/2016/03/12/the-simplest-webpack-and-express-setup/ (示例代码与最新的软件包不兼容,但可以进行一些小的调整)

最新答案包括 Webpack 5

For Webpack(版本不记得了)

NODE_ENV=production webpack --config ./webpack.production.config.js

Webpack <4

plugins: [
    new webpack.DefinePlugin({
        'process.env':{
            'NODE_ENV': JSON.stringify('production')
                        //for development -> JSON.stringify('development')
        }
    })
]

对于 webpack >=4 (包括 webpack 5) - 指定 mode

 module.exports = {
   mode: 'production', //for development -> development
   devtool: 'inline-source-map',
   ...
 };

引自Webpack官方website

Since webpack v4, specifying mode automatically configures DefinePlugin for you