webpack中的module,chunk 和 bundle
module
:模块,reuqire或者是export引入的代码块chunk
:代码块,进行依赖分析时,代码分割出来的代码块,是又一个或者多个module组成,通过code split之后的就是chunkbundle
:最终打包出来的文件,一般一个bundle对应一个chunk
webpack中loader和plugin
loader
: 用于对模块的源代码进行转换。loader 可以使你在 import 或 “load(加载)” 模块时预处理文件。plugin
: 赋予各种灵活的功能(打包优化,资源管理,环境变量注入等)
Webpack插件机制之Tapable
tapable
: webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable,webpack中最核心的负责编译的Compiler和负责创建bundles的Compilation都是Tapable的实例。
具体可阅读《webpack4.0源码分析之Tapable》链接:link
提升打包速度
SourceMap
(源代码映射)
是一个用来生成源代码与构建后代码——映射的文件的方案
增强调试,在开发阶段调试更加友好,打包上线报错后提示更加精确
提升打包构建速度(HotModuleReplacement)HMR
oneOf
其中一个,每个文件只能被一个loader配置处理
Include
/ Exclude
对js 文件处理时,只处理src下面文件,排除node_modules
Cache(缓存)
每次打包时js文件都要经过Babel编译,速度比较慢。
可以缓存Babel编译结果,这样第二次打包时速度就会更快了。
Thead(启动多进程打包)
减少代码体积
Tree shaking
自动移除Js中没有使用的代码,它依赖ES module;webpack中已经默认了这个功能,无需配置。
Bable
为编译的每个文件都插入了辅助代码,使代码体积过大!
对一些公共方法使用了非常小的辅助代码,如_extend。默认情况下会被添加到每一个需要它的文件当中。
@babel/plugin-transform-runtime:禁用了Babel自动对每个文件的runtime注入,而是引入@babel/plugin-transform-runtime,并且使所有辅助代码从这里引用。
Image Minimizer
图片体积过大, 请求速度比较慢。
对图片进行压缩,减少图片体积。
image-minimizer-webpack-plugin:压缩图片的插件
优化代码运行性能
Code split
(代码分割)
打包代码时会将所有js文件打包到一个文件中,体积过大;如果只渲染首页,就因该只加载首页的js文件,其他文件不应该加载。
分割文件:将打包生成的文件进行分割,生成多个js文件。
按需加载:需要哪个文件就加载哪个文件。
配置多入口文件打包的配置(多入口中有公共的配置项)
代码分割配置
optimization:{
chunk:all, //对所有模块进行分割
minSize:2000, //分割代码最小的大小
minRemainingSize:1, //类似于minSize,最后确保提取的文件大小不能为0
minChunks:1, //至少被引用的次数,满足条件才会分割
maxAsyncRequests:30, //按需加载时并行加载的文件的最大数量
maxInitialRequests:30, //入口js文件最大并行请求数量
enforceSizeThreshold:50000, //超过50KB一定会单独打包(此时忽略minRemainingSize,maxAsyncRequests,maxInitialRequests)
caecheGroups:{
defaultVendors:{
test:/[\\/]node_modules[\\/]/, //需要打包到一起的模块
priority:-10, //权重越大越好
reuseExistingChunk:true, //如果当前chunk包含已从主bundle中拆分的模块,则它将被重用,而不是生成新的模块
},
default:{ //其他没有写的配置会使用上面的默认值
minChunks:2, //这里的minChunks权重最大
priority:-20,
reuseExistingChunk:true,
}
}
}
按需加载
import动态导入,将会动态导入的文件代码分割(拆分成单独模块),在需要使用的时候自动加载,会让首页加载速度更快
document.getElementById("btn").onclick = function(){
import("./count").then((res)=>{
console.log("模块加载成功",res.defauly(2,1));
}).catch((err)=>{
console.log("模块加载失败",err)
})
}
Preload
/ Prefetch
(浏览器空闲时间加载后续使用的资源,只加载不执行)
-
Preload:告诉浏览器立即加载资源
-
Prefetch:告诉浏览器在空闲时间才开始加载资源
共同点
:都只会加载资源,并不执行。都有缓存区别
:Preload加载优先级高, Prefetch加载优先级低
Preload只能加载当前页面需要使用的资源,Prefetch可以加载当前页面资源,也可以加载下一个页面需要使用的资源。总结
:当前页面优先级高的资源用 Preload 加载
下一个页面需要使用的资源用 Prefetch 加载
can I use
Preload相对于 Prefetch 兼容性好一点
Network Cache
Core-js
(解决js的兼容性问题)
过去使用babel对js代码进行了兼容性处理,其中使用@babel/preset-env 智能预设来处理兼容性问题。
它能将ES6的一些语法进行编译转译,比如箭头函数,拓展运算符。但是如果是async函数,promise对象,数组的一些方法等,它没有办法处理
此时JS代码仍然存在兼容性问题,一旦遇到低版本浏览器会直接报错,所以想让将js兼容性问题彻底解决
core-js 是专门用来做 ES6 以及以上API 的polyfill(垫片 / 补丁)在不兼容某些新特性的浏览器中使用该新特性
PWA (用的比较少)
在开发web APP项目一旦处于网络离线情况,就没法访问了;希望给项目提供离线体验。
PWA是:渐进式网络应用程序,是一种可以提供类似于native app体验的web app的技术。
在离线时应用程序能够继续运行功能。
能不通过service Workers技术实现的。
npm i workbox-webpack-plugin --save-dev
总结
我们从4个角度对 webpack 和代码进行了优化;
1.提升开发体验
- 使用 source Map 让开发或上线时代码报错能有更加准确的错误提示。
2.提升 webpack 提升打包构建速度
- 使用 HotroduteRepIacement 让开发时只重新编译打包更新变化了的代码,不变的代码使用缓存,从而使更新速度快。
- 使用 oneof 让资源文件一旦被某个 loader 处理了,就不会继续遍历了,打包速度更快。
- 使用 Include/Exclude 排除或只检测某些文件,处理的文件更少,速度思快。
- 使用 cache 对 babel 处理的结果进行缓存,让第二次打包速度更快。
- 便用Thead, 多进程处理 eslint 和 babel 任务,速度更快。(需要注意的是,进程启动通信都有开销的,罗在北较多代码处理时使用才有效
3.减少代码体积
- 使用 Tree Shaking 剔除了没有使用的多余代码,让代码体积更小。
- 使用 @babel/plugin-trensform-runtime 插件对 babel 进行处理,让辅助代码从中引入,而不是每个文件都生成辅助代码,从而体积更小。
- 使用 Image Minimizer 对项目中图片进行压缩,体积更小,请求速度更快。(需要注意的是,如果项目中图片都是在线链接,那么就不需要了。本地项目中静态图片才需要进行压缩。)
优化代码运行性
- 便用code split 对代码进行分割成多个 js 文件,从而使单个文件体积更小,并行加载js速度更快。并通过 import 动态导入语法进行技露加戟,从而达到需要使用时才加载该资源,不用时不加载资源。
- 便用 preload / prefetch对代码进行提前加载,等末来需要使用时就能直接使用,从而用户体验更好。
- 便用 Network cache能对输出资源文件;进行更好的命名,将来好做缓存,从而用户体验更好。
- 使用 core-js对js进行兼容性处理,让我们代码能运行在低版本浏览器。
- 使用 puA 能让代码离线也能访问,从而提升用户体验。