通常为了开发效率,咱们会应用 vue-cli
创立我的项目,这样创立的我的项目默认状况下编译是会对代码进行宰割的。然而如果是自行配置的 webpack 环境的话,还是很有必要相熟代码宰割的相干常识的。
为什么要做代码宰割
在配置 webpack 的过程中,很多时候咱们的 webpack 入口只写了一个 entry: '${sourceDir}/index.js’
,默认状况下只会生成一个 bundle 文件,蕴含了第三方库、公共代码及不同页面所用到的业务逻辑,这必然会造成该 bundle 文件体积过大,影响页面首次的加载速度,因而咱们须要对代码进行宰割,放慢首次进入页面的速度。
代码宰割思路
首先把第三方库、公共代码抽离进去,因为这些代码变动的频率小,能够打包成一个文件,这样每次上线文件都不发生变化,能够充分利用网络缓存放慢文件下载速度,宰割的细的话就是,第三方库为一个 js 文件, 公共代码为一个 js 文件。
而后,依照路由(页面)进行代码宰割,每个页面生成一个 js 文件,这样每次首次进入就只加载公共代码和本页面用的的 js 文件, 而不必加载其它页面无关的代码。
最初,再进行精密宰割的话,就是依据组件应用状况进行宰割,来实现组件的懒加载,比方:页面中的不同 tab,能够依据 tab 的展现状况进行宰割,把须要点击或者用户被动操作能力出现的组件进行懒加载,这样就在页面级又进行了更细粒度的代码宰割。
代码宰割实战
第三方库及公共代码宰割
第一步咱们进行第三方库的宰割,比方 vue、vue-router、vuex、axios 等三方库,把它们放到 vender.js 中,而后 utils、common 文件等放在 common.js 中。这些通过 webpack 的 entry 及 splitChunk 配置即可实现。
批改 entry 配置:
{ // ... entry: { // 把公共代码放到 common 里 common: [`${sourceDir}/utils/index.js`], main: `${sourceDir}/index.js`, }, // ...}
splitChunk 配置:
{ optimization: { // splitChunks 配置 splitChunks: { cacheGroups: { default: { name: 'vendor', // 把第三方库放到 vendor 里,包含 vue, vue-router, vuex 等 // 因为他们都是从 node_modules 里加载的,这里间接正则匹配 test: /[\\/]node_modules[\\/]/, chunks: 'initial', // 调整优先级,优先解决 priority: 10, }, common: { chunks: 'all', name: 'common', // 匹配 entry 里的 common 配置 test: 'common', }, }, }, // runtime 代码放在 runtime 文件中 runtimeChunk: { name: 'runtime', }, }}
另外就是 output 配置了,[name]
示意让 chunk 名称作为文件名, [chunkhash:8]
示意加上 hash,上线后不走缓存加载最新的代码。
{ output: { path: path.join(__dirname, './dist'), filename: 'static/[name].[chunkhash:8].bundle.js', chunkFilename: 'static/[name].[chunkhash:8].bundle.js', },}
做完第三方库及公共代码宰割,打包后生成的文件如下:
assets by path static/*.js 138 KiB asset static/vendor.4391b08b.bundle.js 133 KiB [emitted] [immutable] [minimized] (name: vendor) (id hint: default) asset static/main.0d6dab3a.bundle.js 3.9 KiB [emitted] [immutable] [minimized] (name: main) asset static/runtime.bdaa3432.bundle.js 1.1 KiB [emitted] [immutable] [minimized] (name: runtime) asset static/common.3f62940b.bundle.js 204 bytes [emitted] [immutable] [minimized] (name: common)asset index.html 537 bytes [emitted]asset static/main.acdc2841.bundle.css 127 bytes [emitted] [immutable] [minimized] (name: main)
咱们能够看到代码宰割到了不同的文件中,vender.js 蕴含了所有的第三方库,main.js 蕴含了咱们各个页面的业务逻辑,公共代码在 common 中,runtime 蕴含了运行时代码,这样代码就扩散到了不同的文件中,各司其职,且有利于同时进行加载。
然而 main.js 还是蕴含了多个页面的代码,如果只是进入首页的话,其它页面的代码就是多余的,接下来再进行优化。
按路由宰割
这一个比拟容易解决,只需扭转下路由配置即可,以 () => import(path)
的形式加载页面组件:
const routes = [ { 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, component: () => import('./pages/NotFound'), }, { path: '*', redirect: '/404', },];
此时打包会看到多了很多文件,这是把不同页面的代码宰割到了不同的 JS 文件中,只有拜访对应的页面才会加载相干的代码。
assets by path static/*.js 142 KiB asset static/vendor.4391b08b.bundle.js 133 KiB [emitted] [immutable] [minimized] (name: vendor) (id hint: default) asset static/runtime.07c35c52.bundle.js 3.99 KiB [emitted] [immutable] [minimized] (name: runtime) asset static/821.7ba5112d.bundle.js 1.89 KiB [emitted] [immutable] [minimized] asset static/main.1697fd27.bundle.js 1.68 KiB [emitted] [immutable] [minimized] (name: main) asset static/820.de28fd7b.bundle.js 562 bytes [emitted] [immutable] [minimized] asset static/646.a902d0eb.bundle.js 406 bytes [emitted] [immutable] [minimized] asset static/114.26876aa2.bundle.js 402 bytes [emitted] [immutable] [minimized] asset static/common.3f62940b.bundle.js 204 bytes [emitted] [immutable] [minimized] (name: common)assets by path static/*.css 127 bytes asset static/main.beb1183a.bundle.css 75 bytes [emitted] [immutable] [minimized] (name: main) asset static/821.cd9a22a5.bundle.css 52 bytes [emitted] [immutable] [minimized]asset index.html 537 bytes [emitted]
当然,这个中央可能会有争议,争议的中央就是:「页面进入时就把所有页面的代码都下载下来,再进入其它页面不是更快吗?」。这就取决于我的项目状况了,看是着重于页面秒开,还是着重于页面切换体验。如果着重于秒开的话,配合 SSR 解决成果会更好。
更细粒度的宰割
如果对于页面关上速度或性能有更高的要求,还能够做更细粒度的代码宰割,比方页面中功能模块的懒加载。
这里以一个点击按钮时加载相应的组件为例,进行代码演示:
这里有一个 Load Lazy Demo
按钮,点击时才加载 LazyComponent
组件,LazyComponent
组件并没有什么特别之处,写法跟一般组件一样。
<template> <button @click="loadLazyDemo">Load Lazy Demo</button> <template v-if="showLazyComponent"> <lazy-component /> </template></template>
这里通过一个 showLazyComponent
管制组件的显示,当点击按钮时,把 showLazyComponent
置为 true,而后就加载 LazyComponent 对应的代码了。其实要害还是通过 () => import(path)
的形式引入组件。
<script>export default { data() { return { showLazyComponent: false, }; }, methods: { loadLazyDemo() { this.showLazyComponent = true; }, }, components: { 'lazy-component': () => import('../components/LazyComponent'), },};</script>
OK,以上就是我在 Vue 我的项目中做的代码宰割的相干内容。