webpack
为什么用webpack
- 浏览器端实现模块化
如果使用es6一个大型工程会有大量的模块,每个模块都需要请求,会导致严重的性能问题,现阶段浏览器不支持commonjs只支持es6,如果使用的第三方
库是cjs写的就会不兼容 - 浏览器端在使用外部依赖的时候不能用import导入,因为不允许从node_modules文件夹中找,不开放的原因是包可能是common.js导出的,其次就是导入的
包如果有大量的依赖那么就会导致严重的性能问题 - 开发时态和运行时态不同的文件期望
webpack的安装和基础使用
-
wp基础基于什么
- wp是基于noed开发的,因为中间的打包过程需要读文件而浏览器端无法读取文件
- 基于模块化的,因为在压缩依赖的时候它是根据模块的导入语句的
-
wp安装(用npm安装)
webpack:核心包,包含构建过程中的所有api
webpack-cli:提供了一个简单的cli命令行,它调用了wp核心包的api来完成构建过程(了解源码可以不安装此,用js来调用也可)
一般安装在本地,因为需要用到webpack的步骤就在中间的文件压缩过程,压缩过之后的代码在执行的时候不需要webpack所以在安装的时候需要装在开发需求中 -
基础使用
默认情况下wp会以./src/index.js作为入口文件分析以来,打包到./dist/main.js文件中,所以需要在根目录下建一个src文件夹,然后将所有文件写在这里
可以在package.json中配置脚本以方便使用打包命令,在开发完之后直接运行 npm run build 就可以了
开发完之后所有需要打包的文件必须放在src目录下,并且打包的时候终端必须是src目录下的终端
现在每次打包完之后机器会报给一个warning是说缺少了mode参数,这个参数用来规定打包的结果是用于开发环境还是生产环境,如果在生产环境运行会进行精压缩
如果在开发环境那么他会让打包得适合调试,默认生产环境。在打包时配置:
npx webpack --mode=development 表示打包后是开发环境
npx webpack --mode=production 表示打包后是生产环境
npx webpack --mode=development --watch 表示监控,如果src目录下的文件发生变化会自动重新打包
所以在配置脚本的时候一般配置两个,一个是生产环境一个是开发环境 -
webpack的模块化兼容性
因为wp支持commonjs和es6的模块化标准所以需要理解- 同模块化标准
它和正常是一样的 - 不同模块化标准
不同的导出和导入标准
1.用es6导出用cjs导入
最终结果是会导入一个对象,对象内罗列导出的属性
2.cjs导出es6导入
最终结果是导出一个对象。对象罗列导出的属性
需要注意的是如果导出时使用es6的default导出一个对象,那么在接收的时候如果想接收一个对象那么就要使用.default因为导出的结果都是一个对象,如果直接
使用的话就会是一个对象里有一个对象
- 同模块化标准
-
炫酷的数字查找特效(练习)
-
编译结果分析(mymain.js)
所谓编译结果就是经过webpack编译的main.js
编译的结果不会污染全局变量,所以将每个模块放在一个函数环境下来执行,总体来说就是将执行环境写成一个立即执行函数,将所有模块封装成一个对象,对象中的每一项
的项名都是模块的路径,项是一个函数,每个函数将需要的参数传入(如exports等),将这个对象传入这个立即执行函数中,在执行每个模块的时候调用这个路径下的方法- 具体方法
根据模块化的思想,在运行一个项目的时候首先运行一个入口文件,文件中首先需要去读取require(导入的模块)的模块,拿到所有导入的结果,所以这个立即执行函数
内部需要首先完成require方法的构建此方法用于运行模块对象中的方法
每个模块对象都有的参数在执行的时候需要先行给出,module参数就是一个包含了exports(要导出的结果)的对象那么先行构建此对象,有的是modile.exports那么
因为是同一个对象的下属属性就直接传入即可,然后将构建的require传入(这里相当于在内部调用自己,即递归如果执行的模块依赖别的模块那么就会向下继续执行直到
不再依赖就会层层返回结果)然后用一个参数来获取并保存结果即可
然后在函数内部用require设定默认入口文件就可以执行了 - 细节优化
模块化中有缓存,要实现缓存,直接在立即执行函数的顶端定义一个缓存的对象,用于保存每个模块的导出结果以避免多次执行同一模块,在require中,在执行导入模块前
首先判断这个模块是否有缓存如果有就直接返回,如果没有就执行在返回之前将之缓存起来
模块对象中的模块内容在正常wp中会用eval来进行封装,因为如果用老方法会不好调试,eval方法会将内部的字符放在一个纯净的环境之中执行不会有其他代码的干扰
可以在其中写入代码的路径注释 【# sourceURL=webpack:///./src/b.js?】 浏览器会直接将这段代码的在原先的模块路径显示出来方便调试
- 具体方法
-
配置文件
为了更灵活的控制webpack的行为我们会配置一个文件,默认webpack会读取webpack.config.js文件作为配置文件,这个文件配置在根目录下(src)
可以手动指定配置文件 npx webpack --config 123.js 通过这个命令就制定了一个文件为配置文件
配置文件必须通过commonjs导出一个对象且必须满足node语法,因为在执行打包的时候是在nodejs环境执行的,此文件在打包过程中需要运行的
1.配置
mode 配置打包模式,有开发环境有生产环境
entry 配置入口文件
output 出口,表示打包完成后的结果文件信息,为一个对象
filename 控制打包结束后的文件名 -
编译过程
步骤
初始化--编译--输出
初始化
此阶段wp会将cli参数,配置文件,默认配置融合形成最终配置对象,对象配置的处理过程使用了yargs第三方库
编译- 创建chunk
他是在打包过程中的概念翻译为块,表示通过某个入口找到的所有依赖的统称,chunk可能会有多个且有自己独立的名字
每个chunk都至少有两个属性
name 默认为main
id 唯一编号,如果是在开发环境那么id和name相同,如果是生产环境id就是一个一0开头的数字
devtool:"source-map" 明示打包过程 - 构建所有的依赖模块
【AST在线测试工具 https://astexploren.net/】
1.流程
1.首先找到入口文件
2.检测chunk中的模块记录(这里因为是首次加载所以没有任何记录,继续往下执行)
3.读取入口文件内容(不是运行,只是将其读出,)
4.使用AST进行语法分析(语法分析是将读取到的代码解析成语法树,语法树的作用是清晰的得到文件的依赖,方便遍历)
5.将依赖记录到dependencies依赖数组中,这里会记录依赖的完整相对路径,方便树形遍历(深度优先,就是一条找到根然后在返回去找另一条)
6.替换依赖函数,将导入的方法require变成_webpack_require
7.将转换后的代码进行保存与模块的id(完整相对路径)形成表格
8.进行下一次循环(即刚读取到的入口文件的依赖数组的第一项,循环一圈之后如果第一项依赖其他的模块则优先读取第一项的dependencies数组这一线
读取完毕之后才会层层向上返回,这里是深度优先)最终形成依赖的id和代码的表格 - 产生chunk assets
根据模块列表生成文件列表即chunk assets,所谓文件列表就是文件名和文件内容一一对应的一个表,文件内容是将上一步读取到的每个模块的内容封装在一个函数里并不执行
通过这个文表即可基本构成打包过后的文件
chunk hash
hash是一种算法,它的作用是将一个任意长度的字符串转换成一个固定长度的字符串,且保证原始文件内容不变
这里有一个chunk hash 值是将表里的所有文件内容合并在一起变成一个24位的hash值,其作用是判断原文件有没有变化 - 合并chunk assets
将chunk的多个assets(文件列表)合并在一起,生成总的文件列表,产生一个总的hash(现在写的多只有一个chunk),如果配置多个入口则会最终输出多个文件
输出
webpack利用node的fs根据编译产生的assets(文件列表)生成对应的文件
- 创建chunk
-
入口和出口
出口
出口指的是将所有chunk assets合并生成的资源结果,出口将之配置,通过output配置(在webpack.config.js上配置)
output(配置的时候是一个对象)
path 必须配置绝对路径,表示资源放置的文件夹,默认是dist文件夹(手写不提倡,因为运行在不同的操作系统对绝对路径不一样,运行在不同电脑那么路径可能发生变化)
配置时用path.resolve(_dirname,"target")
filename 配置导出资源的文件的规则(合并后的js代码文件,因为chunk打包后除了js打包文件可能还有其他的文件),最简单的是直接一个文件名,也可以在这里写路径
它会在打包的时候依照此存储
filename 以上是静态配置,当配置了多个入口之后静态配置就会出问题,所以最好是动态配置 fillname : "[name].js"
有时候浏览器会自动缓存请求到的js文件,当服务器的文件发生变动的时候由于浏览器的文件缓存,导致浏览器不更新,这个时候我们希望当文件发生改动时文件名也相应变化
以达到消除缓存的目的,这个时候可以使用 hash 命名
filename: "[name].[hash].js"
这样命名当服务器文件发生变化则文件名相应变化,浏览器则会发起请求,不会出现前后不一,但是这样写会导致文件名过长很丑陋
filename: "[name].[hash:5].js"
这样在hash后加个冒号加上数字表示保存几位哈希值,这样就会好很多,在打包过程中会生成chunk,他也会有hash所以我们也可以用它
filename: "[name].[chunkhash].js"
这样写可以减小影响范围,因为如果一个文件变了只会影响一个文件名入口
入口配置的是chunk(入口文件,默认一个)
entry(配置的时候是一个对象)
main:"./index.js" 此为默认配置 (属性名:chunk的名称 属性值 入口模块)可以设置多个入口,比如设置一个 a:"./a.js" 【这就有一个问题,因为默认只有一个出口
那么这里却有两个入口需要两个最终文件,这样就会出现冲突,所以出口的配置可以是动态的】 -
入口和出口的最佳实现
- 一页一个js
适用于公共代码不多 - 一个页面多个js
多个js互不相干,可以分别打包 - 单页应用
页面所有内容由js控制
- 一页一个js
-
loder
本质就是一个函数它的作用是将某个源码字符串转换成另一个源码字符串返回
loder是一个一个的js文件,文件导出一个函数,函数传入wp处理过程中读取的文件内容,经过处理返回一个字符串(处理过的文件内容)然后去进行抽象语法树构建,但是只是写了还是无法应用的,因为
webpack不会自己去找- 流程
1.判断当前模块是否满足某个规则(可配置规则)
true的话读取对应的loders封装成数组
false的话给一个空数组
2.拿到loders数组之后开始遍历数组,从最后loder一个开始处理模块,知道循环完数组得到最终需要处理的模块代码进入语法树构建 - 配置
在webpack.config.js中配置
1.配置模块(模块怎么去解析,解析要经过那些loder)
module对象
rules : [] 是数组,模块的匹配规则,从后往前看,每个规则是一个对象
test 一个正则表达式,匹配模块路径
use :[] 匹配到之后使用哪些加载器(要用到的loder)数组内部是一个一个的对象
loader : 配置加载器的路径
- 流程
-
处理样式(练习)
-
处理图片(练习)
-
plugin
实现当某个阶段实现什么样的事的时候使用-
本质
plugin的本质是带有apply的方法对象
var plugin = {
apply : function(compiler){} }通常使用类
-
使用
需要在配置文件配置
先导入模块MyPlugin
plugins : [
new MyPlugin()
] -
原理
从初始化开始会创建一个compiler对象,贯穿整个打包过程,打包过程中在编译的时候会在前内部创建一个compilation对象直至打包结束(此阶段为这正式打包阶段
在监控文件变化的插件工作时如果文件发生变化则会重新构造一个compilation,compiler不会重新创建),它相当于在打包过程中注册事件;导出的apply方法会在
创建完compiler对象后开始运行,所以此方法在整个打包过程只会运行一次,事件就在apply中注册的,事件的注册需要用到hock和compiler
var plugin = {
apply : function(compiler){
compiler.hocks.done.事件名(name,function(compilation){
//事件处理函数
})
}
}
文档【https://www.webpackjs.com/api/compiler-hocks】
-
-
添加文件列表(练习)
-
区分环境
在不同开发阶段需要的配置时不同的,为了方便我们使用此方法
配置文件返回一个函数,在函数内部判断此时的开发阶段,返回不同的配置对象
module.exports = function (env){
//通过传入的参数来进行判断当前环境
//在使用webpack命令打包的时候传入这个参数(这一步可以在package文件中的script中配置)
}
npx webpack --env.abc -
其他细节配置
3. 常用扩展
1. 清除输出目录
clean-webpack-plugin 一个Webpack插件,用于删除/清理您的生成文件夹(在使用hash来进行文件打包命名之后,如果改动文件重新打包则会出现新的文件名,老的文件
不会自动删除,此插件就是解决此问题的)
安装此插件之后在配置文件中导入此插件然后在plugin中配置就好()
2. 自动生成页面
html-webpack-plugin 在引用了上插件的情况下,每次打包都会删除创建dist目录那么我们要测试我们的打包代码会在dist目录中写入一个html并引用,删除创建后这个
html就被删除了,此插件用于自动在dist目录下生成并引用js和html,可配置如template 用于指定生成html的模板
如果打包文件的时候配置了多入口,又希望html文件配置指定的js可以配置chunks:[]
默认值为all表示所有都用,即所有都应用到一个html
可手动配置要在此html中引用的具体文件chunk
要生成多个html就多实例化几次插件包就好
3. 复制静态资源
copy-webpack-plugin 用于移动静态资源
4. 开发服务器
为开发阶段创建的服务器,用以模拟服务器
webpack-dev-server 既不是插件也不是库,要运行这个库直接用npx来运行即可
npx webpack-dev-server 这就搭建好了一个服务器
配置
devServer 为一个配置对象
port:8000 配置监听的端口号
open: true 表示开启之后自动打开浏览器自动访问
index: "index.html" 如果直接访问端口号默认访问的页面
stats: 控制控制台输出
proxy:{} 为了解决页面访问其他页面的时候的跨域问题(没开发完的时候请求后端数据)【开发完之后js和html会放在一个域下所以前后端连接不会出现跨域
但是在开发阶段前后端还没有放在一个域下所以会有跨域;在正式生产的时候访问秩序写总段不用写具体域,会自动拼接域】当请求某个字段的时候由服务器去
请求不会有跨域问题
"/api":"http:www.baidu.com" 表示只要请求包含/api就会将请求地址改为后边的(不更改请求头等)
"/api":{} 可以配置成一个对象
target 表示请求地址
changeOrigin : true 表示将请求头中的host和origin改成地址对应的就可以成功访问了
5. 普通文件处理
file-loader 将文件解析/在 URL 中,然后将文件发出到输出目录中,用法和loader一样,loader在配置时需要完全符合格式,不要简写容易出错(生成新文件)
url-loader 将以来的文件转换为一个base64字符串,不生成新文件
6. 解决路径问题
有的情况下如在使用file-loader打包图片的时候,file-loader会先将图片复制到指定文件夹,然后将这个文件的名字通过require返回回来,但是在这一切完成之前
整个项目的打包还没有完成,也就是说它不知道最终的js文件在哪,也不知道最终的html文件在哪,在网页上生成img中写入这样的路径(插件记录的路径)服务器访问的时候
会将当前访问的页面地址后直接拼接这个路径,这样就会出现访问不到图片的情况
面对这样的问题可以依靠publicPath解决
publicPath 配置到output中,它会生成一个静态字符串在打包的js文件中的 webpack_require.p = "";中,它的本质就是一个字符串,如果要输出它就用
console.log(_webpack_require.p)这里就更加说明这就是一个普通字符串;但是有的plugin和插件会用到这个字符串
如htmlwebpackplugin插件 它会在引用js的时候将这个字符串拼接到原路径最前边,由于这个特性我们通常将之配置为一个 "/"
如果两个插件用到的publicPath不一样那么就在插件配置内部配置
7. webpack内置插件
1. 用法
导入webpack,然后 new webpack.插件名(options) 在配置文件的plugins中配置
2. DefinePlugin
定义全局常量,对象内以键值对的形式存在,属性值是用飘字符括起来的字符串,当在打包过程中生成了抽象语法树之后会查看代码如果有键的内容就会把它替换成
值的内容
3. BannerPlugin
给chunk加备注,对象里有banner属性,属性值是用飘字符括起来的键值对
4. providePlugin
让需要大量使用的模块实现自动加载,对象内以键值对的方式存在,键是函数名,值是对应函数的模块如
$ : 'jquery'
8. 区域查询(练习) -
css工程化{
- css工程化概述
问题
1. 类名冲突
嵌套过深不利于阅读,压缩,编译,复用,嵌套过浅会造成命名冲突
2. 重复样式
样式改动文件量大修改会很繁琐
3. 文件细分
解决
类名冲突
1.命名约定
2.css in js
3.css module
样式重复
1.css in js
2.预编译器
文件细分
webpack - 利用webpack拆分css
有两个loader,需要配合使用
css-loader
此插件的作用是将导入的css文件内容转化成js代码
style-loader
此插件的作用是将上插件转换的字符串导入到页面上使其生效
这两个插件时配合使用的首先需要第一个将之转化成js代码,然后再有第二个将之在页面加入,所以在配置loader的
时候需要将第一个写在最后变,第二个写在最前边(由loader的原理决定) - BEM
用于解决类名冲突(类名约定)
类名将由3部分构成 Block Element Modified
Block 大区域,最顶级的区域,如头部
Element 大区内部的组成部分,如头部的一个图标
Modified 此区可选,表示状态,如头部的一个图标是显示还是消失
大工程的时候有的会加上前缀
l 这个样式适用于布局的
c 组件
u 工具
j 给js拿元素的 - css-in-js
用js对象来描述css样式,极其灵活,应用面机器广泛 - css module
思路:
1.类名冲突往往发生在大型项目的构建中
2.大项目使用构建工具搭建工程
3.构建工具可以将css精准分块
4.和js的变量一样,同一个模块中不会出现类名冲突,不同模块不会冲突,要实现让css不同模块不冲突就行了
实现原理
简而言之:在将在将css文件进行构建的过程中将类名使用loader进行修改,修改就使用模块路径和类名形成一个hash值,这样不同模块就不可能出现冲突
具体:
css-loader实现了css module但是默认是不使用的需要在options里将module配置成true,配置完后生成文件的类名就发生变化了,但是也仅仅是类名发生变化
并没有添加到页面
为了解决这一问题css-loader会导出一个对象,对象会将原先的类名和改变后的类名进行一一对应,我们可以拿到这个对应关系然后在js代码中用对应关系修改dom
类名,但是还是无法使用,因为css-loader转化后的代码还没有被应用到页面
此时使用style-loader将css-loader导出的对应对象导出并添加到style中,这时修改dom的类名之后样式表就开始生效
流程:css-loader在编译期间将css文件的类名通过hash值进行修改,导出复杂的对应对象,style-loader将经过修改的css代码引用到页面并修改前者
导出的复杂对象将之简化
特殊:
不想让某类被修改类名(共用类)
:global(类名) 此类将不会被修改
没使用以上的将会默认使用local
控制最终类名
给css-loader的module的localIdentName配置名字
注意事项
1.此方法一般应用于大型项目
2.只处理顶级类名,不要使用类名嵌套
3.只处理类名和id其他的都不会处理 - 预编译器less
less的安装
npm i -D less
less的使用
lessc less less代码文件名 编译后的css文件 - 在webpack中使用less
之前已经解决了css如何和webpack连用并使用module成功解决了类名冲突的问题,现在学习了less,less的原理是通过编译器将less代码转换成css代码,那么只需要在之前的
步骤前加一步将less代码通过loader转换成css代码即可:
less-loader 代码转换器,需要最先使用所以要配置在loader的最后边
less less核心编译器,需要安装
之后的步骤就是用css-loader将css代码转换成js代码,可以在此使用module将类名转换成hash值,避免命名冲突问题,然后由style-loader将转换好的js加到页面中 - PostCss
理念
如同webpack一样的思想,将所有的事集中处理
原理
css源文件--parser分析代码生成语法树--插件进行代码操作--转换成字符串--导出新的css
安装
postcss-cli
postcss
使用
postcss 源码文件 -o 输出文件
配置文件
这是一个相对独立的东西所以需要一个独立的文件来进行配置
postcss.config.js
插件
postcss-preset-env 预设环境,预安装插件,自动添加厂商前缀,支持未来的css语法。需要配置在plugins中配置
postcss-apply 实现在css中编写属性集
stylelint 在书写不规范的代码时报错,这是一个相对独立的插件,可以离开postcss独立运行,需要配置规则,可以下载规则库
stylelint-config-standard 规则标准库
.stylelintrc 配置文件,vscode如果装了stylelint插件只要由这个文件就会按照这个配置进行报错 - 在webpack中使用postcss
根据原理:
postcss文件--postcss解析--css代码--css-loader--style--loader--应用
需要安装
postcss
postcss-cli
安装好后在webpack配置文件中按以上流程配置
然后配置postcss:
postcss.config.js 配置postcss行为
.browserslistrc 配置兼容浏览器版本 - 抽离css文件
需要用到 mini-css-extract-plugin 库,此库包含两个部分,一个plugin和一个loader,plugin负责生成文件,loader负责记录生成的css文件内容
同时录导入启动module后的样式对象
原理:
在编译过程中通过自带的loader记录生成的css文件内容,plugin生成一个css文件,loader将记录的文件内容装进生成的css文件,然后将集成的
css文件放入指定的文件目录之下,这里既然生成了css文件就不需要style-loader来将css-loader的内容导入页面了,所以将style-loader替换成
插件自带的loader
使用:
首先安装mini-css-extract-plugin库
导入mini-css-extract-plugin
在plugins中启动此库
将需要替换的style-loader替换成【库名.loader】
- css工程化概述
-
js兼容性{
- babel的安装和使用
原理:
各式语言--babel编译--兼容性语言
安装:
npx i -D @babel/core
npx i -D @babel/cli
使用:
npx babel 文件名 -o 结果文件 -w 按文件名编译并保持监控
npx babel 目录名 -d 结果目录 -w 按文件目录进行编译
配置:
因为babel实际上不做任何事,做事的是babel的插件,所以需要配置,在 【.babelrc】 文件进行配置
{
"presets" : [], 配置预设插件
"plugins" : [], 配置插件
} - babel预设
安装
@babel/preset-env
配置
在 【.babelrc】中配置预设,如需给预设进行额外配置则将这个预设配置成数组,第一项为预设名第二项
为预设的配置对象
usebuildins 预设只会转换语法不会转换api所以配置这个之后就会转换api了,转换方式是从corejs导入
所以需要先安装corejs,将此项配置为usage即可 - babel插件
插件在预设之前运行,预设从预设数组末尾开始运行,插件从插件数组第一位开始运行,预设无法转换处于早期的语法,这时需要用到插件
插件:
@babel(plugin-proposal-class-properties)
插件如果需要配置则如预设一样,将之配置为数组,数组第一项为插件名第二项为配置对象 - 在webpack中使用babel
使用很简单,需要安装 @babel/core @babel/cli babel-loader,然后在loader中配置babel-loader,然后配置 .babelrc 文件即可使用 - 对类的转换
此处教的是阅读源码的方法,属重点,需要反复研究 - async和await的转换
此处教的是阅读源码的方法,属重点,需要反复研究
}
- babel的安装和使用
-
性能优化{
- 性能优化概述
webpack这块的性能问题包括三个方面:
1.构建性能 生产环境无所谓,因为生产环境代码很久才打包一次,而开发环境时打包频繁
2.传输性能 打包后的js传输事件,可以控制总传输量,控制文件数量,使用浏览器缓存
3.运行性能 书写高性能代码
不要过早的去关注性能问题,只要更多的关注自己代码的优雅程度 - 减少模块解析
模块解析是什么:
模块解析是打包过程中的抽象语法树构建,依赖保存,依赖替换这三个步骤
所以如果要打包的模块没有依赖其他模块他就可以不进行这三个步骤,就提高了构建性能,要让某个包或文件不打包只需在配置文件的module下进行配00置
noParse : /匹配不需构建的文件的正则表达式/ - 优化loader性能
- 限制loader的影响范围
可以通过配置文件来控制不受loader影响的文件
module.rule.exclude : 配置排除在外的文件
module.rule.include : 配置要处理的文件,没包含的不处理 - 缓存loader的结果
若有文件不会变化,那么编译结果就不会变化,用 cache-loader 配置缓存
将cache-loader放在loader的最前边就好
cachedirectory : "file" 配置缓存文件的放置位置
为什么cache-loader放在loader的最前边却可以影响在自己之前运行的loader,是因为在loader运行之前有pitch的过程 - loader运行开启多线程
使用thread-loader会开启线程池
- 限制loader的影响范围
- 热替换
在使用devserver开发的时候,每次文件的改动都会让浏览器刷新页面彻底重载代码,这样很不利于开发,热更新就是用来解决这一问题的
使用:
需要在devserver中配置 【hot: true】
需要在plugins中配置 【new webpack.HotModuleReplacementPlugin();】 可选
需要在入口文件写入 if(module.hot){module.hot.accept()}
原理:
devserver会自动开启一个websocket通道当文件改动之后浏览器会运行webpack打包文件中的 loaction.reload 命令,会彻底重加载文件,
而使用了热替换之后浏览器依然不会有作用需要加上判断代码,如果加了就会接受热更新,运行插件,先由服务器向浏览器发出信息,告诉浏览器
文件变动了,然后浏览器会发送请求请求更改的部分代码,请求到之后会将源代码替换。
这个方法可以用在css打包上,但是不能使用 mini-css-extract-plugin 因为它运行需要重写文件,只可以用 style-loader 因为文
导入的时候就需要用到它 - 手动分包
流程:
1. 打包公共模块的代码
2. 正常打包
3. 手动引用公共模块代码
原理:
先将公共模块的代码打包,并将公共模块的代码的全局变量暴露出来,用一个json文件记录暴露出的信息然后正常打包时检查这个json文件,已经
打包的公共文件就直接按照路径导入变量,极大的减少了打包代码的代码量,然后需要在页面上手动引用打包好的代码
配置:
首先配置一个控制公共代码打包的配置文件,名字随意,有多少个公共代码块就配置多少个入口,入口需要写成数组
配置公共出口的时候需要配置一个library,名字就是name作用是暴露出每个bundle的全局变量
在插件中需要配置 webpack.DllPlugin 的 path 绝对路径,此绝对路径是文件打包时的资源清单的路径,以及 name
是资源清单的名字
配置正常打包的配置文件,首先配置文件夹自动清除插件不能清除公共文件的文件和文件夹
然后配置在正常打包的时候首先查看资源文件根据资源文件打包以减少对公共文件的打包 配置 webpack.DllReferencePlugin 的 manifest
它用来获得资源文件导出的json对象 - 自动分包
原理:
首先在正常打包过程中在生成chunk的阶段,在基础chunk生成完毕之后会读取这些chunk根据定义的缓存组确定哪些包需要生成新的chunk
,生成新包之后删除原文件中的包依赖,并且修复原包
webpack用的是splitChunksPlugin插件进行打包
配置:
webpack.optimization.splitChunks: {
chunks : 设置宏观哪些chunk需要分包,有三个配置 initial【普通chunk】 async【异步chunk默认】 all【所有chunk】
maxSize : 控制分的包的最大字节数,如果大了就会尽量将其拆成小的,拆分是以模块为单位的,不会拆分模块,所以会存在拆分后大于配置
配置分隔符,打包后的文件名分隔符
minChunks : 配置一个包至少要多大才会被认为是一个chunk
}
webpack.optimization.splitChunks.cacheGroups : {
//此为缓存组,缓存组用于控制缓存策略,分包策略基于缓存组,缓存组的配置会影响一类文件的分包,默认有两个缓存组
//一般这两个就够用了,但是在遇到需要对js以外的文件进行分包的时候就需要配置了,比如对css进行分包
style : { //一个对象表示一个缓存组
test : 正则匹配要打包的文件类型
minSize : 配置最小大小
minChunks : 配置chunk引用数
}
} - 代码压缩
https://terser.org/
用查文档
纯函数:
若函数无副作用,所有的返回都仅依靠参数则为纯函数
无副作用:不对外部产生影响
需要对css进行压缩的时候就配置optimizeCssAssetsPlugin插件进行配置 - tree shaking
原理:
webpack会在分析依赖的时候,会对没有用到的代码进行标记,然后使用loader删除没用到的代码 - 懒加载
- ESLint
此为代码风格检查,一般会配合编辑器使用
使用:
首先需要初始化工程文件夹
然后用 【eslint --init】 初始化eslint,初始化之后会生成一个配置文件,配置相关信息查文档 - bundle analyzer
此为一个分析工具,在代码打包完毕之后分析代码的可深度优化性
使用:
首先安装【Webpack-Bundle-Analyzer】
导入该包的插件【requir("Webpack-Bundle-Analyzer").BundleAnalyzerPlugin】
plugins中实例化插件可进行配置,具体看文档 - gzip
此为一种文件压缩算法,在前端BS架构中使用,或在webpack中使用
在bs架构中的使用方法:
浏览器向服务器说明可接受压缩版本,服务器接收到根据此对文件进行相应处理然后返回给浏览器,但是压缩的过程会消耗时间
所以webpack可以提前将文件预压缩,但是这样会牺牲服务器的灵活性
使用:
先安装【compression-webpack-plugin】插件并导入
在plugins中实例化插件,需要配置可以查看文档
}
- 性能优化概述
-
补充和案例{
赶进度中,复习需学习
}