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>
标签包含进来。