webpack优化配置

webpack 优化配置

现在很多主流的框架都已经先把 bundler 的相关 config 都写好了,但了解这些
相关配置也能帮助到自己在开发时可以思考一下要如何改良自己的代码,进而提升整体的打包性能。

  • 数据性能分析
  • 编译时间优化
  • 编译体积优化
  • 运行速度优化

数据性能分析

1. 速度分析

这个性能到底是快还是慢,快多少,慢多少,得有数据,那么就需要工具帮我我们统计数据来分析。

speed-measure-webpack-plugin
图片1.png
图片2.png

2. 文件体积监控

webpack-bundle-analyzer
  • 是个webpack的插件,需要配合webpack和webpack-cli一起使用。这个插件的功能是生成代码分析报告,帮助提升代码质量和网站性能
  • 可以直观分析打包出的文件包含哪些,大小占比如何,模块包含关系,依赖项,文件是否重复,压缩后大小如何,针对这些,我们可以进行文件分割等操作。


    图片1.png
图片2.png
图片3.png

编译时间优化

1. 缩小查找范围

extensions

  • 定extensions之后可以不用在require或是import的时候加文件扩展名
  • 查找的时候会依次尝试添加扩展名进行匹配


    图片4.png

alias

  • 配置别名可以加快webpack查找模块的速度
  • 当引入bootstrap模块的时候,它会直接引入bootstrap,而不需要从node_modules文件夹中按模块的查找规则查找


    图片5.png

modules

  • 直接声明依赖名的模块webpack会使用类似Node.js一样进行路径搜索,搜索node_modules目录

  • 果可以确定项目内所有的第三方依赖模块都是在项目根目录下的node_modules中的话可以直接指定

  • 默认配置


    图片6.png
  • 直接指定


    图片7.png

oneOf

  • 没个文件对于rules中的所有规则都会遍历一遍,如果使用oneOf,只要能匹配一个即可退出
  • oneOf中不能两个配置处理同一种类型文件


    图片8.png

external

  • 如果我们想引用一个库,但是又不想让webpack打包,那就可以通过配置externals排除打包
  • 在模板 html 文件中引入 cdn 地址,可通过区分开发和生产环境来判断是否使用 cdn 链接(process.env.NODE_ENV 属性),本地就通过 node_modules 中的资源编译就好,不会在项目里生成文件,而是存储于内存当中,这个时候通过内存获取数据会比从网络中获取 cdn 资源更快。


    图片9.png

2.减少处理文件

noParse

  • module.noParse 字段,可以用于配置哪些模块文件的内容不需要进行解析
  • 需要解析依赖(即无依赖) 的第三方大型类库等,可以通过这个字段来配置,以提高整体的构建速度
  • 用 noParse 进行忽略的模块文件中不能使用 import、require 等语法


    图片10.png

    备注:比如jquery,loadsh工具库

IgnorePlugin

  • ignore-plugin用于忽略某些特定的模块,让 webpack 不把这些指定的模块打包进去
  • requestRegExp 匹配(test)资源请求路径的正则表达式
  • contextRegExp (可选)匹配(test)资源上下文(目录)的正则表达式
  • moment会将所有本地化内容和核心功能一起打包,可使用 IgnorePlugin 在打包时忽略本地化内容

==moment中其它语言包不要了,不打包,忽略掉,需要中文直接import,从600多K 减少到 100多K==


图片11.png

thread-loader(多进程)

  • 把thread-loader放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的worker 池(worker pool)中运行
  • include 表示哪些目录中的 .js 文件需要进行 babel-loader
  • exclude 表示哪些目录中的 .js 文件不要进行 babel-loader
  • exclude 的优先级高于 include,尽量避免 exclude,更倾向于使用 include

==thread-loader开启线程池,开线程和线程通信都需要时间,大概0.7所有,所以项目特别大,任务特别多的时候才用thread-loader (happypack 在webpack5中已经废掉了,不再维护了)。==


