像很多vue,react路由懒加载就是这样的,通过()=>import(’./xxx’)实现路由一个懒加载
实现一个组件懒加载
打包后的文件在这
可以看到一开始是没有加载我们的element.js文件的,当我们点击后
可以看到已经生成了一个文件。
打印出来是一个对象,导出的元素就在这个default里面。
这就是懒加载的应用。
上面那个例子点击按钮后大概是发生了两个步骤。第一个是下载element.js这个文件,第二个是浏览器解析运行js代码。
我们现在希望,当首页加载完,就是浏览器空闲下来的时候,我们就去请求这个文件,而不是等我们点击后再去请求。
webpack已经帮助我们实现了这个功能,只需要我们配置下,
魔法注射,跟命名一样,webpackPrefetch,pre提前的,fetch请求,提前请求。
在我们刷新完之后。他就会去请求,总是在最后面才请求。
当我们点击按钮后,他是从缓存中去拿这个文件并加载。
preload的作用是也是提前下载,但他是在父文件,也就是代码所在的文件被加载的时候,以并行方式开始下载,而prefetch是会在父文件加载完后加载。preload具有中等优先级,是会立即下载,用于当下时刻。而prefetch是在浏览器闲暇时下载,用于未来的某些时刻。
一般路由是设置preloade,而组件一般通过prefetch,一些用户可能不会点击到的就不做预加载处理。
optimization这个属性主要是用来性能优化的,比如chunkIds,splitChunks,还有runtimeChunk。
runtime相关的代码就是对模块引入的时候,比如import啊,require这些啊,就是通过runtime代码完成的。默认是放到main.bundle.js主模块中。或者是index.bundle.js。也就是runtime的代码是没有抽离出来的。
当我们设为true时,默认会打包出两个文件。为什么有两个呢,因为index与main都有runtime的代码。设为multiple与true效果一样
还有值为single,简单的意思。 只会打包一个包
还可以设置一个对象,
name属性设置名字。name值还可以写上函数
传一个入口对象进来。
根据name值不同也生成了两个文件。
认识CDN
CDN内容分发网络,简单地说就是通过相互连接的网络系统,通过利用靠近客户的服务器来给客户提供更好的体验,提高性能,降低成本。
假如A要请求一张图片a,但是a的服务器离他很远,而A的旁边有很多CDN,所以最靠近A的节点被我们称作边缘节点,他有一个父节点,父节点连接着源节点/原站。服务器会把数据a放在源站,然后第一次请求a时,A通过边缘节点向父节点发送请求,父节点向原站发送请求,拿到数据然后自己备份一份,在传给边缘节点,边缘节点备份后返回给A,下次假设有B也是同一个边缘节点也想访问a,因为有缓存了,所以会直接返回。假设有C,不同同一个边缘节点,但他们的边缘节点的父节点都是同一个,那么C会通过边缘节点向父节点发送请求,父节点因为缓存过了,所以直接返回。大大提高了性能。
第二种方式是自己的代码放到自己的服务器,第三方的代码放到cdn去。
第一种方式需要购买cdn服务器。
配置的话就是直接修改output.PublicPath,在打包时添加上自己的CDN地址。这个属性我们之前讲过,我们的index.html文件的script的src路劲就是域名+publicPath(默认是’’)+文件名
然后配置路劲
可以看到已经配置成功了。这样去加载时,就会去cdn上面加载。(公司用得不多)
找到第三方库,配置webpack.config.js的externals属性(与output同级),因为我们的第三方库一般是打包到vendors.js文件(通过optimization.splitChunks.cacheGroup)配置。所以要通过externals告诉webpack,哪些第三方库不要打包进去。然后在打包的index.html配置cdn地址,如Lodash与dayjs这两个模块。
第三方库一些是免费的。怎么配置呢
打包完发现,vendor.js的包已经不见了,证明第三方库不被打包进去。
当时代码跑起来时会报错的,因为没有第三方库的代码,也没有配置cdn。
接着我们要在Index.html模板上手动加上cdn
里面的cdn需要我们去官网找。(这种方法较为推荐)
但是这样配置不太好,因为开发生产模式都会用这种方式。比如我们开发的时候本地服务就很快,还要跑cdn的话是比较多余的。
可以看下打包后的index.html文件,cdn是没有加defer的,就是说下载完就会立即执行。
在开发环境中,没有必要使用cdn。
放到prod(图放错了)里面去,然后在Index.html模板上使用模板引擎
因为我们这个模板是ejs模板,可以使用外部传入变量。又因为我们一开始设置了一个值,porcess.env.NODE_ENV,所以就可以在ejs模板里面拿到这个值。
npm run serve 打开开发模式
没有刚才拿东西了,build一下
可以看到生产模式下是cdn,开发模式下是本地服务器。
比如我们现在引入了一个abc的库,这个库依赖于lodash,但是他没对他做引用,就是在abc的库的源码没有import lodash这个库,abc认为你的源代码引入了lodash库,所以当我们运行的时候就会报错。
所以shimming的作用就出来了,只要有某个东西引入了某个库,那么就自动导入这个库。
webpack内置一个插件叫ProvidePlugin
只要这样配置,就可以了。这个插件的作用是,当我们遇到的某个变量找不到时,会自动导入对应的库。
但是webpack不推荐这么用。因为webpack是提倡模块化,一旦我们用了这方式,webpack会不知道哪个模块对应哪个模块,我们需要编写封闭性的,不存在隐含依赖的彼此隔离的代码。
这是shimming的一个功能。还有另外的功能
我们现在的代码都是通过js分离的,css没有,我们想分离css代码,就可以通过这个插件了。将css文件抽到单独的文件。
我们这样打包后是不会生成一个单独的文件的。
安装 cnpm install mini-css-extract-plugin -D
生产环境才需要分离
所以在prod文件配置,filename是文件名和路劲,单单这样还不够,这个插件也内置了自己的Loader,我们之前使用style-loader来解析css,但是生产环境下不需要style-loader
如果是开发模式,会返回undefined,如果是生产模式,会返回true
改装成一个函数返回一个对象
所以引入这个插件后把style-loader换掉打包
这样就生成css文件了。
hash的区别
为什么有runitme的文件,因为只要是模块化,webpack通过runtimeChunk就会帮我们打包。
哈希值一摸一样,这个hash是怎么来的呢,是通过整个项目来的,也就是说,只要项目有一处地方改变,hash值就会改变。那么其他文件名也会改变,也会重新编译。
所以我们改成ChunkHash
可以看到chunkhash的hash值也不是一样的,也就是说改变一个文件的内容,只会修改那个文件的内容和名字,其他文件不会重新编译一下。但是这种情况也有缺点,比如我们打包css文件的时候,filename也是用chunkhash,那么这个css文件的chunkhash值跟引入他的文件的chunkhash值是一样的,比如main.js。那么main.js文件只要改变一点内容,除了main.js的打包文件的chunkhash会改变,css文件的名字也会改变,因为他们是同个chunkhash,所以这样也不行。
顾名思义,以内容来计算hash值,设置这个之后,一个文件的内容就智能影响自己的文件。
所以推荐,每个独立的包使用contenthash,包括chunkFilename,而我们打包的Bunle.js就使用chunkhash。