Open tomoya06 opened 4 years ago
本文来自InfoQ博客:Vue性能优化:如何实现延迟加载和代码拆分?,原文总结的很有逻辑。
Webpack的打包原理参考Webpack篇issue,简单来说就是,Webpack会从入口出发,构建出一个依赖图,并把依赖图中的所有模块打包成一个bundle。
延迟加载:就是延迟加载应用程序的部分内容。换句话说,只在真正需要它们时加载它们。 代码拆分:是指将应用程序拆分成可以延迟加载的块。
通过延迟加载适当的组件和库,打包出来的主bundle体积会大大减少。
可以使用 Webpack动态导入来加载应用程序的某些部分。
标准的js模块导入语法如下:
// main.js import ModuleA from './module_a.js' ModuleA.doStuff()
此时main.js和module_a.js都会被打包到同一个bundle。
main.js
module_a.js
若仅在某些情况下需要ModuleA,就可以使用动态导入的方法。如下述代码,对main/ModuleA/ModuleB/ModuleC分别用不同方法引入:
//main.js import ModuleB from './mobile_b.js' const getModuleA = () => import('./module_a.js') getModuleA() .then({ doStuff } => doStuff() ) //module_a.js import ModuleC from './module_c.js'
实际构建出来的依赖图如下,相当于创建了一个新的入口:
在Vue中可以延迟加载整个 SFC 以及它的 css 和 html,语法和之前一样:
<template> <div> <lazy-component v-if="lazyLoad" /> </div> </template> <script> const lazyComponent = () => import('Component.vue') export default { data() { return {}; }, components: { lazyComponent } } </script>
这样,只有当请求在模板中渲染组件时,才会调用 lazyComponent 函数。例如,如果lazyLoad = false,那么就不会导入组件。
lazyLoad = false
vue-router也支持路由懒加载。官方文档参考这里。语法类似:
const routes = [ { path: /', component: () => import('./components/Home.vue') }, { path: /about', component: () => import('./components/About.vue') }, ]
依赖图变化如下,Webpack将创建三个包:
/
/about
指的是对Vue modules的延迟加载。参考Vuex文档的模块动态注册,即使用store.registerModule方法来动态注册。
store.registerModule
// store.js import { userAccountModule } from './modules/userAccount' export const store = new Vuex.Store({ modules: { user: userAccountModule, // admin: adminModule, } }) // Admin.vue import adminModule from './admin.js' export default { // other component logic mounted () { this.$store.registerModule('admin', adminModule) }, beforeDestroy () { this.$store.unregisterModule('admin') } }
这样只有在Admin组件被加载时,adminModule子模块才会被加载。依赖图的变化如下:
这里主要以lodash为例。原文介绍的方法是使用 webpack 的 splitChunksPlugin 插件,这样可以保证只有用到了lodash的页面才引入lodash,不过引入的时候还是全量引入。
另外常见的方法如下,参考掘金博客:
import isEqual from 'lodash.isequal'; // 或者 import difference from 'lodash/difference';
babel-plugin-lodash
lodash-webpack-plugin
// webpack.config.js var LodashModuleReplacementPlugin = require('lodash-webpack-plugin'); var webpack = require('webpack'); module.exports = { module: { rules: [ { use: 'babel-loader', test: /\.js$/, exclude: /node_modules/, options: { plugins: ['lodash'], presets: [['env', {modules: false, targets: {node: 4}}]] } } ] }, plugins: [new LodashModuleReplacementPlugin(), new webpack.optimize.UglifyJsPlugin()] };
import {isEmpty, isObject, cloneDeep} from 'lodash-es';
延迟加载和代码拆分
前言
Webpack的打包原理参考Webpack篇issue,简单来说就是,Webpack会从入口出发,构建出一个依赖图,并把依赖图中的所有模块打包成一个bundle。
定义
延迟加载:就是延迟加载应用程序的部分内容。换句话说,只在真正需要它们时加载它们。 代码拆分:是指将应用程序拆分成可以延迟加载的块。
通过延迟加载适当的组件和库,打包出来的主bundle体积会大大减少。
实现
可以使用 Webpack动态导入来加载应用程序的某些部分。
标准的js模块导入语法如下:
此时
main.js
和module_a.js
都会被打包到同一个bundle。若仅在某些情况下需要ModuleA,就可以使用动态导入的方法。如下述代码,对main/ModuleA/ModuleB/ModuleC分别用不同方法引入:
实际构建出来的依赖图如下,相当于创建了一个新的入口:
Vueの实践
延迟加载组件
在Vue中可以延迟加载整个 SFC 以及它的 css 和 html,语法和之前一样:
这样,只有当请求在模板中渲染组件时,才会调用 lazyComponent 函数。例如,如果
lazyLoad = false
,那么就不会导入组件。路由懒加载
vue-router也支持路由懒加载。官方文档参考这里。语法类似:
依赖图变化如下,Webpack将创建三个包:
/
路径时才会加载;/about
路径时才会加载。Vuex模块
指的是对Vue modules的延迟加载。参考Vuex文档的模块动态注册,即使用
store.registerModule
方法来动态注册。这样只有在Admin组件被加载时,adminModule子模块才会被加载。依赖图的变化如下:
第三方依赖
这里主要以lodash为例。原文介绍的方法是使用 webpack 的 splitChunksPlugin 插件,这样可以保证只有用到了lodash的页面才引入lodash,不过引入的时候还是全量引入。
另外常见的方法如下,参考掘金博客:
babel-plugin-lodash
和lodash-webpack-plugin
插件