图片12.png

利用缓存

利用缓存可以提升重复构建的速度

babel-loader
  • Babel在转义js文件过程中消耗性能较高,将babel-loader执行的结果缓存起来,当重新打包构建时会尝试读取缓存,从而提高打包构建速度、降低消耗
  • 默认存放位置是node_modules/.cache/babel-loader


    图片13.png

    备注:Babel-loader 自带缓存功能,直接通过配置开启。 其他loader没有缓存功能,比如css-loader等,可以使用cache-loader缓存。

cache-loader
  • 在一些性能开销较大的loader之前添加cache-loader,可以以将结果缓存中磁盘中
  • 默认保存在 node_modules/.cache/cache-loader 目录下


    图片14.png
hard-source-webpack-plugin ==(替换了DllPlugin)==
  • HardSourceWebpackPlugin为模块提供了中间缓存,缓存默认的存放路径是 node_modules/.cache/hard-source
  • 配置hard-source-webpack-plugin后,首次构建时间并不会有太大的变化,但是从第二次开始,构建时间大约可以减少80%左右
  • webpack5中已经内置了模块缓存,不需要自己单独配置此插件


    图片15.png

编译体积优化

1. 压缩JS、CSS、HTML和图片

  • optimize-css-assets-webpack-plugin是一个优化和压缩CSS资源的插件
  • terser-webpack-plugin是一个优化和压缩JS资源的插件
  • image-webpack-loader可以帮助我们对图片进行压缩和优化


    图片16.png

    图片17.png

2. 清除无用的CSS

  • purgecss-webpack-plugin单独提取CSS并清除用不到的CSS

==mini-css-extract-plugin // 因为css和js的加载可以并行,所以我们可以通过此插件提取css成单独文件,干掉无用的css进行压缩==

==考虑通过js动态添加的css==


图片18.png

图片19.png

备注:

1. 不再使用style-loader,直接使用MiniCssExtractPlugin.loader。
2. const glob = require(’glob’) // 文件匹配模式,给他一个字符串,能够匹配文件出来。
3. const PATHS = { //一堆路径的集合
    src: path.resolve(__dirname, ’src’)
};
4. **匹配任意字符,包括路径分隔符,*匹配任意字符,不包括路径分隔符。

3. Tree Shaking

  • 一个模块可以有多个方法,只要其中某个方法使用到了,则整个文件都会被打到bundle里面去
  • 原理是利用es6模块的特点,只能作为模块顶层语句出现,import的模块名只能是字符串常量
webpack默认支持,可在production mode下默认开启

package.json 配置:
1.sideEffects": false 所有的代码都没有副作用(都可以进行 tree shaking)
2.可能会把 css和@babel/polyfill文件干掉 可以设置 "sideEffects":["*.css"]

dev模式下通过配置babel看到tree shaking效果
图片20.gif

备注:

  1. webpack5中的treeshaking是经过了加强优化的,功能比webpack4强大的多。
  2. 在 ES6 module 还没诞生以前我们也可以利用 commonJS 来进行 module 的导入,为什麽 ES6 module 可以做到 Tree Shaking 可是 commonJS 无法呢?其实是因为 ES6 module 有著非常多的特性,让 bundler 可以针对这些特性来进行静态的分析:
    • module 必须要在顶层被 import。
    • module 内部会自动被定义为 strict mode。
    • module name 不能动态改变。
    • module 内容为 immutable 无法在其他文件中被动态新增或删除内容。
      因为这些强限制在,所以 ES6 module 就可以让 bundler 做到 Tree Shaking 的效果,而 commonJS则无法达到此点。

运行速度优化

1. 代码分割

1.1 入口点分割

Entry Points:入口文件设置的时候可以配置
这种方法的问题:

  • 如果入口 chunks 之间包含重复的模块(lodash),那些重复模块都会被引入到各个 bundle 中
  • 不够灵活,并且不能将核心应用程序逻辑进行动态拆分代码


    图片21.png

