Webpack 4 升级步骤和注意点

发布于 2024-09-07 12:29:42 字数 10398 浏览 47 评论 0

一、环境及依赖库更新

由于 Webpack 的更新,很多 Loader 也必须更新才能适应 Webpack 的最新版本

必须更新的 loader最低要求版本功能说明
babel-loader7.1.3对最新的 ES 语法进行转换
eslint-loader2.0.0代码检查
file-loader1.1.10批量修改文件路径,或者指定编译后文件存储路径
vue-loader15.0.0解析、编译 vue 单文件组件
vue-style-loader4.1.0解析、编译 vue 单文件组件中的样式

二、Webpack 4.x 的破坏性变更

由于 Webpack 4.x 的重大变更,导致其不再支持部分插件和 Loader ,其中最闹心的是 Chunk 分离及文件分离

失效的插件或 loader类型功能说明
webpack.optimize.CommonsChunkPlugin内置插件分离 Chunk 。将多次出现的代码统一打包到一个文件中。 Vue 工程中用来打包 vendormainfest
webpack.optimize.UglifyJsPlugin内置插件压缩 JS
extract-text-webpack-pluginLoader分离文件。将部分代码或文件提取到单独文件中。Vue 工程里用来分离 CSS 到指定文件

2.1 使用 config.optimization 代替

Webpack 4.x 中,新增了 optimization 的选项来代替之前版本中的 webpack.optimize 等。在 optimization 选项中,我们可以进行详细的设置,以达到分离 CSS ,分离 Chunk ,压缩文件等等操作

module.exports = {
  //...
  optimization: {}
};

2.2 压缩 JS 及 CSS 文件

由于 Webpack 4.x 中取消了其内置插件,所以之前的方法都不管用了。这里我推荐大家使用 UglifyJsPluginOptimizeCSSPlugin 插件来代替之前的内置插件,当然如果你只是想简单的压缩,而不做任何配置的话,可以按照官方文档中给出的方法使用 optimization.minimizer: true 即可

const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  //...
  optimization: {
    minimizer: [
      // js mini
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: false // set to true if you want JS source maps
      }),
      // css mini
      new OptimizeCSSPlugin({})
    ]
  }
}

2.3 分离 JS 文件

在之前版本中,我们使用 CommonsChunkPlugin 进行文件分离,而在 Webpack 4.x 中,我们则借助于 config.optimization 来实现

// webpack 3.xx
module.exports = {
  //...
  plugins:[
     new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function(module) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
  ]
}
// webpack4
module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      // 大于 30KB 才单独分离成 chunk
      minSize: 30000,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: true,
      cacheGroups: {
        default: {
          priority: -20,
          reuseExistingChunk: true,
        },
        vendors: {
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          chunks: "all"
        },
        echarts: {
          name: 'echarts',
          chunks: 'all',
          // 对 echarts 进行单独优化,优先级较高
          priority: 20,
          test: function(module){
            var context = module.context;
            return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0)
          }
        }
      }
    }
  }
}

2.3.1 公共代码抽取

CommonsChunkPlugin 已弃用,使用 optimization.splitChunks 代替

配置项

  • cacheGroups 自定义配置主要使用它来决定生成的文件
  • test 限制范围,可以是正则,匹配文件夹或文件
  • name 生成文件名
  • priority 优先级,多个分组冲突时决定把代码放在哪块
  • minSize 最小尺寸必须大于此值,默认 30000B
  • minChunks 其他 entry 引用次数大于此值,默认 1( minChunks 指的是被不同 entry 引入的次数)
    • 1 时,适合分离 node_moudles 里的第三方库(很多人认为这个值设成 2 其实不合理)
  • maxInitialRequests entry 文件请求的 chunks 不应该超过此值(请求过多,耗时)
  • maxAsyncRequests 异步请求的 chunks 不应该超过此值
  • automaticNameDelimiter 自动命名连接符
  • chunks 值为 "initial" , "async" (默认) 或 "all"
    • initial 入口 chunk ,对于异步导入的文件不处理
    • async 异步 chunk ,只对异步导入的文件处理(个人理解)
    • all 全部 chunk (我反正选 all ,不甚理解)

使用方式

  1. 使用默认配置

不配置时再 production 模式下开启 async

optimization:{
  splitChunks:{
    chunks:"all"
  }
}

生成的文件 vendors~xx.js ,xx 与入口名对应

默认配置

