通常为了开发效率,我们会使用vue-cli来创建项目,这样创建的项目默认会进行代码拆分编译。但是如果是自己配置的webpack环境,熟悉codesplitting的相关知识还是很有必要的。为什么要进行代码拆分?在配置webpack的过程中,很多时候我们的webpack入口只写了一个入口:'${sourceDir}/index.js'。默认情况下,只会生成一个bundle文件,包括第三方库,不同页面使用的公共代码和业务逻辑,难免会造成bundle文件过大,影响页面的首次加载速度,所以我们需要对代码进行拆分,加快进入速度页面第一次。代码切分的思路首先将第三方库和公共代码抽取出来。由于这些代码变化较少,可以将它们打包成一个文件,这样文件每次上线都不会变化,可以充分利用网络缓存,加快文件下载速度。详细点,第三方库是js文件,公开代码是js文件。然后,按照路由(页面)划分代码,为每个页面生成一个js文件,这样每次第一次进入,只会加载公共代码和本页面使用的js文件,而不是从其他页面加载不相关的代码。最后如果进行细化分割,根据组件的用途进行划分,实现组件的懒加载。比如页面中不同的tabs可以根据tabs的展示方式进行划分,将需要用户点击或者主动操作的组件展示出来组件懒加载,这样可以更细粒度的代码拆分在页面级别。代码拆分实际第三方库和公共代码拆分第一步是拆分第三方库,比如vue,vue-router,vuex,axios等三方库,放到vendor.js,然后是utils,common文件等。把它放在common.js中。这些都可以通过webpack的entry和splitChunk配置来实现。修改入口配置:{//...entry:{//将常用代码放在commoncommon:[`${sourceDir}/utils/index.js`],main:`${sourceDir}/index.js`,},//...}splitChunkconfiguration:{optimization:{//splitChunks配置splitChunks:{cacheGroups:{default:{name:'vendor',//在vendor中放第三方库,包括vue,vue-router,vuex等//因为都是从node_modules加载,这里直接正则匹配测试:/[\\/]node_modules[\\/]/,chunks:'initial',//调整优先级,Priorityprocessingpriority:10,},common:{chunks:'all',name:'common',//匹配入口test中的common配置:'common',},},},//运行时代码放置在runtime文件中,runtimeChunk:{name:'runtime',},}}是输出配置。[name]表示使用chunk名称作为文件名,[chunkhash:8]表示添加hash。上线后不会再使用缓存加载最新的代码。{output:{path:path.join(__dirname,'./dist'),文件名:'static/[name].[chunkhash:8].bundle.js',chunkFilename:'static/[name].[chunkhash:8].bundle.js',},}拆分第三方库和公共代码后,打包后生成的文件如下:assetsbypathstatic/*.js138KiBassetstatic/vendor.4391b08b.bundle。js133KiB[emitted][immutable][minimized](name:vendor)(idhint:default)assetstatic/main.0d6dab3a.bundle.js3.9KiB[emitted][immutable][minimized](name:main)资产static/runtime.bdaa3432.bundle.js1.1KiB[emitted][immutable][minimized](name:runtime)资产static/common.3f62940b.bundle.js204bytes[emitted][immutable][minimized](name:common)assetindex.html537bytes[emitted]assetstatic/main.acdc2841.bundle.css127bytes[emitted][immutable][minimized](name:main)我们可以看到代码分为不同的文件,vender.js包含了所有的第三方库,main.js包含了各个的业务逻辑我们的页面,公共代码是通用的,runtime包含运行时代码,这样代码就分散到不同的文件中,各司其职,有利于加载。但是main.js里面还是有多个页面的代码。如果只进入首页,其他页面的代码都是多余的,再优化一下。按路由拆分这个比较好办,只需要更改路由配置,通过()=>import(path)的方式加载页面组件:constroutes=[{path:'/',//component:Home,component:()=>import('./pages/Home'),},{path:'/todos',//component:Todos,component:()=>import('./pages/Todos'),},{path:'/about',//component:About,component:()=>import('./pages/About'),},{path:'/404',//component:NotFound,组件:()=>import('./pages/NotFound'),},{路径:'*',重定向:'/404',},];这时候打包的时候会看到多了很多文件,就是把不同页面的代码分成不同的JS文件,只有访问对应的页面才会加载相关代码。按路径分类的资产static/*.js142KiBassetstatic/vendor.4391b08b.bundle.js133KiB[emitted][immutable][minimized](name:vendor)(idhint:default)assetstatic/runtime.07c35c52.bundle.js3.99KiB[发射][不可变][最小化](名称:运行时)资产静态/821.7ba5112d.bundle.js1.89KiB[发射][不可变][最小化]资产静态/main.1697fd27.bundle.js1.68KiB[发射][不可变][最小化](名称:main)资产静态/820.de28fd7b.bundle.js562字节[发射][不可变][最小化]资产静态/646.a902d0eb.bundle.js406字节[发射][不可变][最小化]资产静态/114.26876aa2.bundle.js402字节[发射][不可变][最小化]资产静态/common.3f62940b.bundle.js204字节[发射][不可变][最小化](名称:common)assetsbypathstatic/*.css127bytesassetstatic/main.beb1183a.bundle.css75bytes[emitted][immutable][minimized](name:main)assetstatic/821.cd9a22a5.bundle.css52字节[发出][嗯utable][minimized]assetindex.html537bytes[emitted]当然这个地方可能会有争议。争议点是:“在进入页面的时候下载所有页面的代码,然后再进入其他页面,这样不是更快吗??”看项目情况,是关注页面秒开,还是页面切换体验,如果关注秒开,配合SSR处理会更好。细粒度细分,如果你有更高的要求对于页面打开速度或者性能,还可以做更细粒度的代码切分,比如页面中功能模块的延迟加载,这里以点击按钮时加载相应组件为例来演示代码:这里是一个LoadLazyDemo按钮,点击时加载LazyComponent组件,LazyComponent组件没有什么特别之处,写法和普通组件一样。
