You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Vite的Vue应用预生成导航数据的最优方案咨询

最优方案:虚拟模块(Virtual Module)

直接给出结论:虚拟模块是你当前场景下的最优选择,另外两个方案的劣势很明显:

  • 独立脚本:需要额外预执行步骤,还要维护临时文件,JSON修改后得重新跑脚本,完全没有Vite生态的便捷性,直接排除。
  • 非虚拟模块的Vite插件:本质上和虚拟模块属于同一类方案,但虚拟模块的实现更直观,导入方式和普通模块完全一致,代码可读性更高,没必要舍近求远。

虚拟模块的核心优势是完全集成在Vite的构建流程中,不需要额外操作,开发时修改JSON会自动触发热更新,生产构建时直接把导航数据打包进代码,不会产生冗余请求。下面是具体实现步骤:

1. 编写Vite虚拟模块插件

在项目根目录创建vite-plugin-nav-data.js:

import fs from 'fs/promises';
import path from 'path';

export default function navDataPlugin() {
  return {
    name: 'vite-plugin-nav-data', // 插件名称,必填
    // 识别虚拟模块ID
    async resolveId(id) {
      if (id === 'virtual:nav-data') {
        return '\0' + id; // 加\0前缀避免和真实文件冲突
      }
    },
    // 加载虚拟模块内容
    async load(id) {
      if (id === '\0virtual:nav-data') {
        const contentDir = path.resolve(process.cwd(), 'content');
        const nav = [];

        // 递归遍历content下所有JSON文件
        async function scanDir(dir) {
          const entries = await fs.readdir(dir, { withFileTypes: true });
          for (const entry of entries) {
            const fullPath = path.join(dir, entry.name);
            if (entry.isDirectory()) {
              await scanDir(fullPath);
            } else if (entry.isFile() && entry.name.endsWith('.json')) {
              const jsonContent = await fs.readFile(fullPath, 'utf-8');
              const data = JSON.parse(jsonContent);
              if (data.title) {
                // 提取相对路径作为路由标识(可根据需求调整)
                const relativePath = path.relative(contentDir, fullPath).replace('.json', '');
                nav.push({ title: data.title, path: relativePath });
              }
            }
          }
        }

        await scanDir(contentDir);
        // 返回ES模块代码,直接导出导航数据
        return `export default ${JSON.stringify(nav, null, 2)}`;
      }
    }
  };
}

2. 在Vite配置中注册插件

修改vite.config.js:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import navDataPlugin from './vite-plugin-nav-data.js';

export default defineConfig({
  plugins: [vue(), navDataPlugin()]
});

3. 在Vue组件中直接使用

需要导航的组件里直接导入虚拟模块:

<template>
  <nav class="sidebar-nav">
    <ul>
      <li v-for="item in navList" :key="item.path">
        <router-link :to="`/${item.path}`">{{ item.title }}</router-link>
      </li>
    </ul>
  </nav>
</template>

<script setup>
import navList from 'virtual:nav-data';
</script>

额外说明

  • 热更新支持:开发时修改任意JSON文件的title,Vite会自动重新生成虚拟模块并触发组件热更新,不需要手动刷新。
  • 生产构建优化:打包时导航数据会直接嵌入到代码中,不会加载任何冗余的JSON内容,性能拉满。
  • 自定义扩展:如果需要更多导航字段(比如排序权重、图标等),只需要修改插件中nav.push的内容即可。

内容的提问来源于stack exchange,提问作者CMTV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:46:11