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

如何在Node.js脚本中导入Vue项目的Router进行静态分析?

解决方案

第一步:让Node.js能解析Vue组件和TypeScript路由

直接用ts-node加载项目的main.ts会因为无法识别.vue文件报错,我们需要给Node.js添加自定义的.vue文件加载逻辑,同时兼容TypeScript:

  1. 安装依赖
    先安装必要的工具包:
npm install -D vue-template-compiler @vue/component-compiler-utils ts-node typescript @types/node
  1. 编写自定义.vue加载器
    创建vue-node-loader.js,只提取Vue单文件组件的脚本部分(我们不需要渲染模板,仅分析组件逻辑):
const vueTemplateCompiler = require('vue-template-compiler');
const fs = require('fs');

require.extensions['.vue'] = function(module, filename) {
  const content = fs.readFileSync(filename, 'utf8');
  const parsed = vueTemplateCompiler.parseComponent(content);
  
  if (parsed.script?.content) {
    // 兼容TypeScript脚本
    const script = parsed.script.lang === 'ts' ? parsed.script.content : parsed.script.content;
    module._compile(script, filename);
  } else {
    module.exports = {};
  }
};
  1. 加载路由并验证
    创建router-analyzer.ts:
// 先引入自定义加载器
require('./vue-node-loader.js');

// 导入项目中的路由(路径根据实际项目结构调整)
import router from './src/main.ts';

// 测试是否成功加载路由
console.log('已加载路由总数:', router.getRoutes().length);

用ts-node运行脚本:

ts-node router-analyzer.ts

第二步:递归遍历路由组件树

拿到router对象后,遍历所有路由(包括子路由),记录每个组件对应的路由信息:

import fs from 'fs';

// 存储组件与对应路由的映射关系
const componentRouteMap = new Map<string, {
  routes: string[],
  component: any
}>();

// 递归遍历路由结构
function walkRoutes(routes: any[], parentPath = '') {
  routes.forEach(route => {
    const fullPath = parentPath + route.path;
    const comp = route.component;
    
    if (comp) {
      const compName = comp.name || `[匿名组件] ${fullPath}`;
      // 初始化映射条目
      if (!componentRouteMap.has(compName)) {
        componentRouteMap.set(compName, { routes: [], component: comp });
      }
      // 添加当前路由路径
      componentRouteMap.get(compName)!.routes.push(fullPath);
    }
    
    // 递归处理子路由
    if (route.children?.length) {
      walkRoutes(route.children, fullPath);
    }
  });
}

// 启动遍历
walkRoutes(router.getRoutes());

第三步:提取组件所用API

通过Babel解析组件脚本的AST(抽象语法树),找出所有API引用:

  1. 安装Babel依赖
npm install -D @babel/parser @babel/traverse @babel/types
  1. 编写API提取函数
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import * as t from '@babel/types';

function extractComponentAPIs(component: any): string[] {
  const apiSet = new Set<string>();
  let scriptContent = '';
  
  // 获取组件脚本内容
  if (component.__file) {
    scriptContent = fs.readFileSync(component.__file, 'utf8');
  } else {
    scriptContent = component.toString();
  }

  // 解析生成AST
  const ast = parse(scriptContent, {
    sourceType: 'module',
    plugins: ['typescript', 'jsx']
  });

  // 遍历AST识别API调用
  traverse(ast, {
    // 处理this.$xxx这类实例API
    MemberExpression(path) {
      if (t.isThisExpression(path.node.object)) {
        apiSet.add(`this.${path.node.property.name}`);
      }
      // 处理第三方库调用,比如axios.get
      if (t.isIdentifier(path.node.object)) {
        apiSet.add(`${path.node.object.name}.${path.node.property.name}`);
      }
    },
    // 处理直接调用的函数,比如axios()
    CallExpression(path) {
      if (t.isIdentifier(path.node.callee)) {
        apiSet.add(path.node.callee.name);
      }
    }
  });

  return Array.from(apiSet);
}

第四步:生成分析报告

整合所有数据,生成Markdown格式的分析报告:

function generateReport() {
  let report = '# 路由组件分析报告\n\n';
  
  report += '## 组件共享统计\n';
  componentRouteMap.forEach((data, compName) => {
    const sharedCount = data.routes.length;
    const apis = extractComponentAPIs(data.component);
    
    report += `### ${compName}\n`;
    report += `- 被 ${sharedCount} 个路由使用\n`;
    report += `- 所属路由:\n`;
    data.routes.forEach(route => report += `  - ${route}\n`);
    report += `- 使用的API:\n`;
    apis.forEach(api => report += `  - ${api}\n`);
    report += '\n';
  });

  // 保存报告到文件
  fs.writeFileSync('component-analysis-report.md', report);
  console.log('分析报告已生成:component-analysis-report.md');
}

// 执行报告生成
generateReport();

关键注意事项

  • 如果组件使用<script setup>语法糖,需要改用@vue/compiler-sfc解析setup部分,替换原有的vue-template-compiler逻辑。
  • 对于懒加载路由(比如() => import('./Home.vue')),需要手动触发加载,Node.js不会自动解析动态import,可以用require替换或提前预加载组件。
  • 全局注册的组件需要额外从Vue实例的app.component中收集,补充到分析逻辑里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:10:42