1、devServer如何引用静态资源?
例子如下,public是模板html,在打包之后,该html文件会作为入口文件。我想在index.html中引入abc.js文件。下面的引用方法是错误的。原因在于,打包之后的abc.js并不在content文件夹下。
正确的做法如下,先配置webpack.config,然后直接引用abc.js。由此可见,static的作用是告诉webpack静态资源应该去哪寻找。当webpack加载abc文件时,就会去磁盘中的content文件夹下寻找abc.js。
热更新的效果
将hot设置为true
如果不开启,那么修改代码,点击保存,页面会恢复到初始状态(相当于重新打开页面)。如果开启,会保留之前的状态。 www.bilibili.com/video/BV1Wy…
2、设置host
设置为0.0.0.0,则同一局域网内的其他所有主机可访问我的devServer。
3、changeOrgin
假设前端部署在localhost:8888端口,前端页面给localhost:9000端口发送请求,肯定会发生跨域问题。此时给devServer配置如下属性:
从此所有给localhost:8888发送的请求,都会被转发给localhost:9000。至此,跨域问题解决了。
但是我如果在服务端打印request的headers,如下图所示:host表示该网络请求的目标地址。该网络请求的目标端口是8888,而服务器部署在9000端口,这明显不对劲,服务器有可能会做拦截处理。如果changeOrigin为ture,则会把host改为9000。
原理如下:如果changeOrigin为ture,则把host改为target地址。
4.魔法注释,设置chunkname
4.1 什么是chunk
如果使用动态导入,那么category和about不会被打包到bundle.js中。而是分成2个单独的包(每个单独的包就是一个chunk),由于没有魔法注释,名字是webpack里配置的:[name]_chunk.js,其中,name是路径名字。
4.2魔法注释的用处
如上图,不设置name,name的值默认是路径名字。如果要设置name,那就得用魔法注释。
5.splitChunk
5.0动态导入分包的原理
当你没有配置optimisation的时候,默认配置如下图:splitChunks是async,表示异步加载的模块全部动态导入。 如果设置为all,表示把node_modules中的内容打包到vendors中。
5.1动态引入分包的缺陷
只有动态导入时,才会分包。但是我们的项目中,很多常用的包,都不是动态导入的。比如axios和react。在下图这种场景中,axios和react不会被单独打包,而是直接打包到bundle.js中。
5.2 如何把node_modules内的包,单独打包
把chunks设置为all。
5.3 vendors太大了?还想继续细分?
如果vendors大于20000B,那么会继续拆分。拆出来的包不能小于10000B。
5.4 如何把自定义的包,单独打包?
例如下图中的foo和bar,我想单独把它们打包,应该如何操作?配置cacheGroups。
5.5 如何设置chunkname
name变量会被替换为chunkId,而chunkId是自然数,从0开始递增。
这就会出现一个问题,如果about_chunk.js不见了(因为main.js中不再导入它),那么utils.js的编号就会变为3,导致重新打包
有没有办法固定chunkname?即使其他的包消失了,不影响我自身的编号?
总结如下:
6.preLoad和preFetch
6.1区别
一句话总结:preload跟随父组件并行下载,它是立即下载。prefetch是在浏览器空闲时下载,是将来某个时刻下载。
浏览器空闲是指浏览器在完成当前页面的关键任务(如加载、渲染、执行脚本等)后,没有其他紧急任务需要处理的时间段。在这段时间里,浏览器可以利用空闲时间来预加载那些可能在将来用到的资源。
6.2 prefetch浏览器空闲时加载
不使用predetch
最开始没有加载category和about,等到点击按钮之后,才会执行import()函数,才会执行代码。
使用prefetch
prefetch的原理是什么?
创建新的html标签(link标签),把它的rel设置为prefetch
link和script的区别是什么?
虽然link标签和script标签都可以用来导入JavaScript文件,但是它们之间有以下几个区别:
- 加载时机:使用link标签导入JavaScript文件时,浏览器会并行地加载文件,而不会阻塞页面的加载和渲染,这会提高页面的性能。而使用script标签加载JavaScript文件时,浏览器会在加载并执行完脚本后才继续渲染页面,这会阻塞页面的加载和渲染,降低页面性能。
- 执行时机:使用link标签导入JavaScript文件时,浏览器会将文件当做普通的JavaScript文件处理,并在文件中定义的函数或变量在其被调用时才执行。而使用script标签加载JavaScript文件时,浏览器会在加载并执行完脚本后立即执行其中的代码。
7.gzip压缩
可以加快首屏速度(因为网络传输时间短了).浏览器请求index.js时,服务器会先检查存不存在index.js.gz文件。如果存在gz文件,就返回gz文件。浏览器收到之后,会自动解压gz文件。
在打包的时候,如何开启gzip压缩?
8.publicPath:配置静态资源的路径
在output中配置publicPath,则所有的静态资源路径前,会自动添加域名(publicPath配置的域名)
9.external排除某些包(不进行打包)
如果按照下图中进行配置,那么axios和React将不会被打包。为了引入axios和React,还需进行下图配置。(在html模板中,通过CDN资源导入某些包)
10.自定义loader
loader的本质
loader本质是一个javascript函数,通过module.export()道出。例如下图中./hy-loaders/hy_loader01.js就是一个函数。
只不过这个函数比较简单,参数是什么,返回结果就是什么。
loader的执行顺序
从后往前,因此下图中的执行顺序是 3,2,1。
pitch的执行顺序
从前往后,因此pitch的执行顺序是1,2,3
loader的查找路径
从上面的例子可以看出,我们每次都会写出loader的完整路径。能否固定前缀,比如loader都写在node_modules文件夹下,那么是否能我直接写文件名,不需要写node_modules前缀呢?答案是可以通过resolveLoader来配置。
loader的链式调用
上一个loader的返回值,就是下一个loader的参数。但如果你在异步操作里面返回,下一个loader就拿不到值了。如下图所示,如果你在异步操作里返回,下一个loader拿到的等同于undefined。
那么,如果我们想在异步操作中返回某个值,并且把这个值传给下一个loader,应该如何操作呢?
1.通过this.aysnc()获取callback函数
2.在异步操作中调用callback函数。其中,callback的第二个参数会被传给下一个loader。
loader获取options
我们在使用 loader 的时候,一般会传入某些 options,例如下图。
那么,如何在自定义的 loader 内获取 options 呢?第八行,通过this.getOptions()可以获取options。
11.自定义 plugun
前置知识
基础版
HYCompiler 是一个自定义class。在他的内部,有一个hooks对象,这个对象上有无数个自定义 hook。例如,我们有个 syncHook,调用它的 tap( ) 可以监听事件:每当执行一次 HYCompiler实例对象.hooks.syncHook.call( ) 的时候,就会回调 tab( ) 内的回调函数。
bailHook
在上述例子中,执行完 回调函数 event1 之后,会继续执行回调函数 event2 。但是,如果我们改成 bailHook 之后,如果 event1 有返回值,那么后续的所有回调不再执行。
loopHook
只要返回值为 true,那么回调函数会重复执行。
waterfall
将上一个回调的返回值传给下一个回调函数。可以看到,它替换了第一个参数。
parallelHook
两个回调函数并行执行,它不会等到第一个执行完,再执行第二个。注意,此处监听函数不再是tab( ),而是tapAsync( )。如果回调函数中有异步操作,比如settimeout,那么需要用tapAsync( )来监听。
seriesHook
第一个执行完之后,手动调用callBack(),才会执行后续
总结
webpack怎么执行我们写的loader
手写插件
使用插件的时候如何传参数
如何获取传的参数
“AutoPlugin”可以随便写,这是你自己起的名字。
callback()是回调函数,你执行它之后,才会触发下一个回调;不执行的话,执行完本次回调就停止了。
通过 this.options 可以拿到调用者传过来的参数
Treeshaking相关
哪些会被treshaking
1.没有import的代码
2.被import,却没有调用的函数
如何开启
webpack.config 的 optimization 中,usedExport设置为 true
sideEffects
有些模块,即使没有被使用,也不会被treeshaking。比如 .css 文件,只要你 import a.css,这个css文件就会被打包。这是webpack自己判断的,它认为 css 文件只要被 import,就是有用的。
这些被设置过sideEffects的文件,即使没有被使用,也不会被删除。