发布时间:2026/9/6 20:13:14
React Router 架构决策 ADR-0008:TypeScript 模板为何只转换 app 代码为 JavaScript React Router 架构决策 ADR-0008TypeScript 模板为何只转换 app 代码为 JavaScript【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router本篇技术文章围绕 React Router 仓库中一份已采纳的架构决策记录ADR展开Only support JS conversion for app code。该决策解释了为什么在脚手架工具中为 JavaScript 用户动态降级 TypeScript 模板时只转换应用目录app/内的代码而不转换构建脚本与配置文件并剖析了 ESM/CJS 双路线各自踩中的技术深坑。读完本文你能理解模板即单一可信源的脚手架设计思想看懂 Node.js 模块系统在真实工程中的约束并能对照 create-react-router 的当前源码验证这套决策最终是如何被模板化机制承接的。背景TypeScript 默认、JavaScript 可选的选择困境React Router及其前身 Remix的项目脚手架默认使用 TypeScript但始终有一批用户更倾向纯 JavaScript。决策文档日期 2023-01-20状态 accepted记录了当时npx create-remix的交互场景——CLI 会直接询问用户选择 TS 还是 JS❯ npx create-remixlatest ? Where would you like to create your app? ./my-remix-app ? What type of app do you want to create? Just the basics ? Where do you want to deploy? Choose Remix App Server if youre unsure; its easy to change deployment targets. Remix App Server ? TypeScript or JavaScript? (Use arrow keys) ❯ TypeScript JavaScript这个语言选择看似只是一个选项背后却要维护两套完整的项目模板由此引出了模板维护成本问题。模板方案的演进从双份模板到仅维护 TS 变体文档还原了一条清晰的演进链最初为每个模板分别维护 TypeScript 和 JavaScript 两个变体。它能用但巨大的模板内容被完整复制了两份两套变体极难维护——任何一处功能更新都要同步改两次。改进团队决定只维护每个模板的 TS 变体。当用户选择 JavaScript 时CLI 会先把 TS 模板拷贝下来然后动态地把所有 TypeScript 相关代码转换成 JavaScript 等价物。这个方案的边界划分很关键转换app/目录即 Remix/React Router 应用代码内的文件是可靠的因为这部分代码由 Vite 统一构建构建管线对 TS/JS 的处理是透明的而转换app/目录之外的 TS 相关代码则棘手且易错。app 代码内可靠、app 代码外易错这个判断是整个 ADR 的支点下面逐一拆解易错具体难在哪里。为什么 app 目录之外的转换如此困难app/之外通常是什么package.json里的 scripts、server.ts/seed.ts这类 Node 直接执行的脚本、vite.config.ts、tsconfig.json、种子数据工具等。这些文件绕过了构建管线由 Node 直接加载于是 Node 的模块解析规则成为硬约束。问题 1.ts文件的陈旧引用Stale references文档给出的实例是 Indie 与 Blues 两个官方栈模板当用户选择JavaScript后模板里的构建/启动脚本仍然引用着server.ts和seed.ts脚本依赖也随之引用了ts-node这类 TS 专用运行工具——结果就是脚本直接跑不起来。这个问题揭示了一个通用规律模板转换不仅是文件内容翻译还必须同时改写所有指向这些文件的引用点package.jsonscripts、import 语句、工具链依赖。引用点分散在 JSON、shell 命令、代码三种介质中静态改写很容易漏。问题 2.aESM 路线.mjsapp/之外转 JS 时最直觉的做法是转成 ESM 风格的.mjs因为 Remix 应用代码本身就用 ESM 语法。但 ESM 在 Node 中有两种启用方式文档逐一分析了两者的死结方式 a在package.json中设置type: module—— 文档指出这会立即破坏构建因为该设置作用于整个包目录覆盖到 app 代码而不只是 app 之外的脚本与 Remix 的构建配置产生冲突。方式 b使用.mjs扩展名—— 看起来更有希望但.mjs文件的 import 说明符必须带完整文件扩展名。而原 TS 模板中的相对导入普遍不带扩展名于是出现这样的困境// ./script.mjs (converted from ./script.js) import myHelper from ./my-helper; // Should this be converted to ./my-helper.mjs? // Probably, but can we be sure? myHelper();把无扩展名相对导入可靠地补上正确扩展名是不可治理untractable的——因为目标文件未必都是.js/.mjs转换器无法保证每一次补全都正确。文档的结论是或许存在某种解法但复杂度代价过高。问题 2.bCJS 路线如果不用.mjsNode 会把 app 目录外的脚本默认当作 CommonJS 处理。而 CJS 不支持 ESM 风格的import/export那就需要把所有import/export改写成require/module.exports。文档补充了一条容易被忽视的约束转换后的代码是要给其他开发者阅读和编辑的因此不能像构建产物那样生成一堆 import/export 的样板适配代码。import/export 的转换或许可行但同样复杂度代价很高。三条路线双模板、ESM、CJS全部被排除后决策的收敛方向就清晰了。决策JS 转换只覆盖 app 代码Only support JS conversion for app code, not for scripts or code outside of the Remix app directory.只为 app 代码提供 JS 转换不为 app 目录之外的脚本和代码提供转换。这个决策的实质是划定转换能力的可信边界构建管线管辖范围内app/的 TS→JS 转换交给工具自动化构建管线管辖范围外Node 直接执行的脚本与配置保持 TypeScript 原样把语言选择的责任上移给用户——通过选择模板来表达。用户的三个选项与手动清理路径根据决策用户面对想用 JavaScript这一诉求时有三种选择使用 TypeScript 模板使用 TypeScript 模板但app 目录被自动转换为 JSapp/外仍是 TS 文件与 TS 工具链;使用专门的 JavaScript 模板dedicated Javascript template。如果选项 2 残留的 TS 让用户无法接受、又找不到合适的选项 3 模板文档给出了完整的手动清理清单删除tsconfig.json或替换为等价的jsconfig.json把 TS 专用工具替换为 JS 对应物例如ts-node-node把剩余的.ts文件改为.mjs并同步更新所有引用点——包括 import 与package.jsonscripts 中的文件名引用。注意这份清单恰好对应了前面分析的三类坑配置文件、工具链依赖、陈旧引用——手动操作时照单排查即可。源码印证模板机制在 create-react-router 中的落地ADR 提出时 CLI 还内置了TS 或 JS的交互式提问到了当前仓库的 create-react-router语言选择已经彻底模板化——在packages/create-react-router包内检索不到任何 TypeScript/JavaScript 的交互提问逻辑语言差异完全由--template指定的模板承载这正是 ADR 选项 3专门模板成为主流路径后的自然演进。当前 CLI 的模板机制可以从源码中完整验证模板来源的五种合法形式copyTemplate 的入口注释明确列出——本地文件或目录、GitHubowner/repo简写、owner/repo/directory简写、完整 GitHub 仓库 URL、任意 tarball URL非法模板会抛出 CopyTemplateError。GitHub 简写解析copyTemplateFromGithubRepoShorthand 将owner/name[/path]拆段后经 codeload 下载仓库 tarball 并解压getRepoInfo 负责从tree分支 URL 中提取分支与子目录。子目录过滤tarball 解压时通过 tar 的map钩子copy-template.ts按前缀过滤只保留指定子目录——这就是能选owner/repo/templates/basic这类仓库内某目录作为模板的实现基础。默认模板copyTemplateToTempDirStep 中未传--template时回退到 remix-run 官方 templates 仓库的 default 模板printHelp 的--help输出把上述五种模板形式与示例逐条列出私有仓库还支持--token传访问令牌。CLI 流程index.ts 中整个创建流程是显式步骤数组introStep→projectNameStep→copyTemplateToTempDirStep→copyTempDirToAppDirStep→ 依赖安装与 git 初始化等模板拷贝先落到临时目录再复制到目标目录并在 copyTempDirToAppDirStep 中做文件冲突检测--overwrite可强制覆盖。这条源码证据链说明ADR 时代的CLI 动态转换与今天的模板选择并不矛盾——--template机制把选语言变成了选模板把转换的责任从 CLI 的脆弱字符串改写前移到模板作者的一次性维护从工程上规避了问题 1、2.a、2.b 的全部风险。要点回顾维护 TS/JS 双份模板的重复成本催生了仅维护 TS 模板 动态转换的中间方案app/之外的转换在 ESM.mjs扩展名强制、type: module污染全包与 CJSimport/export 全量改写且产物需可读两条路上都代价过高加上package.jsonscripts 中的.ts陈旧引用问题最终决策为只转换 app 代码用户因此拥有 TS 模板 / 半转换模板 / 纯 JS 模板三条路径且文档提供了tsconfig.json→jsconfig.json、ts-node→node、.ts→.mjs三步手动清理清单当前 create-react-router 源码显示该决策的落地形态语言选择交由--template模板机制承担CLI 本身不再做任何交互式语言提问或代码级 TS→JS 转换。这份 ADR 的价值在于它示范了一种务实的架构决策方法先穷举候选路线并给出每条路线的失败证据带代码示例再把能力边界收缩到可靠区间内剩下的复杂性交还给用户可控的模板层。对于任何需要为多语言用户提供脚手架的项目这都是一份可直接借鉴的决策样本。【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/9/6 20:13:14

