MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Vue CLI 如何自定义配置文件与构建优化策略

2021-12-072.9k 阅读

一、Vue CLI 自定义配置文件基础

在 Vue 项目开发中,Vue CLI 为我们提供了便捷的项目搭建和开发流程。默认情况下,Vue CLI 会根据一系列预设的配置来构建项目。然而,随着项目的复杂性增加,我们常常需要对这些配置进行自定义,以满足特定的项目需求。

1.1 为什么要自定义配置文件

  • 个性化构建需求:不同的项目可能有不同的构建目标,例如,有些项目需要将特定的资源文件输出到指定目录,或者对特定类型的文件进行特殊的处理。默认配置无法满足这些个性化需求。
  • 性能优化:在大型项目中,默认的构建配置可能无法充分发挥性能优势。通过自定义配置,我们可以进行更精细的代码拆分、压缩策略调整等优化操作,提升项目的加载速度和运行效率。
  • 适配不同环境:开发、测试和生产环境可能对构建有不同的要求。例如,开发环境可能需要更详细的调试信息,而生产环境则需要极致的代码压缩和优化。自定义配置可以帮助我们轻松切换不同环境的配置。

1.2 配置文件类型

Vue CLI 支持多种自定义配置文件,常见的有以下几种:

  • vue.config.js:这是最主要的配置文件,用于修改 Vue CLI 的默认配置。它是一个 JavaScript 文件,在项目根目录下创建,Vue CLI 会自动识别并加载其中的配置。
module.exports = {
  // 配置选项
}
  • .env 文件:用于在不同环境下设置环境变量。例如,.env.development 用于开发环境,.env.production 用于生产环境。这些文件中的变量可以在 vue.config.js 以及项目代码中通过 process.env 访问。
#.env.development
VUE_APP_API_URL = http://localhost:3000/api
  • webpack.extra.js:在一些复杂场景下,我们可能需要对 Webpack 进行更底层的扩展。webpack.extra.js 允许我们在不直接修改 Vue CLI 内部 Webpack 配置的情况下,添加额外的 Webpack 配置。
module.exports = (config, { isServer }) => {
  // 对 Webpack 配置进行修改
  return config;
}

二、自定义 vue.config.js 配置

2.1 项目基本配置

vue.config.js 中,我们可以对项目的基本信息进行配置,例如项目的输出目录、部署基础路径等。

  • outputDir:指定构建输出目录。默认情况下,Vue CLI 会将构建后的文件输出到 dist 目录。如果我们想更改输出目录,可以这样配置:
module.exports = {
  outputDir: 'build'
}

这将使构建后的文件输出到项目根目录下的 build 目录。

  • publicPath:用于指定项目在部署时的基础路径。例如,如果项目部署在 https://example.com/my-project/,则需要将 publicPath 设置为 /my-project/
module.exports = {
  publicPath: '/my-project/'
}

2.2 开发服务器配置

开发过程中,我们经常需要对开发服务器进行一些自定义配置,以满足开发需求。

  • devServerdevServer 选项允许我们对开发服务器进行详细配置。例如,设置代理以解决跨域问题:
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

上述配置表示,当请求以 /api 开头时,将请求代理到 http://localhost:3001,并去除路径中的 /api 前缀。

  • port:可以设置开发服务器的端口号。默认端口是 8080,如果该端口被占用,可以通过以下配置更改端口:
module.exports = {
  devServer: {
    port: 8081
  }
}

2.3 模块解析配置

在项目中,我们可能需要对模块的解析规则进行自定义,以适应项目的组织结构。

  • aliasalias 用于设置模块的别名,方便我们在代码中更简洁地引用模块。例如,在一个大型项目中,我们可能有一个复杂的目录结构,为了方便引用 src/components 目录下的组件,我们可以这样设置别名:
const path = require('path');

module.exports = {
  chainWebpack: config => {
    config.resolve.alias
     .set('@components', path.resolve(__dirname,'src/components'))
  }
}

这样,在代码中我们就可以使用 import MyComponent from '@components/MyComponent.vue' 来引用组件,而不需要使用相对路径。

  • extensionsextensions 用于配置在导入模块时可以省略的文件扩展名。默认情况下,Vue CLI 会尝试 '.js', '.vue', '.json' 等扩展名。如果我们的项目中有自定义的文件类型,例如 .less 文件,并且希望在导入时省略扩展名,可以这样配置:
