Vite动态导入静态资源与自动依赖发现过程

 更新时间:2025年10月28日 08:41:48   作者:斯~内克  
文章主要介绍了在Vite中动态导入静态资源的三种方案,并讨论了Vite自动依赖发现的条件,文章还提供了一些代码示例和优化建议,以帮助开发者更高效地管理动态资源和依赖预构建

一、Vite 动态导入静态资源

在 Vite 中,动态加载图片、JSON 等静态资源是高频需求,但动态路径拼接可能导致构建失败或资源未识别。

以下结合示例代码,分析三种实现方案:

1. 方案一:new URL 动态路径转换

通过 new URL 拼接路径,Vite 自动处理资源引用:

const pathKey = `../assets/${val}.jpg`;
const src = new URL(pathKey, import.meta.url);
imgSrc.value = src.href;

原理与限制

  • Vite 会将路径转换为构建后的哈希 URL(如 _assets/1-abc123.jpg)。
  • 限制:路径必须为静态字符串模板(如 `../assets/${val}.jpg`),不可使用完全动态变量(如 pathKey = '../assets/' + val + '.jpg'),否则构建时无法解析。

2. 方案二:import() 动态导入

使用 import() 语法按需加载资源:

import(`../assets/${val}.jpg`).then((res) => {
  imgSrc.value = res.default;
});

特性

  • 构建时,Vite 会分析 ../assets/ 下的所有 .jpg 文件,生成对应 chunk。
  • 问题:若 val 的取值在构建时无法确定(如用户输入),可能导致资源缺失。

3. 方案三:import.meta.glob 批量预加载

通过 Glob 模式预加载所有匹配资源,运行时按需获取:

// 预加载所有 jpg 文件(构建时生成映射表)
const srcs = import.meta.glob("../assets/*.jpg", { as: "url" });

// 运行时动态获取
const pathKey = `../assets/${val}.jpg`;
const url = await srcs[pathKey]();
imgSrc.value = url;

优势

  • 构建时生成所有资源的 URL 映射表,避免运行时路径不确定性。
  • { as: 'url' } 表示直接返回资源 URL,无需手动处理 default 属性。

二、代码示例的问题与优化

1. 路径严格匹配问题

示例代码中,pathKey 必须与 Glob 生成的键完全一致(如 ../assets/2.jpg)。若文件名含动态前缀(如时间戳),需调整 Glob 模式:

// 松散匹配文件名中的数字
const srcs = import.meta.glob("../assets/[0-9].jpg", { as: "url" });

2. 资源未找到的兜底处理

通过 try/catch 或条件判断增强健壮性:

try {
  const url = await srcs[pathKey]();
  imgSrc.value = url;
} catch {
  imgSrc.value = fallbackImage; // 加载默认图
}

三、Vite 自动依赖发现的条件

Vite 的依赖预构建(Pre-Bundling)是性能优化的核心,其触发条件如下:

1. 依赖类型识别

  • CommonJS 模块:若 node_modules 中的依赖未提供 ESM 格式,Vite 自动预构建。
  • 嵌套依赖:若依赖内部引用了其他 CJS 模块(如 lodash 的子包),触发预构建。
  • 非优化入口:依赖的 package.json 未指定 moduleexports 字段。

2. 代码中的导入方式

  • 静态导入import axios from 'axios' 会被自动分析。
  • 动态导入import('lodash') 若路径为字符串字面量,触发预构建。
  • 完全动态路径import(someVar) 不会触发预构建,可能导致运行时加载问题。

3. 配置干预

vite.config.js 中手动控制依赖:

export default {
  optimizeDeps: {
    include: ['lodash/debounce'], // 强制预构建特定子模块
    exclude: ['jquery'],          // 排除无需预构建的库
  },
}

四、实战:动态资源与依赖预构建的联动问题

场景:动态加载第三方图标库

假设项目中按需加载 @ant-design/icons 的图标:

const loadIcon = async (name) => {
  const icon = await import(`@ant-design/icons/${name}.js`);
  return icon;
};

问题:Vite 默认不会预构建 @ant-design/icons 的子模块,导致运行时加载延迟。

解决方案

在配置中显式声明需要预构建的子模块:

// vite.config.js
export default {
  optimizeDeps: {
    include: ['@ant-design/icons/HomeOutlined'],
  },
}

五、总结与最佳实践

1. 动态资源加载

  • 优先使用 import.meta.glob:提前声明资源范围,避免路径不确定性。
  • 统一资源目录:如将所有动态图片放在 src/assets/dynamic/ 下,通过 Glob 简化匹配。
  • 处理未找到资源:添加日志与兜底逻辑,提升用户体验。