通达信九转趋势主图指标:源码解析与实战应用

简介:这是一份通达信九转趋势主图指标源码文档,适合使用通达信进行技术分析、想自制主图指标的交易者学习参考。资源仅包含一个doc文件,压缩包74KB,文档内给出了完整指标公式源码,覆盖九转序列自动判断、趋势支撑与压力…

2026/9/6 20:13:14

同步发电机并网建模与动态仿真:从并网条件到参数整定全解析

简介:围绕发电机并网模型的建立与并网过程仿真,这份PDF文档面向电力系统自动化、电气工程等专业的学生与工程技术人员,适用于课程设计、毕业设计、并网操作研究,也可供互联网能源电力类项目参考。文档从并网条件入手,分…

2026/9/6 21:08:18

A3报告培训课件设计:从问题解决逻辑到实操落地全指南

简介:这份PPT课件专注于A3报告制作培训,面向企业班组长、精益改善专员、质量管理人员及希望提升问题解决能力的职场人士。课件系统梳理了A3报告的定义与意义,强调以A3纸为载体实现简明沟通和深度分析,并围绕PDCA循环展开解决问题八…

2026/9/6 21:08:18

基于战略的绩效管理体系设计方案:从战略解码到落地闭环

简介:这份146页的全面绩效管理体系设计方案,以战略解码为主线,面向企业中高层管理者、HR及战略规划人员,重点解决绩效管理与战略重点脱节、指标分解与职责角色不匹配等常见难题。方案围绕战略篇、实施篇、机制篇、工具篇、名企篇展…

