[Vite] 静态资源的动态访问

前言

这篇笔记是对渡一教育网课的知识点总结,源视频👉 静态资源的动态访问【渡一教育】

静态资源与打包规则

Vite脚手架在打包代码的时候,会把源代码里对于静态资源的访问路径转换为打包后静态资源文件的路径。主要的区别是文件指纹,即打包后的文件会带上一个hash值,用于区分不同版本的文件。

文件指纹的作用:

客户端会缓存文件。当前端项目更新之后,重新打包、部署,由于文件指纹的存在,客户端检测到文件名不同,则会下载新版的文件。如果没有文件指纹,且新旧版文件名一致,客户端会读缓存,而不能及时地拿到新版文件。

动态访问静态资源

动态访问静态资源通常导致读取不到文件,因为源代码中使用的路径是src中的,而打包之后静态资源带上了文件指纹,代码中的路径却没有随之改变。

如下情景属于对静态资源的动态访问,也就是说使用了插值语法,而变量值只有在代码执行中才被确定:

  • css中的background-image: url()使用v-bind动态地绑定一张图片的路径;
  • template中节点的style,在background-image:url()使用插值语法;
  • img节点的src属性使用动态绑定传递图片路径。

方法一:直接导入

import img1 from './assets/1.jpg';
import img2 from './assets/2.jpg';
...

const imgName = ref('');
function handleChange(val){
    if(val === 1){
        imgName.value = img1;
    }else if(...){
		...
    }
}
<img :src="imgName" />

将所有可能用到的图片都导入,并配合if语句实现动态切换。

缺点

  • 代码臃肿,难以维护。

方法二:静态资源转移到Public目录

转移到public目录的静态资源文件会原封不动地被打包到dist文件夹中,不用担心文件名发生变化,在源代码中直接使用绝对路径访问静态资源即可:/assets/1.jpg

但缺点就是失去了文件指纹带来的好处,后期如果静态资源被替换了,但是文件名没变,客户端仍读取缓存,无法及时获取最新版的静态资源。

方法三:动态导入

const imgName = ref('');
const url = ref('');

watchEffect(async()=>{
    const module = await import('./assets/${imgName.value}.jpg');
    console.log(module);
    // ...后续操作
});

Vite脚手架在静态分析代码的时候,读取到动态导入import(),且内部是模板字符串,只有一部分内容是动态的,那么Vite会自动将符合./assets/*.jpg路径格式的静态资源全部进行打包。

在打包的时候,不仅会打包所有符合情况的静态资源,还会打包出对应的.js文件。import()语句实际上是导入.js文件,而.js文件又默认导出打包后的静态资源文件路径。

缺点

  • 打包结果多出许多.js文件;
  • 异步导入。

方法四:URL构造函数

使用计算属性computedURL

const url = computed(()=>{
    const obj = new URL(`./assets/${imgName.value}.jpg`, import.meta.url); 
    return obj.pathname;
});

URL传入两个参数:1. 文件路径;2. 基准路径。

返回URL实例对象的pathname属性,即是打包后的文件路径。

<div :style="{backgroundImage: url(url)}">
</div>

原理

单文件组件在进行打包的时候,会分析以下内容:

  1. <img>标签的src属性;
  2. cssbackground-image属性的url()函数;

1和2:如果是静态的,则会进行路径转换。

  1. import()
  2. new URL();

3和4:可以是动态的,但是只能是某一个部分是动态的。通常是模板字符串。这种情况下会把指定文件夹下面的指定格式的文件全部打包,并进行路径转换。3会生成额外的.js文件,4不会。

总结

以上的方法中,使用URL的方法是最优的。

  • 支持动态导入;
  • 保留文件指纹;
  • 不会产生额外的.js文件;
  • 同步代码。

热门相关:名门贵妻:暴君小心点   走私大明   妖夏   神秘老公,晚上见!   花都保镖