前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

webpack4升级篇

首页2018-11-25 19:10:08Front-End
Webpack升级

# 一、环境及依赖库更新

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

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

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

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

失效的插件或loader 类型 功能说明
webpack.optimize.CommonsChunkPlugin 内置插件 分离Chunk。将多次出现的代码统一打包到一个文件中。Vue工程中用来打包vendor及mainfest
webpack.optimize.UglifyJsPlugin 内置插件 压缩JS
extract-text-webpack-plugin Loader 分离文件。将部分代码或文件提取到单独文件中。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中取消了其内置插件,所以之前的方法都不管用了。这里我推荐大家使用UglifyJsPlugin及OptimizeCSSPlugin插件来代替之前的内置插件,当然如果你只是想简单的压缩,而不做任何配置的话,可以按照官方文档中给出的方法使用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.js ,xx指name的值

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')
    })
}
@前端进阶之旅: 代码已经复制到剪贴板
fe
  • 一、环境及依赖库更新
  • 二、Webpack 4.x 的破坏性变更
    • 2.1 使用config.optimization代替
    • 2.2 压缩JS及CSS文件
    • 2.3 分离JS文件
      • 2.3.1 公共代码抽取
    • 2.4 提取CSS到单独文件
    • 2.5 用更加快捷的mode模式来优化配置文件
    • 2.6 其他调整项备忘
  • 三、更多参考

← docker结合pm2部署node项目dll 预编译提高 webpack 打包速度,以及它现在的替代方案 →