MST

星途 面试题库

面试题:如何深度优化Vue CLI构建的项目在生产环境下的打包体积与加载速度

假设你正在开发一个面向全球用户的大型Vue项目,使用Vue CLI进行构建。在生产环境下,要求尽可能地优化打包体积和加载速度。请从Webpack配置、Vue组件优化、资源加载策略等多方面详细阐述你的优化思路和具体实现方法,包括但不限于Tree - shaking、Code Splitting、CDN引入等技术的应用及配置。
29.5万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

Webpack配置优化

  1. Tree - shaking

    • 原理:Tree - shaking 是一种通过消除未使用的代码来优化打包体积的技术。在JavaScript模块系统中,它可以分析模块之间的依赖关系,只保留项目中实际使用到的代码。
    • 实现方法
      • 使用ES6模块语法。Vue CLI默认支持ES6模块,确保项目中的代码都使用importexport语句进行模块导入和导出。例如:
        // utils.js
        export function add(a, b) {
          return a + b;
        }
        export function subtract(a, b) {
          return a - b;
        }
        // main.js
        import { add } from './utils.js';
        // 这里只使用了add函数,subtract函数会被Tree - shaking移除
        
      • 在Webpack配置中,mode设置为'production',Webpack在生产模式下会自动启用Tree - shaking。如果使用Vue CLI,可以在vue.config.js中设置:
        module.exports = {
          mode: 'production'
        };
        
  2. Code Splitting

    • 原理:Code Splitting将代码分割成多个较小的文件,在需要的时候加载,而不是一次性加载所有代码,从而提高加载速度。
    • 实现方法
      • 动态导入:在Vue组件中使用动态导入语法(import())来实现代码分割。例如:
        // Home.vue
        export default {
          components: {
            SomeComponent: () => import('./SomeComponent.vue')
          }
        };
        
        这样SomeComponent.vue的代码会被分割成单独的文件,只有在Home.vue渲染时才会加载。
      • Webpack SplitChunksPlugin:Vue CLI已经内置了对SplitChunksPlugin的支持。可以在vue.config.js中进一步配置:
        module.exports = {
          chainWebpack: config => {
            config.optimization.splitChunks({
              chunks: 'all',
              minSize: 30000,
              minChunks: 1,
              maxAsyncRequests: 5,
              maxInitialRequests: 3,
              automaticNameDelimiter: '~',
              name: true,
              cacheGroups: {
                vendors: {
                  test: /[\\/]node_modules[\\/]/,
                  priority: -10
                },
                default: {
                  minChunks: 2,
                  priority: -20,
                  reuseExistingChunk: true
                }
              }
            });
          }
        };
        
        这段配置将所有模块进行分割,将来自node_modules的模块提取到vendors组,其他模块根据配置规则进行分割。
  3. CDN引入

    • 原理:将一些常用的第三方库(如Vue、Vue Router、Axios等)通过CDN引入,这样浏览器可以从CDN服务器加载这些资源,减少打包体积,并且CDN服务器通常有更好的缓存策略和分布式部署,能提高加载速度。
    • 实现方法
      • public/index.html中引入CDN链接。例如,引入Vue和Vue Router:
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/vue - router@3.5.3/dist/vue - router.min.js"></script>
        
      • vue.config.js中配置Webpack,告诉它不要将这些库打包进去。使用externals配置:
        module.exports = {
          configureWebpack: {
            externals: {
              'vue': 'Vue',
              'vue - router': 'VueRouter'
            }
          }
        };
        
        这样在打包时,Webpack会跳过这些库,从而减小打包体积。

Vue组件优化

  1. 组件懒加载
    • 原理:与Code Splitting中的动态导入类似,组件懒加载是将组件的加载推迟到实际需要渲染时,避免初始加载时加载过多组件,从而加快页面加载速度。
    • 实现方法
      • 对于路由组件,在router/index.js中使用懒加载:
        const router = new VueRouter({
          routes: [
            {
              path: '/home',
              component: () => import('@/views/Home.vue')
            }
          ]
        });
        
      • 对于普通组件,在父组件中使用动态导入:
        <template>
          <div>
            <component :is="LazyComponent"></component>
          </div>
        </template>
        <script>
        export default {
          data() {
            return {
              LazyComponent: null
            };
          },
          mounted() {
            this.LazyComponent = () => import('./LazyComponent.vue');
          }
        };
        </script>
        
  2. 减少组件的不必要渲染
    • 原理:当组件的状态没有发生变化时,避免不必要的重新渲染,从而提高性能。
    • 实现方法
      • 使用Vue.mixinObject.freeze来创建不变化的数据。例如:
        // 创建一个混入
        const frozenDataMixin = {
          data() {
            return Object.freeze({
              someStaticData: {
                key: 'value'
              }
            });
          }
        };
        Vue.mixin(frozenDataMixin);
        
        这样在组件中使用someStaticData时,即使组件重新渲染,由于数据是冻结的,Vue不会检测到变化,从而避免不必要的重新渲染。
      • 使用shouldComponentUpdate生命周期钩子函数。在组件中定义:
        export default {
          data() {
            return {
              count: 0
            };
          },
          shouldComponentUpdate(nextProps, nextState) {
            // 只有count发生变化时才重新渲染
            return this.count!== nextState.count;
          }
        };
        

资源加载策略优化

  1. 图片优化
    • 原理:通过压缩图片、选择合适的图片格式等方式,减小图片文件大小,加快图片加载速度。
    • 实现方法
      • 图片压缩:使用工具如image - webpack - loader对图片进行压缩。在vue.config.js中配置:
        module.exports = {
          chainWebpack: config => {
            config.module
             .rule('images')
             .use('image - webpack - loader')
             .loader('image - webpack - loader')
             .options({
                mozjpeg: {
                  progressive: true,
                  quality: 65
                },
                // optipng.enabled: false will disable optipng
                optipng: {
                  enabled: false
                },
                pngquant: {
                  quality: [0.65, 0.90],
                  speed: 4
                },
                gifsicle: {
                  interlaced: false
                },
                // the webp option will enable WEBP
                webp: {
                  quality: 75
                }
              })
             .end();
          }
        };
        
      • 图片格式选择:根据不同场景选择合适的图片格式。例如,对于色彩丰富的照片使用JPEG格式,对于简单图形、有透明度需求的使用PNG格式,支持WebP格式的浏览器优先使用WebP格式(WebP通常比JPEG和PNG有更好的压缩比)。可以使用<picture>标签来实现格式选择:
        <picture>
          <source type="image/webp" srcset="image.webp">
          <source type="image/jpeg" srcset="image.jpg">
          <img src="image.jpg" alt="image">
        </picture>
        
  2. 字体优化
    • 原理:减小字体文件大小,避免字体加载阻塞页面渲染。
    • 实现方法
      • 字体子集化:使用工具如fonttools提取项目中实际使用到的字符子集,生成更小的字体文件。例如,如果项目中只使用了英文字母和数字,可以提取对应的字符子集,减小字体文件体积。
      • 字体加载策略:使用@font - face规则加载字体,并设置合适的font - display属性。例如:
        @font - face {
          font - family: 'MyFont';
          src: url('/fonts/myfont.woff2') format('woff2'),
               url('/fonts/myfont.woff') format('woff');
          font - display: swap;
        }
        
        font - display: swap可以让浏览器先使用系统默认字体渲染页面,等自定义字体加载完成后再替换,避免字体加载阻塞页面渲染。