1.2 懒加载

用户当前需要用什么功能就只加载这个功能对应的代码,也就是所谓的按需加载,在给单页应用做按需加载优化时,一般采用以下原则:

  • 对网站功能进行划分,每一类一个chunk
  • 对于首次打开页面需要的功能直接加载,尽快展示给用户,某些依赖大量代码的功能点可以按需加载
  • 被分割出去的代码需要一个按需加载的时机

==import 天然的代码分割点,如果遇到import就会分割出去一个单独的代码块,可以单独加载==


图片22.png
图片23.png

备注:import语法:像vue,react,angular的懒加载组件,包括路由组件的懒加载原理都是一样的,通过import动态引入。

1.3 prefetch

  • 使用预先拉取,表示该模块可能以后会用到。浏览器会在空闲时间下载该模块
  • prefetch的作用是告诉浏览器未来可能会使用到的某个资源,浏览器就会在闲时去加载对应的资源,若能预测到用户的行为,比如懒加载,点击到其它页面等则相当于提前预加载了需要的资源

==通过魔法注释,给懒加载的代码块添加预获取配置==,此导入会让<link rel="prefetch" as="script" href="http://localhost:8080/hello.js">被添加至页面的头部。因此浏览器会在空闲时间预先拉取该文件。


图片24.png

备注:

  1. preload 预加载,该资源肯定用得到,优先级较高,需要提前获取,有可能有性能隐患(需慎用)。
  2. prefetch 预获取,该资源可能在以后用得到,它在浏览器空闲的时候加载,没有性能问题。

1.4 提取公共代码

splitChunks

提取公共代码,防止被重复打包,拆分过大的js文件,合并零散的js文件

module、chunk和bundle 这三个名词是什么意思 :

module:就是js的模块化webpack支持commonJS、ES6等模块化规范,简单来说就是你通过import语句引入的代码。

chunk: chunk是webpack根据功能拆分出来的,包含三种情况:

  • 你的项目入口(entry)
  • 通过import()动态引入的代码
  • 通过splitChunks拆分出来的代码
    chunk包含着module,可能是一对多也可能是一对一。

bundle:bundle是webpack打包之后的各个文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。

splitChunks 配置:
1. maxInitialRequests

是splitChunks里面比较难以理解的点之一,它表示允许入口并行加载的最大请求数,之所以有这个配置也是为了对拆分数量进行限制,不至于拆分出太多模块导致请求数量过多而得不偿失。
这里需要注意几点:

  • 入口文件本身算一个请求
  • 如果入口里面有动态加载得模块这个不算在内
  • 通过runtimeChunk拆分出的runtime不算在内
  • 只算js文件的请求,css不算在内
  • 如果同时又两个模块满足cacheGroup的规则要进行拆分,但是maxInitialRequests的值只能允许再拆分一个模块,那尺寸更大的模块会被拆分出来
2. cacheGroups

是核心,配置提取模块的规则,test,priority,reuseExistingChunk,这三项是特有配置,其他跟外面选项一样,如果里面没配置,就用外面的。


图片25.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • 1. webpack 开发和生产优化 资料参考1:https://www.cnblogs.com/wangjiac...
    暴躁程序员阅读 703评论 0 0
  • 一、HMR 热模块替换:一个模块发生变化,只会重新打包这个模块,而不是打包所有模块,从而提高构建速度 二、sour...
    老衲不生气阅读 368评论 0 0
  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 11,064评论 0 21
  • 最近给项目进行webpack优化,尝试过几乎所有方法,一共26条,列举在此。 优化webpack,首先明确优化目标...
    seaasun阅读 2,154评论 0 4
  • 一、减少前端资源体积 1、webpack 4 开启production模式 production模式下 webpa...
    Yong_bcf4阅读 321评论 0 0