webpack-生产环境最佳实践(https://webpack.js.org/guides/production/)

来源:互联网 发布:淘客网站源码建立 编辑:程序博客网 时间:2024/06/04 19:32

Production

此篇文章介绍利用webpack构建线上版本的最佳实践。

The Automatic Way

一般来说,运行webpack -p命令。此命令相当于webpack --optimize-minimize --define process.env.NODE_ENV="'production'"命令。这条指令执行以下操作:
》使用UglifyJsPlugin插件压缩文件
》运行LoaderOptionsPlugin
》设置nodejs的环境变量,以触发特定包的编译

Minification 压缩

webpack自带UglifyJsPlugin插件,它会运行uglifyjs以压缩输出,这个插件支持所有的uglifyjs选项,如果我们在命令行中添加--optimize-minimize选项,下列的插件属性就会被添加:
// webpack.config.jsconst webpack = require('webpack');module.exports = {  /*...*/  plugins:[    new webpack.optimize.UglifyJsPlugin({      sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)    })  ]};

Source Maps 资源映射

我们建议你在生产环境将source map使能,它们将有利于调试和测试。webpack可以在bundles中生成内联source map或者单独生成文件。webpack支持7种类型的source maps。其中,cheap-module-source-map是最简单的,其在每一行生成单个映射。

当我们把多个js文件转换合并一个js文件时,线上调试就成了问题,当出错误时,我们无法确定哪里出了问题,source map可以解决这个问题。(https://survivejs.com/webpack/building/source-maps/)

Node Environment Variable  Node的环境变量

运行webpack -p 或者--define process.env.NODE_ENV="'production'",将会以下列方式唤醒DefinePlugin插件:

// webpack.config.jsconst webpack = require('webpack');module.exports = {  /*...*/  plugins:[    new webpack.DefinePlugin({      'process.env.NODE_ENV': JSON.stringify('production')    })  ]};

DefinePlugin本质上在源码上执行查找-替换操作,任何在代码中出现的process.env.NODE_ENV被"production"替换。因此,以下代码,if (process.env.NODE_ENV !== 'production') console.log('...')相当于if (false) console.log('...'),然后利用UglifyJS压缩。

从技术上讲,NODE_ENV是nodejs暴露给执行代码的系统环境变量。它通常决定server tools、build scripts、和客户端libary的是开发环境还是生产环境。

The Manual Way 可执行的方式

When we do have multiple configurations in mind for different environments, the easiest approach is to write separate webpack configurations for each environment.

当我们针对不同的环境,执行不同的构建操作时,最简单的方式是针对不同的环境分别写webpack config文件。

Simple Approach

最简单的方式是写2个相互独立的config文件

webpack.dev.js

module.exports = {  devtool: 'cheap-module-source-map',  output: {    path: path.join(__dirname, '/../dist/assets'),    filename: '[name].bundle.js',    publicPath: publicPath,    sourceMapFilename: '[name].map'  },  devServer: {    port: 7777,    host: 'localhost',    historyApiFallback: true,    noInfo: false,    stats: 'minimal',    publicPath: publicPath  }}

webpack.prod.js

module.exports = {  output: {    path: path.join(__dirname, '/../dist/assets'),    filename: '[name].bundle.js',    publicPath: publicPath,    sourceMapFilename: '[name].map'  },  plugins: [    new webpack.LoaderOptionsPlugin({      minimize: true,      debug: false    }),    new webpack.optimize.UglifyJsPlugin({      beautify: false,      mangle: {        screw_ie8: true,        keep_fnames: true      },      compress: {        screw_ie8: true      },      comments: false    })  ]}
然后用以下方式调用

package.json

"scripts": {  ...  "build:dev": "webpack --env=dev --progress --profile --colors",  "build:dist": "webpack --env=prod --progress --profile --colors"}

然后封装webpack.config.js决定哪个配置文件被执行

webpack.config.js

module.exports = function(env) {  return require(`./webpack.${env}.js`)}

Advanced Approach 高级技巧

一个更复杂的方式是,将开发环境和生产环境共有的配置写进一个基础配置文件,然后,将基础配置文件与特定环境下的文件进行合并,这样做的好处,两个配置文件不会有重复代码。

合并配置文件的工具是webpack-merge,它提供了许多合并选项。

webpack.common.js

module.exports = {  entry: {    'polyfills': './src/polyfills.ts',    'vendor': './src/vendor.ts',    'main': './src/main.ts'  },  output: {    path: path.join(__dirname, '/../dist/assets'),    filename: '[name].bundle.js',    publicPath: publicPath,    sourceMapFilename: '[name].map'  },  resolve: {    extensions: ['.ts', '.js', '.json'],    modules: [path.join(__dirname, 'src'), 'node_modules']  },  module: {    rules: [      {        test: /\.ts$/,        exclude: [/\.(spec|e2e)\.ts$/],        use: [          'awesome-typescript-loader',          'angular2-template-loader'        ]      },      {        test: /\.css$/,        use: ['to-string-loader', 'css-loader']      },      {        test: /\.(jpg|png|gif)$/,        use: 'file-loader'      },      {        test: /\.(woff|woff2|eot|ttf|svg)$/,        use: {          loader: 'url-loader',          options: {            limit: 100000          }        }      }    ]  },  plugins: [    new ForkCheckerPlugin(),    new webpack.optimize.CommonsChunkPlugin({      name: ['polyfills', 'vendor'].reverse()    }),    new HtmlWebpackPlugin({      template: 'src/index.html',      chunksSortMode: 'dependency'    })  ]}
然后生产环境配置文件如下

webpack.prod.js

const Merge = require('webpack-merge');const CommonConfig = require('./webpack.common.js');module.exports = Merge(CommonConfig, {  plugins: [    new webpack.LoaderOptionsPlugin({      minimize: true,      debug: false    }),    new webpack.DefinePlugin({      'process.env': {        'NODE_ENV': JSON.stringify('production')      }    }),    new webpack.optimize.UglifyJsPlugin({      beautify: false,      mangle: {        screw_ie8: true,        keep_fnames: true      },      compress: {        screw_ie8: true      },      comments: false    })  ]})

You will notice three major updates to our 'webpack.prod.js' file:

  • Use webpack-merge to combine it with the 'webpack.common.js'.
  • We moved the output property to webpack.common.js as it is common to all environments.
  • We defined 'process.env.NODE_ENV' as 'production' using theDefinePlugin only in webpack.prod.js.

The example above only demonstrates a few typical configuration options used in each (or both) environments. Now that you know how to split up configurations, the choice of what options go where is up to you.

可以看到webpack.prod.js文件有以下3个变化:

》利用webpack-merge工具合并base文件

》将共有的配置移动到了common文件

》在webpack.prod.js中利用DefinePlugin插件设置来环境变量为‘production’



阅读全文
0 0
原创粉丝点击