webpack相关

175 阅读8分钟

1、devServer如何引用静态资源?

例子如下,public是模板html,在打包之后,该html文件会作为入口文件。我想在index.html中引入abc.js文件。下面的引用方法是错误的。原因在于,打包之后的abc.js并不在content文件夹下。

image.png

正确的做法如下,先配置webpack.config,然后直接引用abc.js。由此可见,static的作用是告诉webpack静态资源应该去哪寻找。当webpack加载abc文件时,就会去磁盘中的content文件夹下寻找abc.js。

image.png

image.png

热更新的效果

将hot设置为true

image.png

如果不开启,那么修改代码,点击保存,页面会恢复到初始状态(相当于重新打开页面)。如果开启,会保留之前的状态。 www.bilibili.com/video/BV1Wy…

2、设置host

设置为0.0.0.0,则同一局域网内的其他所有主机可访问我的devServer。

image.png

3、changeOrgin

假设前端部署在localhost:8888端口,前端页面给localhost:9000端口发送请求,肯定会发生跨域问题。此时给devServer配置如下属性:

image.png

从此所有给localhost:8888发送的请求,都会被转发给localhost:9000。至此,跨域问题解决了。

但是我如果在服务端打印request的headers,如下图所示:host表示该网络请求的目标地址。该网络请求的目标端口是8888,而服务器部署在9000端口,这明显不对劲,服务器有可能会做拦截处理。如果changeOrigin为ture,则会把host改为9000。

image.png

image.png

原理如下:如果changeOrigin为ture,则把host改为target地址。

image.png

4.魔法注释,设置chunkname

4.1 什么是chunk

如果使用动态导入,那么category和about不会被打包到bundle.js中。而是分成2个单独的包(每个单独的包就是一个chunk),由于没有魔法注释,名字是webpack里配置的:[name]_chunk.js,其中,name是路径名字。

image.png

image.png

4.2魔法注释的用处

如上图,不设置name,name的值默认是路径名字。如果要设置name,那就得用魔法注释。

image.png

5.splitChunk

5.0动态导入分包的原理

当你没有配置optimisation的时候,默认配置如下图:splitChunks是async,表示异步加载的模块全部动态导入。 如果设置为all,表示把node_modules中的内容打包到vendors中。

image.png

5.1动态引入分包的缺陷

只有动态导入时,才会分包。但是我们的项目中,很多常用的包,都不是动态导入的。比如axios和react。在下图这种场景中,axios和react不会被单独打包,而是直接打包到bundle.js中。

image.png

5.2 如何把node_modules内的包,单独打包

把chunks设置为all。

image.png

5.3 vendors太大了?还想继续细分?

如果vendors大于20000B,那么会继续拆分。拆出来的包不能小于10000B。

image.png

5.4 如何把自定义的包,单独打包?

例如下图中的foo和bar,我想单独把它们打包,应该如何操作?配置cacheGroups。

image.png

image.png

5.5 如何设置chunkname

name变量会被替换为chunkId,而chunkId是自然数,从0开始递增。

image.png

这就会出现一个问题,如果about_chunk.js不见了(因为main.js中不再导入它),那么utils.js的编号就会变为3,导致重新打包

image.png

有没有办法固定chunkname?即使其他的包消失了,不影响我自身的编号?

image.png

总结如下:

image.png

6.preLoad和preFetch

6.1区别

一句话总结:preload跟随父组件并行下载,它是立即下载。prefetch是在浏览器空闲时下载,是将来某个时刻下载。

浏览器空闲是指浏览器在完成当前页面的关键任务(如加载、渲染、执行脚本等)后,没有其他紧急任务需要处理的时间段。在这段时间里,浏览器可以利用空闲时间来预加载那些可能在将来用到的资源。

image.png

6.2 prefetch浏览器空闲时加载

不使用predetch

最开始没有加载category和about,等到点击按钮之后,才会执行import()函数,才会执行代码。

image.png

image.png

使用prefetch

image.png

image.png

prefetch的原理是什么?

创建新的html标签(link标签),把它的rel设置为prefetch

image.png

link和script的区别是什么?

虽然link标签和script标签都可以用来导入JavaScript文件,但是它们之间有以下几个区别:

  1. 加载时机:使用link标签导入JavaScript文件时,浏览器会并行地加载文件,而不会阻塞页面的加载和渲染,这会提高页面的性能。而使用script标签加载JavaScript文件时,浏览器会在加载并执行完脚本后才继续渲染页面,这会阻塞页面的加载和渲染,降低页面性能。
  2. 执行时机:使用link标签导入JavaScript文件时,浏览器会将文件当做普通的JavaScript文件处理,并在文件中定义的函数或变量在其被调用时才执行。而使用script标签加载JavaScript文件时,浏览器会在加载并执行完脚本后立即执行其中的代码。