module.exports = {
  chainWebpack: config => {
    config.resolve.extensions.add('.less')
  }
}

2.4 CSS 配置

CSS 是前端开发中不可或缺的一部分,Vue CLI 提供了丰富的 CSS 配置选项。

  • css.extract:默认情况下,Vue CLI 会将 CSS 提取到单独的文件中。如果我们希望在开发环境中不提取 CSS,而是将其注入到 JavaScript 中,可以这样配置:
module.exports = {
  css: {
    extract: process.env.NODE_ENV!== 'development'
  }
}

这样,在开发环境中,CSS 会被注入到 JavaScript 中,方便调试;在生产环境中,CSS 会被提取到单独的文件,以提升性能。

  • css.loaderOptionsloaderOptions 用于对 CSS 相关的 loader 进行配置。例如,对于 less-loader,我们可以配置全局的变量和混入:
module.exports = {
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          javascriptEnabled: true,
          modifyVars: {
            '@primary-color': '#1DA57A'
          }
        }
      }
    }
  }
}

上述配置通过 modifyVarsless 中的 @primary-color 变量进行了修改,并且启用了 javascriptEnabled 以支持更复杂的配置。

三、利用环境变量进行配置

3.1 环境变量的作用

环境变量在 Vue CLI 项目中起着至关重要的作用。它们允许我们根据不同的环境(开发、测试、生产等)动态地调整项目的配置。例如,不同环境下的 API 地址可能不同,通过环境变量我们可以轻松切换。

3.2 定义环境变量

在项目根目录下创建 .env 文件,用于定义通用的环境变量。例如:

VUE_APP_TITLE = My Vue Project

同时,我们可以创建 .env.development.env.production 等文件,用于定义特定环境下的变量。例如,.env.development 可以包含开发环境的 API 地址:

VUE_APP_API_URL = http://localhost:3000/api

.env.production 可以包含生产环境的 API 地址:

VUE_APP_API_URL = https://api.example.com/api

3.3 在代码中使用环境变量

vue.config.js 中,我们可以通过 process.env 访问环境变量。例如,根据不同环境设置不同的 publicPath

module.exports = {
  publicPath: process.env.NODE_ENV === 'production'? '/prod/' : '/'
}

在组件代码中,也可以通过 process.env 访问环境变量。例如:

<template>
  <div>
    <h1>{{ appTitle }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      appTitle: process.env.VUE_APP_TITLE
    }
  }
}
</script>

四、Webpack 扩展与自定义

4.1 理解 Vue CLI 与 Webpack 的关系

Vue CLI 是基于 Webpack 构建的,它为我们封装了很多 Webpack 的复杂配置,使我们能够更专注于业务开发。然而,在一些高级场景下,我们需要对 Webpack 进行更深入的自定义。

4.2 使用 chainWebpack 进行配置

chainWebpackvue.config.js 中的一个选项,它允许我们通过链式调用的方式对 Webpack 的配置进行修改。例如,我们想添加一个新的 loader 来处理 markdown 文件:

const MarkdownItLoader = require('markdown-it-loader');

module.exports = {
  chainWebpack: config => {
    config.module
     .rule('markdown')
     .test(/\.md$/)
     .use('markdown-it-loader')
     .loader(MarkdownItLoader)
  }
}

上述代码通过 chainWebpack,为 md 文件添加了 markdown-it-loader,这样我们就可以在项目中使用 markdown 文件了。

4.3 使用 webpack.extra.js 进行深度扩展

对于一些更复杂的 Webpack 配置需求,chainWebpack 可能无法满足。这时,我们可以使用 webpack.extra.js 文件。例如,我们想在 Webpack 构建过程中添加一个自定义的插件:

const MyCustomPlugin = require('./MyCustomPlugin');

module.exports = (config, { isServer }) => {
  if (!isServer) {
    config.plugins.push(new MyCustomPlugin());
  }
  return config;
}

在上述代码中,我们在 webpack.extra.js 中添加了一个自定义插件 MyCustomPlugin,并且通过 isServer 判断是否为服务端渲染环境,只在客户端构建时添加该插件。

五、构建优化策略

5.1 代码拆分

