⚠️ Vue CLI 处于维护模式!

对于新项目,现在建议使用 create-vue 来搭建基于 Vite 的项目。还可以参考 Vue 3 工具指南 获取最新建议。

HTML 和静态资源

HTML

索引文件

文件 public/index.html 是一个模板,它将使用 html-webpack-plugin 进行处理。在构建过程中,资产链接将自动注入。此外,Vue CLI 还自动注入资源提示(preload/prefetch)、清单/图标链接(当使用 PWA 插件时)以及构建过程中生成的 JavaScript 和 CSS 文件的资产链接。

插值

由于索引文件用作模板,因此可以使用 lodash 模板 语法在其中插入值

  • <%= VALUE %> 用于未转义的插值;
  • <%- VALUE %> 用于 HTML 转义的插值;
  • <% expression %> 用于 JavaScript 控制流。

除了 html-webpack-plugin 公开默认值 之外,所有 客户端环境变量 也可以直接使用。例如,要使用 BASE_URL

<link rel="icon" href="<%= BASE_URL %>favicon.ico">

另请参阅

预加载

<link rel="preload"> 是一种资源提示,用于指定页面在加载后不久将需要的资源,因此您希望在页面加载生命周期的早期阶段开始预加载这些资源,在浏览器的主要渲染机制启动之前。

默认情况下,Vue CLI 应用会自动为所有用于初始渲染应用的文件生成预加载提示。

这些提示使用 @vue/preload-webpack-plugin 注入,可以通过 chainWebpack 作为 config.plugin('preload') 进行修改/删除。

预取

<link rel="prefetch"> 是一种资源提示,它告诉浏览器在页面加载完成后,在浏览器的空闲时间预取用户可能在不久的将来访问的内容。

默认情况下,Vue CLI 应用会自动为所有为异步块生成的 JavaScript 文件生成预取提示(作为 通过动态 import() 进行按需代码拆分 的结果)。

这些提示使用 @vue/preload-webpack-plugin 注入,可以通过 chainWebpack 作为 config.plugin('prefetch') 进行修改/删除。

多页面设置说明

当使用多页面设置时,上面的插件名称应更改为匹配结构 'prefetch-{pagename}',例如 'prefetch-app'。

示例

// vue.config.js
module.exports = {
  chainWebpack: config => {
    // remove the prefetch plugin
    config.plugins.delete('prefetch')

    // or:
    // modify its options:
    config.plugin('prefetch').tap(options => {
      options[0].fileBlacklist = options[0].fileBlacklist || []
      options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
      return options
    })
  }
}

当预取插件被禁用时,可以使用 webpack 的内联注释手动选择要预取的特定块

import(/* webpackPrefetch: true */ './someAsyncComponent.vue')

webpack 的运行时将在父块加载时注入预取链接。

提示

预取链接会消耗带宽。如果您有一个包含许多异步块的大型应用,并且您的用户主要是移动用户,因此带宽意识很强,您可能希望禁用预取链接并手动选择要预取的块。

禁用索引生成

当将 Vue CLI 与现有后端一起使用时,您可能需要禁用 index.html 的生成,以便生成的资产可以在服务器渲染的页面中使用。为此,可以在 vue.config.js 中添加以下内容

// vue.config.js
module.exports = {
  // disable hashes in filenames
  filenameHashing: false,
  // delete HTML related webpack plugins
  chainWebpack: config => {
    config.plugins.delete('html')
    config.plugins.delete('preload')
    config.plugins.delete('prefetch')
  }
}

但是,这并不真正推荐,因为

  • 硬编码的文件名使得实现有效的缓存控制更加困难。
  • 硬编码的文件名也不利于代码拆分,代码拆分会生成具有不同文件名的其他 JavaScript 文件。
  • 硬编码的文件名不适用于 现代模式

相反,您应该考虑使用 indexPath 选项在您的服务器端框架中使用生成的 HTML 作为视图模板。

构建多页面应用

并非所有应用都必须是 SPA。Vue CLI 支持使用 vue.config.js 中的 pages 选项 构建多页面应用。构建的应用将有效地共享多个入口之间的公共块,以实现最佳加载性能。

静态资源处理

静态资源可以通过两种不同的方式处理

  • 在 JavaScript 中导入或通过模板/CSS 中的相对路径引用。此类引用将由 webpack 处理。

  • 放置在 public 目录中并通过绝对路径引用。这些资产将被简单地复制,不会经过 webpack。

相对路径导入

当您在 JavaScript、CSS 或 *.vue 文件中使用相对路径(必须以 . 开头)引用静态资源时,该资源将被包含到 webpack 的依赖关系图中。在此编译过程中,所有资产 URL(例如 <img src="...">background: url(...) 和 CSS @import)将作为模块依赖关系解析

例如,url(./image.png) 将被转换为 require('./image.png'),并且

<img src="./image.png">

将被编译为

h('img', { attrs: { src: require('./image.png') }})

在内部,我们配置了 webpack 资产模块 来确定具有版本哈希和正确公共基本路径的最终文件位置,并有条件地内联小于 8KiB 的资产,从而减少 HTTP 请求的数量。

您可以通过 chainWebpack 调整内联文件大小限制。例如,要将内联图像的限制设置为 4KiB

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('images')
        .set('parser', {
          dataUrlCondition: {
            maxSize: 4 * 1024 // 4KiB
          }
        })
  }
}

URL 转换规则

  • 如果 URL 是绝对路径(例如 /images/foo.png),它将按原样保留。

  • 如果 URL 以 . 开头,它将被解释为相对模块请求,并根据您文件系统上的文件夹结构进行解析。

  • 如果 URL 以 ~ 开头,它后面的任何内容都将被解释为模块请求。这意味着您甚至可以引用节点模块中的资产

    <img src="~some-npm-package/foo.png">
    
  • 如果 URL 以 @ 开头,它也将被解释为模块请求。这很有用,因为 Vue CLI 默认将 @ 作为 <projectRoot>/src 的别名。(仅限模板)

public 文件夹

放置在 public 文件夹中的任何静态资源将被简单地复制,不会经过 webpack。您需要使用绝对路径引用它们。

注意,我们建议将资产作为模块依赖关系图的一部分导入,以便它们经过 webpack,并具有以下优点

  • 脚本和样式表被压缩并捆绑在一起,以避免额外的网络请求。
  • 丢失的文件会导致编译错误,而不是为您的用户提供 404 错误。
  • 结果文件名包含内容哈希,因此您无需担心浏览器缓存其旧版本。

public 目录提供了一个应急通道,当您通过绝对路径引用它时,需要考虑您的应用程序将部署到哪里。如果您的应用程序没有部署在域的根目录下,则需要在您的 URL 前面加上 publicPath

  • public/index.html 或其他用作 html-webpack-plugin 模板的 HTML 文件中,您需要在链接前面加上 <%= BASE_URL %>

    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    
  • 在模板中,您需要先将基本 URL 传递到您的组件。

    data () {
      return {
        publicPath: process.env.BASE_URL
      }
    }
    

    然后

    <img :src="`${publicPath}my-image.png`">
    

何时使用 public 文件夹

  • 您需要在构建输出中包含一个具有特定名称的文件。
  • 您有成千上万的图像,需要动态引用它们的路径。
  • 某些库可能与 Webpack 不兼容,您别无选择,只能将其作为 <script> 标签包含进来。