optimization: {
  splitChunks: {
    chunks: "async",
    minSize: 30000,
    minChunks: 1,
    maxAsyncRequests: 5,
    maxInitialRequests: 3,
    automaticNameDelimiter: '~',
    name: true,
    cacheGroups: {
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        priority: -10
      },
      default: {//cacheGroups 重写继承配置,设为 false 不继承
        minChunks: 2,
        priority: -20,
        reuseExistingChunk: true
      }
    }
  }
}
  1. 自定义配置

生成的文件 xx.jsxxname 的值

optimization: {
  //打包 第三方库
  //打包 公共文件
  splitChunks: {
    cacheGroups: {
      vendor:{//node_modules 内的依赖库
        chunks:"all",
        test: /[\\/]node_modules[\\/]/,
        name:"vendor",
        minChunks: 1, //被不同 entry 引用次数(import),1 次的话没必要提取
        maxInitialRequests: 5,
        minSize: 0,
        priority:100,
        // enforce: true?
      },
      common: {// ‘src/js’ 下的 js 文件
        chunks:"all",
        test:/[\\/]src[\\/]js[\\/]/,//也可以值文件/[\\/]src[\\/]js[\\/].*\.js/,  
        name: "common", //生成文件名,依据 output 规则
        minChunks: 2,
        maxInitialRequests: 5,
        minSize: 0,
        priority:1
      }
    }
  }
}

配合 runtimeChunk

runtimeChunk ,将入口提取出来,这样入口文件可以很快加载,并且当哪里有改动的时候,只有改动的地方和这个文件有变化。 optimization.runtimeChunk 用来提取 entry chunk 中的 runtime 部分函数,形成一个单独的文件,这部分文件不经常变换,方便做缓存

runtimeChunk: {
  name: 'manifest'
}

2.4 提取 CSS 到单独文件

在之前版本中我们使用 extract-text-webpack-plugin 来提取 CSS 文件,不过在 webpack 4.x 中则应该使用 mini-css-extract-plugin 来提取 CSS 到单独文件中

// webpack 3.xx
const utils = require('./utils')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = {
  //...
  new ExtractTextPlugin({
    filename: utils.assetsPath('css/[name].[contenthash:7].css')
  })
}
// webpack 4.xx
const utils = require('./utils')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  //...
  new MiniCssExtractPlugin({
    filename: utils.assetsPath('css/[name].[contenthash:7].css')
  })
}
// webpack4 生产环境下的配置优化

const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
  optimization: {
  minimizer: [
    new UglifyJsPlugin({
    cache: true,
    parallel: true,
    sourceMap: true 
    }),
    new OptimizeCSSAssetsPlugin({})  // use OptimizeCSSAssetsPlugin
  ]
  },
  plugins: [
  new MiniCssExtractPlugin({
    filename: 'css/app.[name].css',
    chunkFilename: 'css/app.[contenthash:12].css'  // use contenthash *
  })
  ]
  ....
}

将多个 css chunk 合并成一个 css 文件

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  optimization: {
  splitChunks: {
    cacheGroups: {
    styles: {      
      name: 'styles',
      test: /\.scss|css$/,
      chunks: 'all',  // merge all the css chunk to one file
      enforce: true
    }
    }
  }
  }
}

2.5 用更加快捷的 mode 模式来优化配置文件

webpack4 中提供的 mode 有两个值: developmentproduction ,默认值是 productionmode 是我们为减小生产环境构建体积以及节约开发环境的构建时间提供的一种优化方案,提供对应的构建参数项的默认开启或关闭,降低配置成本

// 开启方式 1:直接在启动命令后加入参数

"scripts": {
  "dev": "webpack --mode development",
  "build": "webpack --mode production"
}
// 开启方式 2:可以在配置文件中加入一个 mode 属性:
module.exports = {
  mode: 'production' // development
};

2.6 其他调整项备忘

  • NoEmitOnErrorsPlugin - > optimization.noEmitOnErrors (默认情况下处于生产模式)
  • ModuleConcatenationPlugin- > optimization.concatenateModules`(默认情况下处于生产模式)
  • NamedModulesPlugin - > optimization.namedModules (在开发模式下默认开启)
  • webpack 命令优化 -> 发布了独立的 webpack-cli 命令行工具包
  • webpack-dev-server -> 建议升级到最新版本
  • html-webpack-plugin -> 建议升级到的最新版本
  • file-loader -> 建议升级到最新版本
  • url-loader -> 建议升级到最新版本

三、更多参考

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
23 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文