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

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.js
const 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.js
const 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的是开发环境还是生产环境。

 

 可执行的方式

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

最简单的方式是写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`)
}

 

高级技巧

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

合并配置文件的工具是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
    })
  ]
})
可以看到webpack.prod.js文件有以下3个变化:

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

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

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

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值