
create-quasar 脚手架内核全解析目录布局、模板渲染引擎与测试体系【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar导读本文以create-quasar/AGENTS.md为骨架深入剖析 Quasar 仓库中create-quasar包的内部结构从 CLI 入口、模板渲染引擎、预设组合机制到单元测试与端到端测试的分层策略以及开发中必须避开的几个关键陷阱。读完本文你将掌握 create-quasar 脚手架的工作原理包括_前缀文件名剥离、Eta 风格模板标签语法、本地 registry 测试机制并能在本地快速定位模板缺陷、用环境变量裁剪 E2E 矩阵来验证自己的改动。create-quasar 在 Quasar 生态中的定位create-quasar是 Quasar 仓库中负责空项目脚手架的独立子包其package.json将bin指向 bin/create-quasar.js提供create-quasar命令用于生成两类产物App基于 Quasar CLI Vite 的完整应用模板位于 create-quasar/templates/appApp ExtensionAE可分发、可安装的 Quasar 应用扩展模板位于 create-quasar/templates/ae。从 create-quasar/package.json 的依赖可以看出它的技术栈交互提示基于clack/prompts文件操作基于fs-extra子进程执行基于cross-spawn并复用了同仓库quasar/artBanner 输出与quasar/update-notifier版本更新提示运行时要求 Node.js 20。该包与app-vite构建/开发服务器、cli全局 Quasar 命令解耦但共享同一套 E2E 基础设施这一点在测试体系一节会详细展开。一、目录布局三层清晰边界create-quasar/AGENTS.md首先点明了包的目录划分原则共三层路径职责bin/create-quasar.jsCLI 入口参数解析与校验lib/脚手架业务逻辑其中lib/template.js是模板渲染引擎templates/{app,ae}/按预设preset组织的模板源文件1.bin/create-quasar.js参数解析与校验入口脚本的第一段逻辑处理三类轻量出口--version/-v直接打印 create-quasar/package.json 的version字段通过 create-quasar/lib/cli-pkg.js 导入后退出--no-color或检测到 CI 环境ci-info设置FORCE_COLOR0禁用彩色输出--help/-h打印完整的用法与选项说明。当用户直接执行二进制而非经由pnpm create quasar等包管理器包装命令时还会触发quasar/update-notifier的版本更新提示随后打印 CLI Banner。参数模型脚本基于 Node 内置的node:utilparseArgs解析选项核心参数如下与帮助文本一致--template, -t项目类型app或ae--overwrite, -o目标目录已存在且非空时直接覆盖--preset, -p可多次传入的预设项app 支持typescript / sass / oxlint / eslint / fbr / i18n / piniaae 支持typescript / oxlint / prompts / install / uninstall--namepackage.json中的包名必须是合法 npm 包名--author作者名未指定时从git config user.name/user.email读取见 create-quasar/lib/utils.js 的getGitUser--install, -i经包管理器调用时是布尔开关直接调用时则指定包管理器pnpm / yarn / npm / bun--product仅 app 模板可用移动端构建时要求以字母开头--defaults, -d其余未指定项全部使用默认值--no-git跳过 Git 仓库初始化--no-color、--help。该校验逻辑还包含若干组合约束在 create-quasar/bin/create-quasar.js 中oxlint与eslint两个预设不能同时出现二者都会被映射为内部linting预设并分别记录linter oxlint | eslint--defaults模式下app 的默认预设为[sass, oxlint]、默认安装器为pnpmae 的默认预设为[prompts, install, uninstall, oxlint]且ae 只允许使用 pnpm安装其余包管理器会直接报错退出位置参数项目目录名只允许出现一个多余的会触发参数错误。running-pm.js提供包管理器探测能力通过解析process.env.npm_config_user_agent的首段来判定当前由哪个包管理器包装调用参见 create-quasar/lib/running-pm.js这决定了交互式流程中packageManagerList的取值与--install参数的解析形态。2.lib/脚手架业务逻辑lib目录下的模块各司其职共同构成交互 → 渲染 → 安装 → 收尾的流水线create-quasar/lib/template.js模板编译与渲染引擎详见下一节create-quasar/lib/utils.js渲染、目录创建、依赖安装、lint、Git 初始化的通用工具create-quasar/lib/create-project-folder.js整体编排流程create-quasar/lib/ensure-outside-project.js运行时前置检查create-quasar/lib/running-pm.js包管理器探测create-quasar/lib/cli-pkg.js包的元信息导出。渲染管线utils.renderTemplate(relativePath, scope)是整个脚手架的核心入口。它用tinyglobby扫描模板目录下所有文件然后逐文件处理_前缀剥离路径每一段若以_开头渲染时去掉该下划线这正是 AGENTS.md 中_package.json → package.json规则的实现位置create-quasar/lib/utils.js按扩展名决定处理方式仅对、.json、.js、.cjs、.ts、.vue、.md、.html、.sass等可模板化扩展名执行模板渲染其余文件图片、字体等直接copySync拷贝JSON 美化渲染结果若是合法 JSON会尝试JSON.stringify(..., null, 2)重新格式化解析失败例如模板渲染后仍含注释的 JSON则原样保留避免破坏文件内容。交互编排createProjectFolder见 create-quasar/lib/create-project-folder.js依次询问项目类型 → 目录名 → 包名/产品名由各模板的create-quasar-script.js注入→ 是否安装依赖随后执行依赖安装、lint、Git 初始化最后在终端输出cd、install、run lint、quasar dev等后续命令清单。Git 初始化细节initializeGit会先探测系统是否安装了 Git、目标目录的父级是否已是 Git 仓库是则跳过当用户没有配置init.defaultBranch时会显式使用-c init.defaultBranchmain固定主分支名若用户开启了 GPG 签名commit.gpgsigntrue还会提示等待 GPG 签名以免用户误以为进程卡死create-quasar/lib/utils.js。运行时前置检查ensure-outside-project.js定义了isInsideQuasarProject()——从当前工作目录逐级向上查找quasar.config.js / .mjs / .ts / .cjs以及历史遗留的quasar.conf.js只要发现任意一个就判定在 Quasar 项目内create-quasar/lib/ensure-outside-project.js。CLI 入口在解析参数前就会执行该检查命中则打印This command must NOT be executed inside of a Quasar project folder.并以退出码 1 终止。3.templates/{app,ae}/预设组合与渲染顺序模板目录按「语言js/ts× 预设BASE 增量预设」组织。以 app 模板create-quasar/templates/app/vite-3为例js/BASE与ts/BASE无论何种预设组合都会渲染的公共骨架.vscode、public/、src/、_package.json、quasar.config.js|ts、postcss.config.js等增量预设目录cssSass 变量与样式入口、eslint、oxlint、filenameBasedRouting基于文件名的路由、manualRouting手动路由、i18n、pinia、sass顶层 create-quasar/templates/app/create-quasar-script.js 定义 app 特有的交互问题包名、产品名并把runDevCmd设为quasar dev。ae 模板create-quasar/templates/ae结构类似但 BASE 中包含ae/src/runtime/运行时组件与 boot 注册、playground/配套演示应用增量预设为prompts、install、uninstall、oxlint四类脚本目录。ae 的create-quasar-script.js还会做包名解析去掉quasar-app-extension-前缀把scope.aeShortName与scope.aeFullNamequasar-app-extension-name注入渲染作用域。每个模板根目录的create-quasar-script.js被 create-quasar/lib/create-project-folder.js 动态import从而让交互问题定义与模板布局保持在一起这是从源码结构可以看出的清晰分层设计。二、模板渲染引擎lib/template.js的 Eta 风格实现AGENTS.md 明确说明lib/template.js是模板引擎且深受 Eta v4.5.1 启发。阅读 create-quasar/lib/template.js 可以看到一个约 300 行的自包含实现核心要点如下。1. 标签语法与三种块类型默认解析选项create-quasar/lib/template.js{ varName: scope, // 渲染函数入参名 exec: , // 执行块前缀无前缀 interpolate: , // 插值块前缀 raw: ~, // 原始输出块前缀 tagStart: %, tagEnd: % }对应三种模板块% ... %执行JavaScript 语句不输出% expr %插值把表达式结果拼入输出%~ expr %原始输出与插值的主要区别在于表达式会被整体包裹为字符串字面量parseRawContent对$、、\、做转义后以... 形式拼接适用于输出原始内容。2. 解析器细节getAST用正则扫描把模板拆成字符串与块的 AST 序列其边界处理相当稳健字符串感知闭合标签搜索会跳过单引号、双引号、模板字面量反引号与/* */注释内的内容避免把%块内部的引号误判为标签结束create-quasar/lib/template.js空白修剪%后跟-表示修剪紧随其后的换行nl模式跟_表示全量trimStart/trimEndslurp模式从而实现模板源码的紧凑书写而不污染输出create-quasar/lib/template.js错误定位throwParseError会计算出错的行列号并打印出错行与^指示符方便定位模板语法问题create-quasar/lib/template.js。3. 编译与渲染compileTemplateToFn把 AST 编译为形如return __qstr__ ...的函数体再经new Function(scope, body)实例化渲染函数renderTemplate(str, scope, rawOpts)是外部统一入口支持rawOpts.varName false时把scope的键解构为局部变量注入函数头减少模板中的scope.前缀噪音create-quasar/lib/template.js。正是这个引擎支撑了所有模板文件的% %语法也让模板错误优先在单元测试中暴露成为可能——见下一节的测试策略。三、测试体系单元测试兜底、E2E 矩阵把关create-quasar/package.json定义了四档测试命令pnpm test 单元 两个 E2E 套件test:unit: vitest run, test:e2e: pnpm test:e2e:app pnpm test:e2e:ae, test:e2e:app: vitest run --config ./vitest-e2e.config.js test/e2e/app, test:e2e:ae: vitest run --config ./vitest-e2e.config.js test/e2e/ae1. 单元测试pnpm test:unit快速反馈层按 AGENTS.md 的描述单元测试会把每一种预设组合都渲染到临时目录OS 临时目录因此模板语法错误、_前缀剥离异常、JSON 格式化失败等问题会首先在这一层暴露。对应测试文件位于 create-quasar/test/unittemplate.test.js模板引擎自身的标签解析、修剪与渲染行为scaffold-app.test.js/scaffold-ae.test.js整包渲染流程的黄金文件对比cli.test.jsCLI 参数解析与校验含oxlint eslint互斥等约束ensure-outside-project.test.js项目内检测逻辑running-pm.test.js包管理器探测cli-package-contract.test.js包的 bin/files 契约utils.test.js通用工具函数。任何改动 create-quasar 的提交都应当先跑这一层——它速度最快且覆盖面足以捕捉绝大多数模板回归。2. E2E 测试真实依赖、真实构建E2E 套件采用真实世界验证路径每个预设组合都执行真实脚手架 → 安装真实依赖 → lint → build → 启动 dev server而非停留在文件生成了没。AGENTS.md 强调E2E installs the monorepos own packages, never published ones; third-party deps still resolve from npm.也就是说E2E 安装的是当前仓库未发布的 monorepo 内部包如ui第三方依赖仍从 npm 解析。这是通过 create-quasar/test/e2e/local-registry.js 实现的 registry 代理/拦截机制完成的该 harness 同时被cli与app-vite的 E2E 套件复用因此它的导出接口必须保持稳定这也是 AGENTS.md 特意提醒keep its exports stable的原因。3. 用环境变量裁剪矩阵完整的组合矩阵app 约 48 个组合install × script × engine × linter × fbr × allPresets在本地跑完耗时过长因此测试读取环境变量来挑选单一组合参见 create-quasar/test/e2e/app.test.js 与 create-quasar/test/e2e/ae.test.js套件环境变量默认值作用appE2E_INSTALLpnpm安装器pnpm/npm/yarnappE2E_SCRIPTjs脚本语言js/tsappE2E_LINTERoxlint代码检查器oxlint/eslintappE2E_FBRfalse是否启用基于文件名的路由appE2E_ALL_PRESETSfalse是否一次性启用全部预设aeE2E_SCRIPTjs脚本语言js/tsaeE2E_LINTtrue是否启用 lint 组合AGENTS.md 给出的典型用法是只跑与你改动相关的一个组合例如E2E_SCRIPTts E2E_LINTEReslint pnpm test:e2e:app完整矩阵则由 CI 执行。4. CI 完整矩阵.github/workflows/create-quasar-tests.yml.github/workflows/create-quasar-tests.yml 是 E2E 矩阵的编排者值得注意的设计点路径过滤 动态裁剪仅当改动涉及create-quasar/**、本 workflow、根package.json/pnpm-lock.yaml/pnpm-workspace.yaml时才触发unit-testsjob 会通过 GitHub API 获取变更文件清单只有确认脚手架本身可能被改动时才放行昂贵的 E2E 矩阵.github/workflows/create-quasar-tests.ymlUI 构建缓存E2E 需要把 monorepo 的ui包发布到本地 registry因此单独一个build-uijob 构建ui/dist并上传 artifact供后续矩阵 job 复用采用精确输入哈希作为缓存 key绝不使用过期产物app 矩阵 48 个 jobinstall(pnpm/npm/yarn) × script(js/ts) × engine(vite-3) × linter(oxlint/eslint) × fbr × allPresetsmax-parallel: 12避免同时拉取 action 触发 429ae 矩阵 4 个 jobscript(js/ts) × lint(true/false)并发控制按 ref 分组、可取消进行中的旧运行避免快速推送时任务堆积。四、关键注意事项GotchasAGENTS.md 最后列出的三条陷阱是开发者最容易踩坑的地方逐一结合源码说明。1. 严禁在 Quasar 项目内运行如前所述create-quasar/lib/ensure-outside-project.js 会向上逐级探测quasar.config.*一旦命中CLI 立即报错并以退出码 1 终止create-quasar/bin/create-quasar.js。测试代码也遵循这一约定——单元测试把脚手架输出渲染进 OS 临时目录E2E 同样在隔离目录中执行。2. 依赖安装失败不会让 CLI 失败exit 0installDeps内部调用runCommand基于cross-spawn同步子进程安装失败时只是把scope.install置为false、返回falseCLI 继续走完后续流程并以 0 退出create-quasar/lib/utils.js。此时scope.meta.hasInstalledDeps为false结束提示会额外给出pnpm install与pnpm run lint作为补救命令。对测试的推论既然进程退出码不可靠E2E 断言安装成功就必须直接验证node_modules是否存在而不是依赖退出码。此外installDeps对 pnpm 会注入PNPM_CONFIG_STRICT_DEP_BUILDSfalse环境变量——因为 pnpm 11 对未审批的依赖构建脚本会以错误退出而这并不代表安装真的失败create-quasar/lib/utils.js。3. E2E 失败后的reproduce manually与自动跳过E2E 组合是脚手架 → 安装 → lint → build → dev server 启动的多步流水线。失败时测试会打印一个reproduce manually块包含可用于本地复现的完整命令序列并且一旦某个组合的某一步失败该组合的剩余步骤会自动跳过避免在已知失败的前提下继续执行造成噪音与无谓的耗时。这要求开发者在排查时先复现最小失败步骤再修正模板或测试。五、本地实操建议综合以上机制给出一套贴近仓库内部开发流程的实践清单任何改动先跑快速层cd create-quasar pnpm test:unit模板渲染错误、JSON 格式问题在这一层就能暴露。改动涉及具体预设组合时用环境变量裁剪 E2EE2E_SCRIPTjs E2E_LINTERoxlint E2E_FBRfalse pnpm test:e2e:app按需覆盖 js/ts、oxlint/eslint、fbr 开关等维度不要本地跑全矩阵。排查模板问题直接读引擎与渲染代码语法与渲染规则create-quasar/lib/template.js_前缀剥离与扩展名过滤create-quasar/lib/utils.js的renderTemplate参数校验与预设映射create-quasar/bin/create-quasar.js各预设的增量文件create-quasar/templates/app/vite-3/*/与create-quasar/templates/ae/*/。涉及 E2E 基础设施改动时务必保持create-quasar/test/e2e/local-registry.js的导出接口稳定因为它同时服务于cli与app-vite两套 E2E 套件。验证 CLI 运行行为时在任意非 Quasar 项目目录如临时目录中执行node create-quasar/bin/create-quasar.js my-app --defaults体验全自动流程若要验证项目内拒绝执行则在一个含quasar.config.js的目录中运行并观察退出码 1。结语create-quasar虽然只是一个脚手架子包但其内部结构体现了清晰的工程分层入口负责参数契约lib负责渲染与编排templates以BASE 增量预设的方式组合出无限多的项目形态测试侧则用快速单元测试全覆盖 环境变量裁剪的 E2E 单组合验证 CI 全矩阵把关三级策略平衡了反馈速度与覆盖度。理解 AGENTS.md 中的布局、测试与注意事项等于拿到了这棵脚手架代码树的完整地图——无论是排查模板问题、新增预设还是改动 E2E harness都能快速定位到正确的文件与命令。【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考