热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

webpack代码分离优化快速指北

这篇文章主要介绍了webpack代码分离优化快速指北,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

分离代码文件

在此之前,首先要知道经常配置的 output 中有关 filename 和 chunkFilename 的区别;简单来说在 entry 定义的入口文件走的就是 filename 配置项,在入口文件内部引入的通常情况下是 chunk,走 chunkFilename 的配置

所以很多时候分离代码文件就是将不同的 chunk 分离开来,生产环境中有利于浏览器缓存,加快二次访问的速度

代码分离的时候,optimization 中配置的 splitChunks 默认就是 async,默认对异步代码进行分离;所以通常情况下能用异步的用异步 import;配合 prefetching 和 preloading 能够产生很好的效果

filename 和 chunkFilename 的区别

output: {
 filename: '[name].js',
 chunkFilename: '[name].chunk.js'
}

举个例子

如果入口文件是 main.js

那么打包后生成的文件是 main.js

如果 main.js 中引入了其他模块,比如引入了 lodash 那么可能会生成一个名为 lodash.chunk.js 文件

基本概念了解了,接下来开始对 js 和 css 文件进行分离的操作:

js 代码分离

js 代码的分离操作,首先要考虑的就是对异步代码的分离。这里使用 dynamicImport

dynamicImport

可以使用 magic comment 来修改动态 import 导出的 chunkname,语法规则如下:

import('/* webpackChunkName: "lodash" */' 'lodash').then(//...)

如果需要使用这种注释的写法,应该安装模块 @babel/plugin-syntax-dynamic-import,并在 babelrc 中引入这个插件,使用方法很简单这里不多说了

splitChunks

splitChunk 的相关配置参数

建议将公共使用的第三方类库显式地配置为公共的部分,而不是 webpack 自己去判断处理

  • chunks: 表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
  • minSize: 表示在压缩前的最小模块大小,默认为0;
  • minChunks: 表示被引用次数,默认为1;
  • maxAsyncRequests: 最大的按需(异步)加载次数,默认为1;
  • maxInitialRequests: 最大的初始化加载次数,默认为1;
  • name: 拆分出来块的名字(Chunk Names),默认由块名和hash值自动生成;
  • cacheGroups: 缓存组。

缓存组中还有其他几个参数:

  • priority: 表示缓存的优先级;
  • test: 缓存组的规则,表示符合条件的的放入当前缓存组,值可以是function、boolean、string、RegExp,默认为空;
  • reuseExistingChunk: 表示可以使用已经存在的块,即如果满足条件的块已经存在就使用已有的,不再创建一个新的块。

webpack4——SplitChunksPlugin使用指南

module.exports = {
 entry: {
 vendor: ["react", "lodash", "angular", ...], // 指定公共使用的第三方类库
 },
 optimization: {
 splitChunks: {
  cacheGroups: {
  vendor: {
   chunks: "initial",
   test: "vendor",
   name: "vendor", // 使用 vendor 入口作为公共部分
   enforce: true,
  },
  },
 },
 },
 // ... 其他配置
}

或者:

optimization: {
 splitChunks: {
  name: true, // 自动处理文件名
  chunks: 'all',
  minChunks: 1, // 至少 import 1 次的即需要打包
  automaticNameDelimiter: '-',
  cacheGroups: {
  vendors: {
   test: /axios|lodash/, // 将这两个第三方模块单独提取打包
   chunks: 'initial',
  }
  }
 }
 },

optimization-splitchunks

chunks 的配置

注意 ⚠️

如果是动态 import,import('/* webpackChunkName: "lodash" */' 'lodash').then() 那么 splitChunks 设置为 async,代码分离将会起作用。

如果是同步加载 import, import _ from 'lodash' 那么 splitChunks 设置为 async 将不起作用,如果设置为 all,那么还需要配置 cacheGroups

cacheGroups 的配置

vendors 缓存组的配置可以检测第三方模块是否在 node_modules 中,如果存在则该 splitChunks 生效,将会分离到 vendors~... 这样的文件中

配置 filename 则会打包成 [filename] 命名的文件中

runtimeChunk 的作用

这个 runtimeChunk 实际上就是链接业务逻辑和第三方类库之间的关系的 manifest。需要将其提取出来,否则使用 contenthash 的情况下有可能会导致模块内容没发生改变的情况下出现 contenthash 多次打包出现不一致的情况(实际上就是存在在业务逻辑和模块中的 manifest 发生了改变)

// v4版本的 webpack 不用配置,但最好也提取出来
optimization: {
 runtimeChunk: {
 name: 'runtime'
 }
}

reuseExistingChunk:

如果 a 模块使用了 b,b 模块又使用了 a;a 被打包到 common.js 中,打包 b 时将直接使用已经打包好的 common.js 中的 a;这就是 reuseExistingChunk 的作用:

default: {
 reuseExistingChunk: true,
 filename: 'common.js'
}

他的含义就是只要其中一个模块使用了 import $ from 'jquery',其他文件中就可直接使用 $ 变量,webpack 会自动在打包过程中 import 这个模块

css 代码分离

css 部分分离代码文件 直接使用 extract-text-webpack-plugin 即可

一个 JS 文件,加载页面时虽然只需要加载一个 JS 文件,但代码一旦改变,用户访问新的页面时就需要重新加载一个新的 JS 文件。有些情况下,我们只是单独修改了样式,这样也要重新加载整个应用的 JS 文件,相当不划算。
多个组件共用一部分样式,如果分离开来,第二个页面就有了 CSS 文件的缓存,访问速度自然会加快

MiniCssExtractPlugin

新版本的 webpack 使用这个插件

注意,在引入样式文件 import './style.css' 的时候,如果配置了 treeshaking,应当在 package.json 中配置:

"sideEffects": [
 "*.css"
]

⚠️ 注意,另外在 vue 中如果有 style 标签,还需要在 sideEffects 中加入 *.vue 的配置项。不必担心 vue 中的 script 部分会被 treeShaking 掉。

插件的相关配置

filename 指的是如果该 css 文件会直接被插入 html 中那么走的就是 filename 的配置

plugins: [
 new MiniCssExtractPlugin({
 filename: '[name].css',
 chunkFilename: '[name].chunk.css'
 })
]

既然有分离那就有合并,这里顺便提及一下 css 代码合并

如果有多个入口,想把多个入口引入的样式文件全部打包到一个地方,那么可以使用 optimization 配置项的 splitChunks,所以这个配置项不仅仅只作用于 js,css 也是可以的:

optimization: {
 splitChuns: {
 cacheGroups: {
  styles: {
  name: 'style', // 将多个入口文件中的样式文件全部合并打包
  test: /\.css$/,
  chunks: 'all',
  enforce: true
  }
 }
 }
}

css 代码根据入口分别打包

还可以根据入口的不同,来分别打包 css 文件,文档已经讲的很详细了,这部分比较简单可以直接戳文档 https://webpack.js.org/plugins/mini-css-extract-plugin

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了解决IE678伪类不兼容问题的方法,包括少用CSS3和HTML5独有的属性,使用CSS hacker,使用last-child清除浮动、批量添加标签、去掉list item最后一个的border-right等技巧。同时还介绍了使用after清除浮动时加上IE独有属性zoom:1的处理方法。另外,本文还提到可以使用jQuery代替批量添加标签的功能,以及使用负边距和CSS2选择器element+element去掉list item最后一个的border-right的方法。 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • 例如控件ID为user.id使用$(#user.id)不能得到正确的结果必须使用\\转义即$(#user\\.id)转载于:https:www.cnblogs.comrch ... [详细]
  • 在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合。使用Gson解析json成对象时,默认将json里对应字段的值解析到java对象里对应字段的属性里面。然而,当我们自己定义的java对象里的属性名与json里的字段名不一样时,我们可以使用@SerializedName注解来将对象里的属性跟json里字段对应值匹配起来。本文介绍了使用@SerializedName注解解析json数据的方法,并给出了具体的使用示例。 ... [详细]
author-avatar
手机用户2502913375
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有