前端调研:代码分割和懒加载:Vue的异步组件功能

391 阅读7分钟

1.什么是代码分割?

基本概念:

代码分割(Code Splitting)是将应用程序的代码分成多个小的块(chunk),这些块可以独立加载。这样做的好处是可以减少单个文件的大小,从而加快初始加载时间。

应用场景:

**1. 大型单页应用(SPA):当你的页面非常大时,组件特别多,所有代码打包在一起会导致初始加载时间过长。通过代码分割,可以只加载用户当前访问页面所需的代码。

  1. 按需加载组件:一些组件可能只在特定情况下使用,比如模态框、弹出窗口(详情页、二次确定对话框)等。可以将这些组件单独分割出来,在需要时再加载。**

解决问题:

1.减少加载时间:在需要的时候加载相应的代码块,以替代一次加载所有代码,从而减少初始加载时间。 2.提高性能:按需加载可以减少不必要的资源消耗。

2.什么是懒加载?

基本概念:

懒加载(Lazy Loading)是指在需要时才加载某些资源,而不是在应用初始化时加载所有资源。懒加载通常与代码分割结合使用。

应用场景:

1.路由懒加载:在 Vue Router 中,可以对每个路由组件进行懒加载。当用户访问某个路由时,才加载对应的组件代码。 2.图片懒加载:对于页面上的图片,可以在用户滚动到图片所在位置时再加载图片资源。

解决问题:

1.减少带宽消耗:只加载用户需要的资源,减少不必要的网络请求。 2.提高页面响应速度:用户在滚动或导航时,页面可以更快响应,因为不需要一次性加载所有资源。

3.实现代码分割和懒加载

Vue实现代码分割和懒加载

  1. 在 Vue 中,可以使用 Webpack 的代码分割功能,主要是通过动态导入来实现代码分割。我们可以将某些组件或模块分割成独立的代码块,并在需要时动态加载它们。
/** home.vue 依赖于HelloWorld.vue 这个页面 **/
<script>
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  components: {
    HelloWorld,
  },
}
</script>
  1. 使用动态导入 (import()) 的方式懒加载组件

    当点击按钮设置 showHello 为 true 时,HelloWorld 组件会被动态导入,这时会触发一个 HTTP 请求来获取 HelloWorld.vue 的代码。

<template>
  <div class="home">
    <button @click="() => showHello = true">Hello</button>
    <HelloWorld v-if="showHello" />
  </div>
</template>

<script>
// Home.vue
export default {
  components: {
    HelloWorld: () => import('@/components/HelloWorld.vue'),  // 
  },
  data() {
    return {
      showHello: false,
    }
  },
}
</script>
  1. 路由懒加载
/** 导入vue框架和vue路由插件 **/
import Vue from 'vue';
import Router from 'vue-router';

/** 使用路由**/
Vue.use(Router);

/**
这两行代码使用了 JavaScript 的动态导入语法 import(),
它可以在需要时才加载模块。这里的 Home 和 About 是两个 Vue 组件,
它们分别位于 ./views/Home.vue 和 ./views/About.vue 路径下。

/*  xxxx */ Webpack 提供的 魔法注释,用于颗粒度更小的配置(作用类似于配置文件)

=() => es6语法 箭头函数 
**/
const Home = () => import(/* webpackChunkName: "home" */ './views/Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './views/About.vue');

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: About
    }
  ]
});
  1. 组件懒加载(异步加载组件)
**Vue.component('AsyncComponent', () => ({
  // 需要加载的组件 
  component: import('./components/AsyncComponent.vue'),
  // 加载中应显示的组件
  loading: LoadingComponent,
  // 出错时显示的组件
  error: ErrorComponent,
  // 渲染加载中组件前的等待时间。默认:200ms。
  delay: 200,
  // 最长等待时间。超出此时间则渲染错误组件。默认:Infinity
  timeout: 3000
}));**

4.代码分割和懒加载问题与解决方案

1.常见问题

  • 首屏加载时间增加

    如果懒加载的组件在首屏中使用,可能导致首屏加载时间增加,因为需要等待组件的 HTTP 请求完成。

  • 闪烁或延迟显示

    懒加载的组件在加载过程中可能会导致页面闪烁或延迟显示,影响用户体验。

  • SEO问题搜索引擎优化

    对于需要 SEO 的页面(例如 SSR 应用),懒加载可能会影响搜索引擎的抓取和索引。从而手上引擎中的排名

  • 错误处理

    动态导入的组件在加载过程中可能会遇到网络错误或其他问题,需要去处理这些错误,方便查出现的问题。