2026/9/6 21:08:18

快速跑起来 Qwerty Learner 打字练习完整指南

快速跑起来 Qwerty Learner 打字练习完整指南 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers 项目地址: https://gitcode.com/GitHub_Tre…

2026/9/6 21:08:18

OpenClaw智能体框架:从安装部署到技能编排的实践指南

简介:OpenClaw是奥地利开发者发布的开源个人AI Agent框架,在2026年初凭借“本地优先、自主闭环执行”的特性迅速走红。这份129页的PDF指南正适合想系统学习OpenClaw的开发者、技术爱好者与AI产品从业者,帮助读者理清从入门到精通的完整路径。…

2026/9/6 21:08:18

大型企业全面绩效管理体系设计方案:从战略解码到落地实战

简介:这是一份146页的某大型企业全面绩效管理体系设计方案PPT,聚焦基于战略的绩效管理落地路径,适合企业高管、HR团队及绩效管理咨询人员参考,用于解决战略解码不清晰、考核指标与经营重点脱节等问题。整套资料共1个pptx文件&…

2026/9/6 21:03:17

Vector 日志管道 Kubernetes 部署与配置实战指南

Vector 日志管道 Kubernetes 部署与配置实战指南 【免费下载链接】vector A high-performance observability data pipeline. 项目地址: https://gitcode.com/GitHub_Trending/vect/vector 凌晨三点,一条线上故障把你叫起来,你 SSH 到十几台机器逐…

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/6 0:06:59

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/6 0:06:59

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/6 0:06:59

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/6 11:40:10

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/6 19:33:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/6 10:19:40

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…