webpack-summary icon indicating copy to clipboard operation
webpack-summary copied to clipboard

webpack3 升级到 webpack4

Open diamont1001 opened this issue 6 years ago • 0 comments

webpac 4 是一个大版本,其中 plugin 机制都变化挺大的,几乎所有的 plugin 都需要升级来做兼容,这里简单记录一下遇到的一些问题。

1. webpack-cli

webpack 4 把核心代码和客户端分离开了,现在需要安装一个 webpack-cli 才可以启动 webpack 命令。

全局安装:

npm i webpack-cli -g

项目依赖:

npm i webpack --save-dev
npm i webpack-cli --save-dev

或者 package.json 配置:

{
  "webpack": "^4.1.1",
  "webpack-cli": "^2.0.12"
}

2. html-webpack-plugin

html-webpack-plugin 要升级到 3.0.6 以上即可。

3. module.loaders 替换为 modules.rules

module: {
  loaders: [
    ...
  ]
}

替换为:

module: {
  rules: [
    ...
  ]
}

4. 单独打包 CSS 的 extract-text-webpack-plugin

extract-text-webpack-plugin 暂不支持 webpack 4,我们可以使用另外一个插件 mini-css-extract-plugin 来替换之。

举个栗子(顺便支持一下 less):

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

...

  optimization: {
    minimizer: [
      new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ filename: 'css/index.css' }),
  ],

...

  module: {
    rules: [
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
    ]
  }

5. mode

webpack 4 增加了一个 mode 配置,值可选有两个 developmentproduction,对不同的环境他会提供不同的一些默认配置,比如开发环境下默认开启 optimization.namedModules(原NamedModulesPlugin,现已弃用),而生产环境默认使用 `optimization.noEmitOnErrors(原NoEmitOnErrorsPlugin,现已弃用)。

不同模式下的默认配置:

  1. 生产环境默认开启了很多代码优化(minify,splite 等)
  2. 开发时开启注视和验证,并且自动加上了 eval devtool
  3. 生产环境不支持 watching,开发环境优化了重新打包的速度
  4. 生产环境开启模块串联(原 ModuleConcatenationPlugin),没用过不多说
  5. 自动设置 process.env.NODE_ENV 到不同环境,也就是不需要 DefinePlugin 来做这个了
  6. 如果你给 mode 设置为 none,所有默认配置都去掉了

6. CommonsChunkPlugin

CommonsChunkPlugin删除之后,改成使用optimization.splitChunks进行模块划分,详细文档看 这里

官方的说法是默认设置已经对大部分用户来说非常棒了,但是需要注意一个问题,默认配置只会对异步请求的模块进行提取拆分,如果要对 entry 进行拆分,需要设置 optimization.splitChunks.chunks = 'all'

对应之前我们拆分runtime的情况,现在也有一个配置optimization.runtimeChunk,设置为true就会自动拆分runtime文件。

真实例子 webpack.conf.js

'use strict';

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Html文件处理

module.exports = {
  entry: {
    index: './src/index.js'
  },
  output: {
    path: path.resolve(__dirname, './build'), // This is where images AND js will go
    publicPath: '', // This is used to generate URLs to e.g. images
    filename: 'js/[name].js',
    chunkFilename: 'js/[id].chunk.js?[hash:8]'
  },
  mode: 'development', // 'production'
  optimization: {
    minimizer: [
      new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
      new OptimizeCSSAssetsPlugin({})
    ]
  },
  plugins: [
    // 单独打包CSS
    new MiniCssExtractPlugin({ filename: 'css/index.css' }),

    new CopyWebpackPlugin([
      { from: 'src/images/*', to: 'images/', flatten: true},
      { from: 'src/parallax/*', to: 'js/', flatten: true}
      ], {}),

    new HtmlWebpackPlugin({
      filename: 'index.html',
      chunks: ['index'],
      template: './src/index.html',
      hash: true
    })
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader', // ES6
        exclude: /(node_modules|parallax|fullpage)/
      },
      // { test: /\.css$/, loader: 'style-loader!css-loader' },
      // { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.(png|jpg|gif)$/,
        loader: 'url-loader',
        query: {
          name: '[path][name].[ext]?[hash:8]',
          limit: 8192 // inline base64 URLs for <=8k images, direct URLs for the rest
        }
      }
    ]
  }
};

附件

diamont1001 avatar Apr 10 '18 03:04 diamont1001