2.解决方案

  • 首屏加载时间增加

    对于首屏需要的组件,尽量避免懒加载。可以通过代码分割将非首屏的组件进行懒加载,减少首屏的体积。使用 Webpack 的 Prefetching 和 Preloading 技术来预加载可能需要的资源。

    Prefetching

    Prefetching 是一种在浏览器空闲时预加载资源的技术。这些资源通常是用户在当前页面不一定会立即需要的,但可能在未来的某个时刻需要。例如,你可以预加载用户可能会导航到的下一个页面的资源。

    在 Webpack 中,你可以使用 webpackPrefetch 魔法注释来实现预取。

    prefetch在Safari中暂时还不支持

    下面的链接 用于查询prefetch是否支持浏览器

    caniuse.com/?search=pre…

    示例

    **// 预取资源
    const Component = () => import(/* webpackPrefetch: true */ './Component');**
    

    这段代码告诉 Webpack 在浏览器空闲时预加载 ./Component 模块。

    Preloading

    Preloading 是一种在页面加载时立即加载资源的技术。这些资源通常是用户在当前页面很快就会需要的。例如,你可以预加载当前页面的关键资源以加快页面的渲染速度。

    在 Webpack 中,你可以使用 webpackPreload 魔法注释来实现预加载。

    示例

    **// 预加载资源
    const Component = () => import(/* webpackPreload: true */ './Component');**
    

    这段代码告诉 Webpack 在页面加载时立即加载 ./Component 模块**。**

    应用场景

    1. **Prefetching:**适用于用户可能会访问的下一个页面或未来可能需要的资源。(上下翻页)
    2. **Preloading:**适用于当前页面的关键资源,用户很快就会需要这些资源。
  • 闪烁或延迟显示

    在懒加载组件时,可以显示一个加载指示器(如 Spinner 或 Skeleton)来改善用户体验。Vue 提供了 Suspense 组件,可以用来处理异步组件的加载状态。(加载过渡组件)

    <template>
      <div class="home">
        <!-- 按钮,点击后将 showHello 设置为 true -->
        <button @click="showHello = true">Hello</button>
        
        <!-- Suspense 组件,用于处理异步组件加载 -->
        <Suspense>
        
          <!-- 默认插槽,当 HelloWorld 组件加载完成后显示 -->
          <template #default>
            <!-- 使用 v-if 指令,只有当 showHello 为 true 时才渲染 HelloWorld 组件 -->
            <HelloWorld v-if="showHello" />
          </template>
          
          <!-- fallback 插槽,当 HelloWorld 组件正在加载时显示 -->
          <template #fallback>
            <div>Loading...</div>
          </template>
        </Suspense>
      </div>
    </template>
    
    <script>
    export default {
      components: {
        // 懒加载 HelloWorld 组件,只有在需要时才加载
        HelloWorld: () => import('@/components/HelloWorld.vue'),
      },
      data() {
        return {
          // showHello 用于控制是否显示 HelloWorld 组件
          showHello: false,
        }
      },
    }
    </script>
    
  • SEO问题搜索引擎优化

    对于需要 SEO 的页面,可以使用服务端渲染(SSR)或静态站点生成(SSG)技术,如 Nuxt.js。SSR 和 SSG 可以确保页面内容在服务器端渲染好,再发送到客户端,从而提升 SEO 友好性。

  • 错误处理

    在动态导入组件时,可以使用 catch 方法处理加载错误,并显示相应的错误提示。

       const HelloWorld = () => import('@/components/HelloWorld.vue')
         .catch(error => {
           console.error('Error loading HelloWorld component:', error);
           return import('@/components/ErrorComponent.vue'); // 加载错误时显示的组件
         });
       
       export default {
         components: {
           HelloWorld,
         },
         data() {
           return {
             showHello: false,
           }
         },
       }
    

5.总结

Vue中使用懒加载和代码分块对产品进行优化,简单实用,但是这其中存在着权衡,如果项目较小,打包文件并不大,则可能不需要进行代码分块和懒加载,毕竟需要请求http请求。当项目较大时,使用懒加载和代码分块就可以显著地提升性能,但是同样注意那需要由后来的请求弥补的,目前大部分浏览器都支持资源预加载策略,搭配使用效果更佳。