开发工具IDE前端【免费下载链接】veturVue tooling for VS Code.项目地址https://gitcode.com/gh_mirrors/ve/vetur点击查看免费下载本文以 Vetur 仓库中的 RFC 002Monorepo 支持 为骨架结合 RFC 001vetur.config.js 配置文件、setup 文档、VLS 源码server/src/services/vls.ts、server/src/config.ts以及 monorepo 集成测试套件 进行深度扩展。读完本文你将理解 Vetur 如何在单进程 VLSVue Language Server内承载多个子项目、三种候选方案的取舍逻辑以及如何编写一份可运行、可落地的vetur.config.js来支撑 monorepo / 子目录 / 多仓库场景。一、背景为什么 monorepo 需要专门的支持RFC 002rfcs/002-monorepo-support.md提出的核心问题是How to achieve monorepo, sub-folders, multi-repos support?在 monorepo如packages/*多包仓库、子目录嵌套、以及多仓库multi-repos场景下Vetur 面临一个基础困境一个工作区里存在多个彼此独立的 Vue 工程每个工程可能有自己的package.json决定 Vue 2 / Vue 3 版本、自己的tsconfig.json/jsconfig.json决定 TypeScript 语言服务与模板插值分析的作用域、自己的自定义 snippets 目录。而 Vetur 此前默认以一个工作区根目录 一个工程的模型工作这直接对应了社区中大量被反复提出的 issueRFC 中引用了 vuejs/vetur#815、#424、#873、#1360、#2016。RFC 的动机可以概括为四点该功能请求在社区中非常受欢迎This feature request is very popularMonorepo 是前端工程化的发展趋势实现该功能存在多条技术路径需要做系统性的方案对比试图解决那些无法配置non-configurable的用户在现有模型下遇到的困难。需要先明确 RFC 中的几个关键名词这些名词贯穿全文也是理解 Vetur 架构的基础名词含义VeturVS Code 上的 Vue 支持扩展VTIVetur Terminal Interface用于 Vue 文件类型检查、诊断等的 CLI实现见 vti/src/cli.tsVLSVue Language Server一切能力的核心基于 LSP 协议LSP / LSP server / LSP clientLanguage Server Protocol 及其服务端本文中指 VLS与客户端TLSTypeScript Language Service不基于 LSP以库调用的方式被 VLS 使用提供 hover、completion 等工程级语言能力TS pluginTypeScript Language Service Plugin用于 rename、refactor 等重构能力二、三种候选实现方案与最终取舍RFC 002 的核心章节Detailed design总结了三种可能的实现路径并逐一分析了优缺点。这一部分是理解 Vetur 最终架构走向的关键。方案 AMultiple LSP client多 LSP 客户端思路通过配置打开多个 LSP 客户端每个客户端对应一个独立进程的 LSP serverVLS一个项目作用域对应一个专属 VLS 服务。优点简单、容易实现每个 server 拥有独立进程性能上互不干扰保持 VLS 本身的简单性。缺点每个第三方客户端都需要自行维护这套多客户端逻辑需要更多计算机资源由于 TS plugin 与 VLS 运行时单元不同VLS 与 TS plugin 之间的通信会存在问题可能需要处理意外情况项目之间的信息无法共享。方案 B在 LSP server 中基于 TLS 支持多项目思路TypeScript 本身支持在一个 server 内承载多个 project即一个 Project 对应一个 TLS以tsconfig.json的位置为划分依据。当时只有 TypeScript/JavaScript 功能需要这项能力因此这是一个局部扩展的方案参考了 angular/vscode-ng-language-service 的实现方式但 angular 方案中项目完全依赖 TS plugin。优点只需简单扩展 TypeScript 支持部分与 VSCode 自身的实现方式一致与 TS plugin 的实现一致VLS 与 TS plugin 通信无障碍。缺点在没有 Vue 的 project 上可能会创建完全多余的 TLS需要引入懒加载逻辑Vue 生态中不支持多个tsconfig.json详见 RFC 001 中的 Why isnt array 讨论略显冗余项目之间的相互影响会拖累性能除非用 nodeworker_threads做进程分离模板插值template interpolation尚未定义 project 边界多文件互相导入时存在潜在风险由于 VLS 中没有显式定义 project全局组件的注册可能不准确。方案 C在 LSP server 内添加多项目支持最终选择思路直接在 VLS 内部实现多项目支持。优点限制最少集成效果最好。缺点开发成本未知RFC 001 的vetur.config.js方案可能可以降低此成本需要更长的开发时间。最终实现结论RFC 002 明确写道We dont want to put the blame on all the clients. so removeMultiple LSP clientoption. Consider package.json and tsconfig.json issues, we will try to useAdd multiple project support in LSP server. Also works withvetur.config.jsconfiguration file.即不把负担转嫁给所有客户端否决方案 A综合考虑package.json与tsconfig.json的问题采用方案 C在 VLS 内支持多项目并配合vetur.config.js配置文件工作。这也是 RFC 001 与 RFC 002 两个 RFC 天然衔接的原因——前者定义了配置文件的格式后者定义了基于该配置的多项目运行时模型。三、vetur.config.jsmonorepo 的配置基石既然最终方案依赖配置文件就必须完整掌握 RFC 001rfcs/001-vetur-config-file.md定义的配置规范。官方 setup 文档将其列为Advanced高级配置docs/guide/setup.mdIf you use a monorepo, VTI orpackage.jsonandtsconfig.json/jsconfig.jsondoes not exist at project root, you can usevetur.config.jsfor advanced settings.3.1 配置文件规格RFC 001 明确规定了配置文件的技术规格所有路径统一使用/分隔符有利于跨平台项目只支持 CommonJS 格式可以直接、快速地使用使用纯 JavaScript同上且可以通过JSDoc获得类型提示必须为 UTF-8 编码。3.2 完整配置示例可直接复制使用RFC 001 与 setup 文档给出的标准示例二者一致此处合并为一个可直接运行的版本// vetur.config.js /** type {import(vls).VeturConfig} */ module.exports { // **optional** default: {} // override vscode settings part // Notice: It only affects the settings used by Vetur. settings: { vetur.useWorkspaceDependencies: true, vetur.experimental.templateInterpolationService: true }, // **optional** default: [{ root: ./ }] // support monorepos projects: [ ./packages/repo2, // shorthand for only root. { // **required** // Where is your project? // It is relative to vetur.config.js. root: ./packages/repo1, // **optional** default: package.json // Where is package.json in the project? // We use it to determine the version of vue. // It is relative to root property. package: ./package.json, // **optional** // Where is TypeScript config file in the project? // It is relative to root property. tsconfig: ./tsconfig.json, // **optional** default: ./.vscode/vetur/snippets // Where is vetur custom snippets folders? snippetFolder: ./.vscode/vetur/snippets, // **optional** default: [] // Register globally Vue component glob. // If you set it, you can get completion by that components. // It is relative to root property. // Notice: It wont actually do it. You need to use require.context or Vue.component globalComponents: [ ./src/components/**/*.vue ] } ] }配置中的每个字段从源码 server/src/config.ts 可以印证其类型定义export interface VeturProjectC BasicComponentInfo | Glob { root: string; package?: string; tsconfig?: string; snippetFolder: string; globalComponents: C[]; } export type VeturConfig PartialPickVeturFullConfig, settings { projects?: Arraystring | (PickVeturProject, root PartialVeturProject); };3.3 各字段的语义详解settings传入 Vue language server 的配置。在 VLS 中它会将VS Code 设置或 VTI 默认配置与vetur.config.js的settings合并。RFC 001 给出了合并逻辑的关键代码片段而在实际源码 server/src/services/vls.ts 中正是这样实现的private getVLSFullConfig(settings: VeturFullConfig[settings], config: any | undefined): VLSFullConfig { const result config ? _.merge(getDefaultVLSConfig(), config) : getDefaultVLSConfig(); Object.keys(settings).forEach(key { _.set(result, key, settings[key]); }); return result; }注意它只影响 Vetur 使用的设置。例如可以设置typescript.preferences.quoteStyle供 Vetur 使用但不会影响 VS Code 原生的 TypeScript 支持。projectsmonorepo 需要一个基准baseline或逻辑。RFC 001 指出可选基准是package.json或tsconfig.json但两者分别用于 node 和 typescript 工程强行用作基准会在不需要的地方浪费资源因此最终选择通过显式配置来定义项目边界。若projects[]中的元素仅为字符串它是只定义 root时的简写形式若projects未定义默认值为[{ root: ./ }]与旧行为保持一致。projects[].root所有运行时依赖如typescript、prettier、prettier/pug的解析都基于该值。Vetur 也会默认在该目录下查找./package.json与./tsconfig.json/jsconfig.json。projects[].package用于获取项目名称或依赖信息但目前只用于判定 Vue 版本Vue 2 / Vue 3 的差异化处理不排除未来更多用途。projects[].tsconfigTypeScript 项目配置是帮助 Vetur 支持 JavaScript 和 TypeScript 的关键也用于支持模板插值template interpolation。RFC 001 专门解释了为什么 tsconfig 不支持数组Why isnt array?TypeScript 本身允许多个离散的tsconfig但 Vue 生态几乎完全不支持——例如常用 webpack 编译 Vue 项目时vue-loader调用ts-loader而ts-loader只支持单个tsconfig.json。因此 Vetur 同样不支持数组以降低开发与维护成本。注意jsconfig.json同样被支持源码 server/src/config.ts 会优先选择路径深度更深的那个配置文件。projects[].snippetFolderVetur 自定义 snippets 文件夹路径默认./.vscode/vetur/snippets。projects[].globalComponentsVetur 有诸如模板插值template interpolation的强力功能但它只在组件内部注册组件时才生效例如import Comp from /components/Comp.vue export default { components: { Comp } }配置了globalComponents后VLS 启动时会解析匹配该 glob 的 Vue 组件文件从而让这些组件在项目任意位置获得模板插值支持。该属性在数组中允许两种值Glob字符串Vetur 以projects[].root为基准调用 glob 库加载组件并以path.basename(fileName, path.extname(fileName))作为组件名对象{ name: string, path: string }Vetur 直接使用该数据是最灵活的方式若为相对路径则基于projects[].root解析。官方文档特别提醒配置它并不会真正注册组件你仍需要在项目中通过require.context或Vue.component完成实际注册。四、源码级验证VLS 如何承载多项目RFC 002 的最终实现在代码中得到了完整落地。以 server/src/services/vls.ts 为主线可以还原 VLS 的多项目运行时模型。4.1 配置文件的查找与热更新addWorkspaceserver/src/services/vls.ts在初始化时依次查找vetur.config.js与vetur.config.cjs后者是 CommonJS 的显式扩展名并通过findConfigFile基于 TypeScript 的ts.findConfigFile实现见 server/src/utils/workspace.ts从工作区根目录向上查找。找到后用requireUncached加载确保每次读取都是最新内容let veturConfigPath findConfigFile(workspace.fsPath, vetur.config.js); if (!veturConfigPath) { veturConfigPath findConfigFile(workspace.fsPath, vetur.config.cjs); }同时VLS 监听文件变化事件setupFileChangeListenersvls.ts当vetur.config.js本身被修改时会自动删除并重建对应 workspace并 dispose 相关 project实现配置热更新无需重启编辑器。4.2 从配置到 ProjectConfig 的归一化getAllProjectConfigsvls.ts把每个 workspace 的veturConfig.projects展平为ProjectConfig[]并按照 root 路径深度降序排序——这保证了嵌套的父子项目在后续匹配时更内层的项目路径更深优先命中。而getProjectConfigvls.ts正是通过docFsPath.startsWith(projectConfig.rootFsPath)来把任意打开的文档归入正确的项目const projectConfig projectConfigs.find( projectConfig docFsPath.startsWith(projectConfig.rootFsPath) [/, \\].includes(docFsPath.substring(projectConfig.rootFsPath.length, projectConfig.rootFsPath.length 1)) );4.3 每个项目独立的运行时环境getProjectServicevls.ts按rootFsPath缓存并加载项目每个项目拥有独立的EnvironmentService含tsconfigPath、packagePath、snippetFolder、globalComponents、独立的DependencyService依赖解析并通过正在加载中等待 完成后复用的机制避免重复初始化loadingProjects数组 sleep(500)轮询。这也回应了 RFC 002 中项目之间信息不共享 / 相互影响的顾虑——VLS 为每个项目隔离了运行时环境。4.4 globalComponents 的加载与使用getVeturFullConfigserver/src/config.ts在解析配置时即完成 glob 匹配globalComponents: flatten( project.globalComponents?.map(comp { if (typeof comp string) { return fg.sync(comp, { cwd: projectRoot, absolute: true, suppressErrors: true }).map(fileName ({ name: path.basename(fileName, path.extname(fileName)), path: normalizeFileNameToFsPath(fileName) })); } return comp; }) ?? [] )随后在 server/src/modes/script/globalComponents.ts 中getGlobalComponents通过 TypeScript 的 LanguageService 读取这些组件的默认导出getDefaultExportNode配合 TypeChecker 生成组件文档并按tagCasing默认 kebab生成标签名最终交给模板标签提供器componentInfoTagProvider.ts供模板补全与诊断使用。这与 RFC 001 描述的能力完全吻合。4.5 缺失配置时的友好提示warnProjectIfNeedvls.ts会在项目缺少tsconfig.json/jsconfig.json、package.json或它们不在项目根目录时向用户弹出警告/错误并提供Learn More链接。当检测到 Vue 3 项目时还会提示 Volar 是 VS Code 中新的推荐扩展。这与 RFC 002 Adoption strategy中Try to provide humane tips提供人性化提示的规划一致。五、实战示例仓库内置的 monorepo 测试夹具仓库中 test/monorepo/ 目录就是一套可复现的 monorepo 集成测试。其夹具配置文件 test/monorepo/fixture/vetur.config.js 是官方推荐写法的实际落地module.exports { settings: { vetur.validation.templateProps: true }, projects: [ ./packages/vue2, { root: ./packages/vue3, tsconfig: ./src/tsconfig.json, globalComponents: [./src/components/**/*.vue] } ] };5.1 一个仓库、两种 Vue 版本./packages/vue2使用字符串简写其 package.json 声明vue: ^2.6.11对应 Vue 2 项目./packages/vue3使用对象完整写法tsconfig指向 src/tsconfig.json配置了/*路径别名与resolveJsonModulepackage.json声明vue: ^3.0.0对应 Vue 3 项目。Vetur 通过每个项目自己的package.json判定 Vue 版本projects[].package字段的用途从而在同一个语言服务器里同时为 Vue 2 与 Vue 3 子工程提供正确的能力。5.2 测试用例验证的能力测试用例直接验证了 RFC 002 要达成的多项目能力completion/alias.test.ts在packages/vue2/completion/Alias.vue中输入import AppSpinner from /时能基于 jsconfig.json 中的paths: { /*: [components/*] }别名补全AppSpinner—— 验证了子项目路径别名解析completion/vue3.test.ts在 Vue 3 的App.vue中能补全setup等 Composition API 选项 —— 验证了每个子项目按自身 Vue 版本提供能力diagnostics/basic.tsAppButton.vue中通过/data/test.json导入 JSON 无诊断错误 —— 验证了resolveJsonModule与别名配置生效diagnostics/globalComponent.test.tsApp.vue模板中使用app-button时能报出app-button misses props: text的 props 缺失诊断 —— 验证了globalComponents的 glob 注册确实让全局组件进入模板诊断diagnostics/eslint.test.ts对 Vue 2 子项目中的 ESLint.vue 报出vue/require-v-for-key、vue/no-unused-vars、vue/no-multiple-template-root等 eslint-plugin-vue 诊断 —— 验证了每个项目独立加载其 ESLint 校验环境。六、与 VTI命令行诊断的配合monorepo 支持不仅面向 VS Code也面向 VTI。RFC 001 说明 VTI 使用配置的方式为vti action vti -c vetur.config.js action vti --config vetur.config.js action不带-c/--config时从process.cwd()起向上查找vetur.config.js显式传入路径时使用指定配置文件。VTI 的 CLI 入口vti/src/cli.ts定义了diagnostics [workspace] [paths...]命令可选-l, --log-level可选值ERROR | WARN | INFO | HINT默认WARN。其实现vti/src/commands/diagnostics.ts会启动一个内存中的 VLS 实例通过TestStream双工流建立客户端/服务端连接按**/*.vue排除node_modules收集文件并逐个下发$/getDiagnostics请求最终以退出码 0/1 报告结果。VTI 的默认配置见 vti/src/initParams.ts例如默认vetur.experimental.templateInterpolationService: true、vetur.validation.templateProps: true。这意味着 monorepo 的vetur.config.js在 CI 场景下同样生效——你可以用同一份配置驱动本地编辑器和命令行诊断。七、实践建议与注意事项结合 RFC 的Adoption strategy与仓库源码给出以下落地建议把vetur.config.js提交进 gitVS Code 的 workspace 配置归 VS Code 所有、且通常不进 git而vetur.config.js作为团队共享配置RFC 001 的动机之一应随仓库版本管理保证团队一致性。字符串简写 vs 对象完整写法子项目只需定义 root 时用字符串需要指定tsconfig、globalComponents、snippetFolder时用对象。为每个子项目提供自己的package.json与tsconfig.json/jsconfig.json前者用于 Vue 版本判定后者是 TS/JS 支持与模板插值的基石。缺失时 VLS 会弹出提示对应 FAQ 文档 docs/guide/FAQ.md 中的相关条目。globalComponents只负责让 Vetur 认识全局组件实际注册仍需项目内require.context或Vue.component。Yarn PnP 注意点见 docs/guide/setup.md不要在多根/多项目中混用普通项目与 PnP 项目Prettier 不支持 Yarn PnP无法自动加载插件。如需使用 yarn editor SDK 的 tsserver可通过settings.typescript.tsdk指向.yarn/sdks/typescript/bin。配置热更新修改vetur.config.js后无需重启编辑器VLS 会监听文件变化并自动重建相关项目见 vls.ts。八、RFC 遗留问题与思考RFC 002 在 Unresolved questions 中留下三个开放问题它们也解释了为什么最终选择配置文件 VLS 内多项目的组合是否存在需要多个tsconfig.json的 Vue 项目Vue 生态工具链如ts-loader只支持单 tsconfig见 RFC 001 的说明项目基准应该基于什么tsconfig.json、package.json还是 RFC 中定义的配置其他框架React、Angular是否存在多tsconfig.json场景从最终实现看Vetur 给出的答案是通过vetur.config.js显式定义项目边界而不是自动推断每个项目允许一个tsconfig/package在 VLS 内按路径前缀匹配文档归属——这套设计平衡了 Vue 生态的实际约束与多项目场景的需求也是 monorepo 支持能够以无破坏性变更RFC 002 的 Adoption strategy 明确 No breaking change方式落地的关键。赞分享开发工具IDE前端【免费下载链接】veturVue tooling for VS Code.项目地址https://gitcode.com/gh_mirrors/ve/vetur点击查看免费下载相关推荐Vetur 配置指南vetur.config.js 完整参考与实践详解Vetur 配置指南 vetur.config.js 完整参考与实践详解 vetur.config.js 是 Vetur 与 VTI 共享的配置文件用于在多开发工具IDE前端Vetur 配置文件 vetur.config.js 完全指南从单项目到 Monorepo 的配置与源码解析Vetur 配置文件 vetur.config.js 完全指南从单项目到 Monorepo 的配置与源码解析 vetur.config.js 是 Vetur开发工具IDE前端Vetur 快速上手与项目配置完全指南从 Vue CLI 到 Monorepo 的 vetur.config.js 实战Vetur 快速上手与项目配置完全指南从 Vue CLI 到 Monorepo 的 vetur.config.js 实战 导读 本文是 VeturVS Co开发工具IDE前端上一篇Robot Framework reStructuredText 测试数据完全指南从 __init__.rst 套件初始化文件到解析原理下一篇革新性安卓应用运行方案在Windows系统实现无缝体验的高效工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?