7.gzip压缩

可以加快首屏速度(因为网络传输时间短了).浏览器请求index.js时,服务器会先检查存不存在index.js.gz文件。如果存在gz文件,就返回gz文件。浏览器收到之后,会自动解压gz文件。

image.png

在打包的时候,如何开启gzip压缩?

image.png

8.publicPath:配置静态资源的路径

在output中配置publicPath,则所有的静态资源路径前,会自动添加域名(publicPath配置的域名) image.png

image.png

9.external排除某些包(不进行打包)

如果按照下图中进行配置,那么axios和React将不会被打包。为了引入axios和React,还需进行下图配置。(在html模板中,通过CDN资源导入某些包)

image.png

image.png

10.自定义loader

loader的本质

loader本质是一个javascript函数,通过module.export()道出。例如下图中./hy-loaders/hy_loader01.js就是一个函数。

image.png

只不过这个函数比较简单,参数是什么,返回结果就是什么。

image.png

loader的执行顺序

从后往前,因此下图中的执行顺序是 3,2,1

image.png

pitch的执行顺序

从前往后,因此pitch的执行顺序是1,2,3

image.png

image.png

loader的查找路径

从上面的例子可以看出,我们每次都会写出loader的完整路径。能否固定前缀,比如loader都写在node_modules文件夹下,那么是否能我直接写文件名,不需要写node_modules前缀呢?答案是可以通过resolveLoader来配置。

image.png

loader的链式调用

上一个loader的返回值,就是下一个loader的参数。但如果你在异步操作里面返回,下一个loader就拿不到值了。如下图所示,如果你在异步操作里返回,下一个loader拿到的等同于undefined

image.png

那么,如果我们想在异步操作中返回某个值,并且把这个值传给下一个loader,应该如何操作呢?

1.通过this.aysnc()获取callback函数

2.在异步操作中调用callback函数。其中,callback的第二个参数会被传给下一个loader。

image.png

loader获取options

我们在使用 loader 的时候,一般会传入某些 options,例如下图。

image.png

那么,如何在自定义的 loader 内获取 options 呢?第八行,通过this.getOptions()可以获取options。

image.png

11.自定义 plugun

详细版:juejin.cn/post/723918…

前置知识

基础版

HYCompiler 是一个自定义class。在他的内部,有一个hooks对象,这个对象上有无数个自定义 hook。例如,我们有个 syncHook,调用它的 tap( ) 可以监听事件:每当执行一次 HYCompiler实例对象.hooks.syncHook.call( ) 的时候,就会回调 tab( ) 内的回调函数。

image.png

bailHook

在上述例子中,执行完 回调函数 event1 之后,会继续执行回调函数 event2 。但是,如果我们改成 bailHook 之后,如果 event1 有返回值,那么后续的所有回调不再执行。

image.png

loopHook

只要返回值为 true,那么回调函数会重复执行。

image.png

waterfall

将上一个回调的返回值传给下一个回调函数。可以看到,它替换了第一个参数

image.png

parallelHook

两个回调函数并行执行,它不会等到第一个执行完,再执行第二个。注意,此处监听函数不再是tab( ),而是tapAsync( )。如果回调函数中有异步操作,比如settimeout,那么需要用tapAsync( )来监听。

image.png

seriesHook

第一个执行完之后,手动调用callBack(),才会执行后续

image.png

总结

image.png

image.png

webpack怎么执行我们写的loader

image.png

手写插件

详细版:juejin.cn/post/723918…

使用插件的时候如何传参数

image.png

如何获取传的参数

“AutoPlugin”可以随便写,这是你自己起的名字。

callback()是回调函数,你执行它之后,才会触发下一个回调;不执行的话,执行完本次回调就停止了。

image.png

通过 this.options 可以拿到调用者传过来的参数

image.png

image.png

Treeshaking相关

哪些会被treshaking

1.没有import的代码

2.被import,却没有调用的函数

如何开启

webpack.config 的 optimization 中,usedExport设置为 true

sideEffects

有些模块,即使没有被使用,也不会被treeshaking。比如 .css 文件,只要你 import a.css,这个css文件就会被打包。这是webpack自己判断的,它认为 css 文件只要被 import,就是有用的。

image.png

这些被设置过sideEffects的文件,即使没有被使用,也不会被删除