代码拆分是提升项目性能的重要手段之一。Vue CLI 默认已经启用了代码拆分,将项目中的代码按照路由、动态导入等方式进行拆分。然而,我们可以进一步优化代码拆分策略。

  • splitChunks:通过 splitChunks 配置项,我们可以更精细地控制代码拆分。例如,将所有的第三方库代码拆分到一个单独的文件中:
module.exports = {
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name:'vendors',
          chunks: 'all'
        }
      }
    })
  }
}

这样,在构建时,所有来自 node_modules 的代码都会被拆分到 vendors.js 文件中,浏览器可以单独缓存这个文件,提高后续页面加载速度。

5.2 压缩与优化

在生产环境中,对代码进行压缩和优化可以显著提升项目的加载速度。

  • terser-webpack-plugin:Vue CLI 默认使用 terser-webpack-plugin 进行 JavaScript 代码压缩。我们可以通过 configureWebpack 选项对其进行进一步配置。例如,启用并行压缩以加快压缩速度:
module.exports = {
  configureWebpack: {
    optimization: {
      minimizer: [
        new TerserPlugin({
          parallel: true
        })
      ]
    }
  }
}
  • css-minimizer-webpack-plugin:对于 CSS 代码压缩,Vue CLI 也有相应的插件。我们可以通过类似的方式进行配置,例如启用更高级的压缩选项:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  configureWebpack: {
    optimization: {
      minimizer: [
        new CssMinimizerPlugin({
          minimizerOptions: {
            preset: ['default', { discardComments: { removeAll: true } }]
          }
        })
      ]
    }
  }
}

上述配置通过 css-minimizer-webpack-plugin 对 CSS 代码进行压缩,并移除所有的注释。

5.3 图片优化

图片在前端项目中通常占据较大的体积,对图片进行优化可以有效提升页面加载速度。

  • image-webpack-loader:我们可以使用 image-webpack-loader 对图片进行压缩和优化。首先安装该 loader:npm install image-webpack-loader -D,然后在 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 },
        pngquant: {
          quality: [0.65, 0.90],
          speed: 4
        },
        gifsicle: { interlaced: false },
        webp: { quality: 75 }
      })
  }
}

上述配置对不同类型的图片进行了相应的压缩优化,例如将 JPEG 图片的质量设置为 65,对 PNG 图片进行特定质量范围的压缩等。

5.4 懒加载优化

懒加载是一种延迟加载非关键资源的技术,可以提升页面的初始加载速度。

  • 路由懒加载:Vue Router 支持路由懒加载,在 Vue CLI 项目中,我们可以很方便地实现。例如:
const router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    }
  ]
})

上述代码通过 import() 语法实现了路由的懒加载,webpackChunkName 用于指定拆分后的代码块名称。

  • 图片懒加载:对于图片懒加载,我们可以使用第三方库如 vue-lazyload。首先安装 vue-lazyloadnpm install vue-lazyload -S,然后在项目中进行配置:
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';

Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'path/to/error.png',
  loading: 'path/to/loading.png',
  attempt: 1
})

在模板中,我们可以这样使用:

<template>
  <div>
    <img v-lazy="imageUrl" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'path/to/image.jpg'
    }
  }
}
</script>

这样,图片只有在进入视口时才会加载,提升了页面的加载性能。

六、多页面应用的配置与优化

6.1 创建多页面应用

在 Vue CLI 中创建多页面应用,我们需要在 vue.config.js 中进行相应的配置。首先,我们要确定项目的页面入口和模板。例如,假设我们有两个页面,indexabout

const path = require('path');

module.exports = {
  pages: {
    index: {
      entry: 'src/pages/index/main.js',
      template: 'public/index.html',
      filename: 'index.html',
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    about: {
      entry: 'src/pages/about/main.js',
      template: 'public/about.html',
      filename: 'about.html',
      chunks: ['chunk-vendors', 'chunk-common', 'about']
    }
  }
}

上述配置定义了 indexabout 两个页面的入口、模板和输出文件名,并且指定了每个页面所依赖的代码块。

6.2 多页面应用的构建优化

多页面应用在构建时,由于页面数量增多,可能会出现一些性能问题。我们可以从以下几个方面进行优化:

  • 代码拆分与公共代码提取:在多页面应用中,不同页面可能会有一些公共的代码,如第三方库、公共组件等。我们可以通过 splitChunks 配置将这些公共代码提取出来,减少每个页面的代码体积。例如:
module.exports = {
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name:'vendors',
          chunks: 'all'
        },
        common: {
          name: 'chunk-common',
          chunks: 'initial',
          minChunks: 2
        }
      }
    })
  }
}

