您会注意到在项目结构中我们有两个资源目录:/public/
和/src/assets/
。他们有什么区别?一些是静态资源,而另一些则由构建系统进行处理和嵌入。
所以我们试着回答上面的问题。我们首先谈谈使用常规资源,然后我们将看到相对于静态资源的区别。
常规资源 - /src/assets
在*.vue
组件中,所有模板和CSS都由vue-html-loader
和css-loader
解析以查找资源URL。例如,在<img src="./logo.png">
和background:url(./logo.png)
中,"./logo.png"
是一个相对的资源路径,并且会被Webpack作为模块依赖进行处理。
因为logo.png
不是JavaScript,所以当被视为模块依赖时,我们需要使用url-loader
和file-loader
来处理它。 Quasar CLI已经为您配置了这些webpack加载程序,因此您可以免费使用文件名指纹(filename fingerprinting)和选择性base64内嵌(conditional base64 inlining)等功能,同时可以使用相对/模块路径而不必担心部署。
由于这些资源可能在构建过程中被内嵌/复制/重命名,因此它们基本上是源代码的一部分。这就是为什么建议将Webpack处理过的资源放在/src/assets
中,与其他源文件一起。实际上,你甚至不需要把它们都放在/src/assets
中:你可以根据模块/组件使用它们来组织它们。例如,您可以将每个组件放在其自己的目录中,其静态资源就位于其旁边。
资源处理规则
相对URL,例如./assets/logo.png
将被解释为模块依赖项。它们将被替换为基于您的Webpack输出配置自动生成的URL。
以~
为前缀的URL被视为模块请求,类似于require('some-module/image.png')
。如果你想利用Webpack的模块解析配置,你需要使用这个前缀。 Quasar提供assets
的开箱即用的Webpack别名,因此建议您像这样使用它:<img src="~assets/logo.png">
。注意‘assets’前面的’~’。
静态资源 - /public
根相对URL(例如/logo.png
– 其中“/”指的是publicPath)或logo.png
根本不处理。这些资源应该放在public/
中。它们将不会被Webpack处理。public文件夹里的内容将按原样简单复制到可分发文件夹。
Quasar在底层有一些聪明的算法,确保无论您构建什么(SPA,PWA,Cordova,Electron),您的静态资源都能被正确引用(当且仅当它们不使用相对路径)。
<!-- 很好! -->
<img src="logo.png">
<!--
很坏! 直到您更改vue路由器模式(hash/history)
或您的公共路径后它才能工作。
不要这样做!
-->
<img src="/logo.png">
常规资源 vs 静态资源
“assets”文件夹中的文件仅包含在您的构建中,如果它们在其中一个Vue文件中具有文字引用。 无论如何,“public”文件夹中的每个文件和文件夹都会按原样复制到生产版本中。
WARNING
如果没有构建SPA/PWA/SSR,那么/public/icons/*
和/public/favicon.ico
将不会嵌入到您的应用中,因为它们不会用于任何目的。 例如,Electron或Cordova应用程序不需要这些文件。
Vue仅绑定所需的静态资源
请注意,无论什么时候您将“src”绑定到Vue范围内的变量,此变量必须是来自public文件夹。 原因很简单:URL是动态的,所以Webpack(它在编译时打包资源)不知道在运行时将引用哪个文件,所以它不会处理URL。
<template>
<!-- imageSrc必须指向一个/public目录下的文件 -->
<img :src="imageSrc">
</template>
<script>
export default {
data () {
return {
/*
指向 /public.
注意字符串不以斜杠 (/)开始。
*/*
imageSrc: 'logo.png'
}
}
}
</script>
您可以使用src
作为Vue属性来强制提供静态资源。 使用:src=" 'path/to/image' "
或:src="imageSrc"
而不是src="path/to/image"
。 请注意在第二个代码示例中使用双引号内的单引号(已添加空格以在文档网站上直观地看到它 - 通常您没有空格)。
在JavaScript中获取资源路径
为了让Webpack返回正确的资源路径,您需要使用require('./relative/path/to/file.jpg')
,它将被file-loader
处理并返回解析后的URL。 例如:
computed: {
background () {
return require('./bgs/' + this.id + '.jpg')
}
}
请注意,上面的例子将包含最终版本中./bgs/
下的所有图像。 这是因为Webpack无法猜测它们中的哪些将在运行时使用,所以它包含了它们全部。