欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

webpack打包生成的map文件_一站式搞明白webpack中的代码分割

发布时间:2023/12/2 编程问答 57 豆豆
生活随笔 收集整理的这篇文章主要介绍了 webpack打包生成的map文件_一站式搞明白webpack中的代码分割 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

上次分析到通过devtool的配置项来设置source map,在线上环境可以通过设置成cheap-module-source-map来生成单独的map文件,但是map文件在线上环境会不会每次都加载呢?如果加载的话,会不会造成带宽和请求的浪费呢?

笔者也有这样的疑问,于是在网络上查了一下。后来才了解到,在浏览器中,只有在调试模式下才会自动下载map文件,平时线上环境的话,是不用担心这个问题的。

在使用webpack构建单页面应用时,为什么要进行代码分割?

  • 如果entry中只配置了一个入口,那么如果从这个入口文件开始引入的公共库的代码过大,打包出来会只有一个bundle文件。当浏览器端加载这样一个体积太大的bundle时就会造成加载过慢。

  • 通常来讲我们的公共库代码是不经常修改的。但是我们的业务代码是经常要修改的,如果打包到不同的bundle文件可以更好的利用浏览器的缓存,在浏览器端来复用之前的公共库的bundle文件。

  • 那如何通过代码分割来优化呢?

    在webpack3中可以通过CommonsChunkPlugin来进行代码分割,但是webpack4中,官方提倡使用SplitChunksPlugin这个插件,所以本次主要讲解的也是在webpack4中通过SplitChunksPlugin这个插件来实现代码分割的方法。

    首先要先弄懂一个预备知识点,就是在webpack中,什么叫做chunk,什么叫做bundle?

    下面这种图可以帮助我们更好地理解:

    在webpack的打包配置entry中有两个入口:index和utils。分别对应index.js文件和utils.js文件,其中index.js文件引用了common.js和index.css。那么webpack打包的时候就会把前三个文件作为一个chunk,utils.js文件作为一个chunk,但是在webpack配置中国年用MiniCssExtractPlugin插件抽离出了css文件,所以产生了.css和.js两个bundle文件。总之,chunk是webpack打包时候的一个概念,而产生出来的单个文件,可以在浏览器中运行的就叫做bundle。

    其实上文中通过在webpack配置文件中配置两个entry入口,其中utils把一些工具函数挂载到全局,也可以算是一种代码切割,但是有没有更加灵活的方式呢?我们来看下SplitChunksPlugin插件。

    SplitChunksPlugin插件的介绍可以在webpack的官方文档中找到:

    从文档中可以看到SplitChunksPlugin的默认配置如下:

    下面会一点点来讲解。

    代码分割有两种场景:一种是同步引入代码模块的分割,还有一种是异步引入的代码模块的分割。

    一、同步代码分割:

    在业务代码中引入lodash,通过之前讲的webpack-bundle-analyzer插件分析打包情况如下:

    可以看出我们的src文件和node_modules文件都是在一个bundle中。如果我们想把node_module中的库文件单独打包到一个chunk中,我们可以把官网上的SplitChunksPlugin的默认配置拷贝到打包配置文件中,然后做如下修改:

    其中chunks表示可以配置成initial、async、all分别表示静态引入、动态引入和两种情况下来进行代码分割。

    minSize为可以进行代码分割的最小包体积,默认为30000Byte。而在打包分析中我们看到lodash的包体积在webpack处理完后是将近70KB,大于SplitChunksPlugin的最小打包体积。所以在做如上修改以后,便能够将lodash打包到单独的chunk中。打包后的情况如下:

    从图中我们可以看到,lodash被单独打包到了叫做vendors~index.js的chunk中。

    下面再来完善一下上面分析的打包流程,满足了minSize的条件以后,顺着条件往下走可以走到cacheGroups配置,cacheGroups中有不同的对象,对象中的test即为测试正则,当引用的模块名满足了这个测试正则后,才会按照当前对象的规则打包。

    vendors这个键名即是打完包的前缀名,而automaticNameDelimiter中配置的就是前缀后面的连接符,后面就是引入此模块的entry中配置的入口文件名index。

    如果我们想要,自定义lodash打包的文件名,我们可以在vendors中配置filename为vendors.js如下:

    那么打完包的lodash的chunk就叫做vendors.js了,而cacheGroups上方的name:true的意思就是使cacheGroups中的filename生效。

    接下来介绍在splitChunks中剩余的配置:

    minChunks是什么意思呢?他的意思就是在entry中配置的入口,引用了该模块的最少个数,只有满足了最少有minChunks个chunk引用了当前模块,才会进行单独打包。

    maxAsyncRequests表示代码分割完后,同时可以请求的最大数量。

    maxInitialRequests表示首页中的最大请求数,如果代码分割后,首页请求的请求数大于这个数,就不会再继续代码分割了。

    二、异步代码分割:

    大家可能还不是很熟悉异步加载的语法,可以在官网的API部分中找到import异步加载的语法说明,其实就是ES6的一种语法:

    而在webpack的使用中,webpack通过一种叫做“魔法注释”的功能丰富了打包功能,下面会详细看到。

    在webpack中SplitChunksPlugin默认就会对异步引入的代码进行分割,但是为了支持异步引入模块的语法,我们还是需要安装babel的plugin-syntax-dynamic-import插件来支持异步加载的语法。

    下面来详细看下我们的业务代码:

    在index.js中,我们通过click事件动态引入了handleClick.js文件,其中注释的部分就是通过魔法注释来给分割的chunk命名为handleClick。

    在handleClick.js文件中,我们为文档添加元素(其中process.env.NODE_ENV是运行时环境变量,可以参考之前几期的推送)。

    从下面的运行效果我们可以看到,当网页刷新的时候,先加载出来index.html文件和index.js文件。当点击网页的时候,才会去请求handleClick.js文件,并且网页上出现“123”。

    其实异步代码分割还有一个大家可能更熟悉的名字——懒加载。

    但是,如果被异步加载的模块很大,我们在真实项目中操作完了再临时请求,会不会还是加载很慢。为了解决这个问题,可以使用魔法注释中的webpackPrefetch来让浏览器加载完首页的js文件后空闲的时候去加载异步分割的bundle文件。

    参考:

    https://segmentfault.com/q/1010000000396077

    https://juejin.im/post/5cede821f265da1bbd4b5630#heading-15

    https://coding.imooc.com/lesson/316.html#mid=22363

    总结

    以上是生活随笔为你收集整理的webpack打包生成的map文件_一站式搞明白webpack中的代码分割的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。