Vite引用本地静态资源的正确方式

 更新时间:2024年12月06日 08:53:20   作者:喺小VIE  
在前端开发中,除了通过 API 动态请求的数据外,还有一些诸如 HTML 文件、图片、字体等文件需要在项目中被用到,通常这些被视为静态资源,本文将基于 Vite + React 来讲述并解锁 Vite 引用本地静态资源的正确姿势,需要的朋友可以参考下

前言

在前端开发中,除了通过 API 动态请求的数据外,还有一些诸如 HTML 文件、图片、字体等文件需要在项目中被用到,通常这些被视为静态资源。对于静态资源的管理和引用方式有时也会产生让人困惑的问题,就比如在 Vite 构建的项目中引用图片资源时,如果引用方式不正确就可能会出现意外的 “图裂” 情况。

本文将基于 Vite + React 来讲述并解锁 Vite 引用本地静态资源的正确姿势,主要包括 Vite 对本地资源的静态引用和动态引用两种方式,并结合一个案例来演示动态引用资源的实现过程。

静态资源目录结构

静态资源的存放位置基本上是约定俗成的,public目录和src/assets

  • public:目录中一般会放着index.htmlfavicon.ico
  • src/assets:而其他业务编码中会使用的静态资源,如图片、字体等会统一放在srcassets目录下。

比如这是我所开发的一个项目中所用到的部分图片资源:

引用图片资源的常规方式

在基础前端项目开发中,通常会用到三种常规的加载图片的方式,<img>元素、background样式、JS 脚本动态指定src属性。

  • <img>:在 HTML中通过<img>元素指定src引用图片资源。
<img src="./assets/logo.png" alt="" />
  • background:通过background: url()background-image: url()引用本地资源。
#logo {
  background: url('./assets/logo.png');
}
#logo {
  background-image: url('./assets/logo.png');
}
  • JS 脚本动态指定图片src属性。
document.getElementById('logo').src = './assets/logo.png'

配置路径别名 @assets

为了更灵活地引用项目中的静态资源,往往会给特定的路径配置别名以方便引用,比如常见的src对应@src/assets对应@assets

如果项目中使用 Vite 构建,可以在vite.config.ts中作如下配置:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  base: './',
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.join(__dirname, './src'),
      '@assets': path.join(__dirname, './src/assets'),
    },
  },
}); 

Vite 项目中引用图片资源

在以 Vite 为底层构建的 React 项目中引用图片资源就不能再同于以往常规的方式了(这也包括以 Webpack 为底层构建的 CRA 项目)。

由于 Vite 或者 Webpack 这类打包工具对静态资源有特定的处理方式,在这里我们需要给引用资源的方式分为两类:静态引入和动态引入。

静态引用图片资源

静态引入图片资源就是使用像 Tailwind CSS、CSS 样式或者指定<img>元素的src属性这样的。

需要注意的是在<img>元素中,src属性使用@路径别名是无效的,这是因为对于 Vite 来说src中的内容就是单纯的字符串,即使是配置了路径别名也并不会当做资源文件去处理;当然如果想使用@路径别名指定src也是有方法的,这时则需要通过动态引入的方式。

  • Tailwind CSS:
<div className='
  w-full h-full
  bg-[url("@assets/images/boat.png")]
  bg-contain bg-no-repeat bg-center'>
</div>
  • CSS:
div {
  background-image: url("@assets/images/boat.png");
}

  • <img>元素指定src属性,使用常规的绝对路径:
<img
  src="/src/assets/images/boat.png"
  alt="Preview"
  className='max-w-full max-h-full object-contain'
  />
  • <img>元素指定src属性,使用@路径别名是无效的:
<img
  src="@assets/images/boat.png"
  alt="Preview"
  className='max-w-full max-h-full object-contain'
  />

动态引用图片资源

动态引用图片资源就是用importnew URL(url, import.meta.url)这样的方式。

import.meta.url 是一个 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的 URL 构造器组合使用,在一个 JavaScript 模块中,通过相对路径我们就能得到一个被完整解析的静态资源 URL。

  • import:Vite 中引入一个静态资源会返回解析后的公共路径,生产构建后生成散列文件名:
import boatImage from '@assets/images/boat.png';

const Main = () => {
  return (
    <img
      src={boatImage}
      alt="Preview"
      className='max-w-full max-h-full object-contain'
      />
  );
};

export default Main;

  • new URL(url, import.meta.url)
const boatImage = new URL('@assets/images/boat.png', import.meta.url).href;

const Main = () => {
  return (
    <img
      src={boatImage}
      alt="Preview"
      className='max-w-full max-h-full object-contain'
      />
  );
};

export default Main;

Vite 动态引用本地图片案例

我们以一个菜单列表为案例演示 Vite 项目中动态引用图片资源。在业务需求中,菜单列表中会展示固定的一些图标,这些就是本地图片资源。

菜单数据列表

在菜单数据列表中,icon属性就是本地图片路径,这里用了一个自定义函数获取,后面会给到。