2. 依赖预构建优化

  • 监控控制台输出:运行 vite build 时,检查哪些依赖被自动预构建。
  • 按需手动包含:对大型库的子模块(如 lodashantd),通过 include 减少构建体积。
  • 慎用 exclude:除非明确知晓依赖的模块格式,否则避免盲目排除。

3. 调试工具推荐

  • 构建分析:使用 rollup-plugin-visualizer 查看产物结构。
  • 依赖检查:运行 npx vite deps 查看预构建的依赖列表。

通过上述实践,开发者可以高效管理 Vite 中的动态资源,同时精准控制依赖预构建策略,实现性能与可维护性的最佳平衡。

<template>
  <div>
    <el-switch
      v-model="value"
      :active-value="2"
      :inactive-value="1"
      active-color="#13ce66"
      inactive-color="#ff4949"
      @change="handleChange"
    >
    </el-switch>
    <img :src="imgSrc" alt="" />
  </div>
</template>
<script setup lang="ts">
import { ref } from "vue";
// import a   from "../assets/1.jpg";
// console.log("a", a);

const value = ref(1);
const imgSrc = ref("");
const handleChange = async (val: any) => {
  console.log(val);

  // const src = new URL(`../assets/${val}.jpg`, import.meta.url);
  // console.log("src", src);
  // imgSrc.value = src.href;

  // import("../assets/" + val + ".jpg").then((res) => {
  //   console.log("res", res);
  //   imgSrc.value = res.default;
  // });

  const srcs = import.meta.glob("../assets/*.jpg", { as: "url" });
  console.log("srcs", srcs);
  // 构建对应的路径 key(注意文件名匹配要完全一致)
  const pathKey = `../assets/${val}.jpg`;
  try {
    const url = await srcs[pathKey]();
    imgSrc.value = url;
  } catch {
    imgSrc.value = ""; // 加载默认图
  }
};
</script>
<style lang="scss" scoped>
img {
  width: 1200px;
  height: 600px;
}
</style>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue前后端分离如何解决每次请求session都会变的问题

    vue前后端分离如何解决每次请求session都会变的问题

    这篇文章主要介绍了vue前后端分离如何解决每次请求session都会变的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 使用 Vue3 实现文章目录功能

    使用 Vue3 实现文章目录功能

    本文给大家分享如何使用vue3实现文章目录功能,特色功能主要是自动高亮选中当前正在阅读的章节,自动展开当前正在阅读的章节的子标题,并隐藏其他章节的子标题,代码简单易懂,感兴趣的朋友跟随小编一起看看吧
    2022-03-03
  • vue-electron中修改表格内容并修改样式

    vue-electron中修改表格内容并修改样式

    本文主要介绍了vue-electron中修改表格内容并修改样式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Vue Ref全家桶具体用法详解

    Vue Ref全家桶具体用法详解

    ref用来辅助我们获取DOM元素或组件的引用实例对象,每个vue的组件实例上,都包含一个refs对象,里面存储着对应的DOM元素或组件的引用,默认情况下,组件的refs指向一个空对象
    2023-03-03
  • 基于form-data请求格式详解

    基于form-data请求格式详解

    今天小编就为大家分享一篇基于form-data请求格式详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • Vue.js中使用Vuex但未正确配置Store问题以及解决过程

    Vue.js中使用Vuex但未正确配置Store问题以及解决过程

    这篇文章主要介绍了Vue.js中使用Vuex但未正确配置Store问题以及解决过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • vue router 跳转时打开新页面的示例方法

    vue router 跳转时打开新页面的示例方法

    这篇文章主要介绍了vue router 跳转时打开新页面的示例方法,本文通过示例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • vue的hash值原理也是table切换实例代码

    vue的hash值原理也是table切换实例代码

    这篇文章主要介绍了vue的hash值原理也是table切换,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Vue+elementUI el-input输入框手机号校验功能

    Vue+elementUI el-input输入框手机号校验功能

    这篇文章主要介绍了Vue+elementUI el-input输入框手机号校验功能,限制input框内只能输入数字,且为11位,通过实例代码介绍了对输入手机号做校验的方法,感兴趣的朋友跟随小编一起看看吧
    2023-10-10
  • Vue中this.$nextTick()的具体使用

    Vue中this.$nextTick()的具体使用

    本文主要介绍了Vue中this.$nextTick()的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02

最新评论