上述配置将来自 node_modules 的代码拆分到 vendors.js 文件中,并且将至少被两个页面引用的公共代码拆分到 chunk-common.js 文件中。

  • 优化页面加载顺序:合理安排页面的加载顺序可以提升用户体验。例如,对于首屏页面,我们要确保关键资源(如 CSS、JavaScript 核心代码)优先加载。可以通过 html-webpack-plugin 的配置来调整页面中资源的加载顺序。例如:
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  chainWebpack: config => {
    config.plugin('html-index')
     .tap(args => {
        args[0].chunksSortMode = (chunk1, chunk2) => {
          const orders = ['chunk-common','vendors', 'index'];
          const order1 = orders.indexOf(chunk1.names[0]);
          const order2 = orders.indexOf(chunk2.names[0]);
          return order1 - order2;
        };
        return args;
      });
  }
}

上述代码通过 chunksSortModeindex 页面的代码块加载顺序进行了调整,确保 chunk-commonvendors 代码块先于 index 代码块加载。

七、自定义配置与构建优化的实践案例

7.1 案例背景

假设我们正在开发一个大型的电商平台前端项目,该项目使用 Vue CLI 构建。随着项目的不断发展,我们遇到了一些性能和配置问题,如构建速度慢、代码体积大、不同环境配置不一致等。为了解决这些问题,我们需要对项目的配置进行自定义,并实施一系列构建优化策略。

7.2 自定义配置实施

  • 环境变量配置:我们根据不同环境(开发、测试、生产)设置了不同的 API 地址、服务器端口等环境变量。例如,在 .env.development 中设置开发环境的 API 地址:
VUE_APP_API_URL = http://dev-api.example.com/api

.env.production 中设置生产环境的 API 地址:

VUE_APP_API_URL = https://api.example.com/api

vue.config.js 中,我们根据环境变量配置开发服务器的代理:

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: process.env.VUE_APP_API_URL,
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}
  • 模块解析配置:项目中有大量的组件和模块,为了方便引用,我们设置了模块别名。例如,我们将 src/components 目录设置为 @components 别名:
const path = require('path');

module.exports = {
  chainWebpack: config => {
    config.resolve.alias
     .set('@components', path.resolve(__dirname,'src/components'))
  }
}

这样,在组件中我们可以使用 import MyComponent from '@components/MyComponent.vue' 来引用组件,代码更加简洁。

7.3 构建优化实施

  • 代码拆分优化:我们通过 splitChunks 配置将第三方库和公共代码进行了拆分。将所有的第三方库代码拆分到 vendors.js 文件中,公共代码拆分到 chunk-common.js 文件中:
module.exports = {
  chainWebpack: config => {
    config.optimization.splitChunks({
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name:'vendors',
          chunks: 'all'
        },
        common: {
          name: 'chunk-common',
          chunks: 'initial',
          minChunks: 2
        }
      }
    })
  }
}

这样,每个页面加载时可以共享这些公共代码,减少了重复加载,提升了加载速度。

  • 图片优化:电商平台中有大量的商品图片,我们使用 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: 70
        },
        optipng: { enabled: false },
        pngquant: {
          quality: [0.70, 0.90],
          speed: 4
        },
        gifsicle: { interlaced: false },
        webp: { quality: 80 }
      })
  }
}

通过这些配置,图片的体积得到了显著压缩,页面加载速度得到了提升。

7.4 优化效果

通过上述自定义配置和构建优化策略的实施,项目的性能得到了明显提升。构建速度加快,代码体积减小,页面加载速度大幅提高。在开发环境中,开发效率得到了提升;在生产环境中,用户体验得到了显著改善。同时,通过合理的环境变量配置,不同环境之间的切换更加方便,项目的维护成本降低。

通过对 Vue CLI 自定义配置文件与构建优化策略的深入学习和实践,我们能够更好地应对项目开发过程中的各种需求,打造高性能、可维护的前端应用。无论是单页面应用还是多页面应用,通过合理运用这些技术,都可以在性能和开发效率上取得显著的提升。在实际项目中,我们需要根据项目的特点和需求,灵活运用这些配置和优化策略,不断探索和实践,以达到最佳的效果。