const menuItems = [
  {
    id: 'profile',
    name: 'Profile',
    icon: getAssetsFile('menu/Profile.png')
  },
  {
    id: 'favorites',
    name: 'Favorites',
    icon: getAssetsFile('menu/Favorites.png')
  }
]

页面结构

页面结构中,主要分为菜单图片和菜单的描述文本。

在这里菜单图标是通过行内样式指定图片路径的,如果使用静态引用的方式那么icon就是绝对路径,如果是动态引用,那么icon的路径就是需要通过new URL()获取。

<div className='flex w-[72px] h-full pt-[24px] pr-0 pb-[24px] pl-0 flex-col gap-[24px] items-center flex-nowrap bg-[#fff] border-solid border-r border-r-[rgba(0,0,0,0.1)] absolute top-[64px] left-0 overflow-hidden z-[36]'>
  {menuItems.map((item) => (
  <div
    key={item.id}
    className={`flex h-[49px] flex-col justify-center items-center self-stretch shrink-0 flex-nowrap relative cursor-pointer border-l-4 ${activeMenu === item.id ? 'border-l-[#ffd05a]' : 'border-l-transparent'}`}
    onClick={() => handleMenuClick(item.id)}
  >
    {/* 菜单图标 */}
    <div
      className="w-[32px] h-[32px] shrink-0 bg-cover bg-no-repeat relative overflow-hidden"
      style={{ backgroundImage: `url(${item.icon})` }}
    />
    {/* 菜单描述 */}
    <span className="h-[20px] shrink-0 basis-auto font-['Inter'] text-[14px] font-normal leading-[20px] text-[#323232] relative text-left whitespace-nowrap">
      {item.name}
    </span>
  </div>
  ))}
</div>

动态获取图片路径

前面我们提到icon的路径是由一个自定义函数getAssetsFile获取的。实际上就是通过new URL()的方式动态获取图片路径。

// 获取assets静态资源
export const getAssetsFile = (url: string) => {
  return new URL(`../assets/images/${url}`, import.meta.url).href;
};

回顾总结

最后回顾总结一下:

  • 静态资源常见存放目录
    • public
    • src/assets
  • 引用图片资源的常规方式
    • <img>元素指定src
    • background: url()background-image: url()样式
    • JS 脚本动态指定src属性
  • Vite 静态引用图片资源
    • background: url()background-image: url()样式
    • <img>元素指定src属性,使用绝对路径或相对路径
  • Vite 动态引用图片资源
    • import导入
    • new URL(url, import.meta.url)

以上就是Vite引用本地静态资源的正确方式的详细内容,更多关于Vite引用本地静态资源的资料请关注脚本之家其它相关文章!

相关文章

  • 手写Vue内置组件component的实现示例

    手写Vue内置组件component的实现示例

    本文主要介绍了手写Vue内置组件component的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • vue内置组件component--通过is属性动态渲染组件操作

    vue内置组件component--通过is属性动态渲染组件操作

    这篇文章主要介绍了vue内置组件component--通过is属性动态渲染组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • vue-print-nb解决vue打印问题,并且隐藏页眉页脚方式

    vue-print-nb解决vue打印问题,并且隐藏页眉页脚方式

    这篇文章主要介绍了vue-print-nb解决vue打印问题,并且隐藏页眉页脚方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Vue使用watch监听一个对象中的属性的实现方法

    Vue使用watch监听一个对象中的属性的实现方法

    这篇文章主要介绍了Vue使用watch监听一个对象中的属性的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • 在Vue中使用JSONP进行跨域数据传输的完整指南

    在Vue中使用JSONP进行跨域数据传输的完整指南

    本文将介绍JSONP(JSON with Padding)的原理和用法,以及如何使用JSONP进行跨域数据传输,详细解释JSONP的工作原理,并提供前端和后端的代码示例,帮助你理解和实践JSONP跨域请求,需要的朋友可以参考下
    2023-06-06
  • vue打包之后配置统一请求地址步骤详解

    vue打包之后配置统一请求地址步骤详解

    这篇文章主要为大家介绍了vue打包之后配置统一请求地址实现步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • vue项目实现添加图片裁剪组件

    vue项目实现添加图片裁剪组件

    这篇文章主要为大家详细介绍了vue项目实现添加图片裁剪组件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue+Element实现动态生成新表单并添加验证功能

    Vue+Element实现动态生成新表单并添加验证功能

    这篇文章主要介绍了Vue+Element实现动态生成新表单并添加验证功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • Vue 中 provide和inject的使用

    Vue 中 provide和inject的使用

    这篇文章主要介绍了Vue中provide和inject的使用,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • 在vue中获取dom元素内容的方法

    在vue中获取dom元素内容的方法

    本篇文章主要介绍了在vue中获取dom元素内容的方法,可以通过给标签加ref属性,这里整理了详细的代码,有兴趣的可以了解一下
    2017-07-07

最新评论