首页 / 资讯中心 / 文章详情

Farm 实战:Rust Worker 插件动态入口 URL 不一致导致的 E2E 失败排查与修复

Farm 实战:Rust Worker 插件动态入口 URL 不一致导致的 E2E 失败排查与修复 ★ FEATURED ARTICLE
前端构建构建工具开发工具【免费下载链接】farmExtremely fast Vite-compatible web build tool written in Rust项目地址https://gitcode.com/gh_mirrors/fa/farm点击查看免费下载本文围绕 Farm 仓库中 docs/experiences/rust-plugin-worker-e2e-url-mismatch.md 记录的调试经历展开完整还原examples/rust-plugin-worker示例在浏览器端 E2E 失败的现象、排查步骤、根因定位与修复方案。读完本文你将掌握「构建成功但浏览器运行失败」这类隐性缺陷的排查套路理解 Farm Worker 插件动态入口命名与模块图去重的底层机制并学会用单元测试与 E2E 双重手段验证修复。问题背景构建成功浏览器却报错examples/rust-plugin-worker是 Farm 仓库中用于演示 Rust Worker 插件farmfe/plugin-worker的示例工程。它的 E2E 失败有一个非常迷惑的特点Farm 的构建与 dev server 都能正常启动、编译产物完整但页面在浏览器中运行 Worker 用例时整体失败。该失败最初在 Windows 与 macOS 的 CI 上通过pnpm run test-e2e观测到且呈平台相关特征。由于 Worker 动态入口名在多种 Worker 语法引用同一份源文件时可能被选择得不同这类问题往往只在特定平台、特定引用方式下暴露本地 Linux 环境难以复现排查成本较高。典型症状与关键信号E2E runner 的默认冒烟测试由 scripts/test-e2e-worker.mjs 驱动会报告来自浏览器控制台的错误[rust-plugin-worker] rust-plugin-worker › start Browser console error: Worker case failures [Object, Object, Object, Object, Object, Object, Object]这条报错有三个值得注意的信号Farm 构建或 dev server 已成功启动——错误不是编译期问题而是运行期问题失败来自页面自身的console.error(Worker case failures, results)——这是 examples/rust-plugin-worker/src/index.tsx 中runWorkerCases()收尾处主动打出的日志说明至少有一个 Worker 用例在浏览器里抛了异常浏览器日志只显示[Object]——失败用例的名称、错误详情被隐藏必须直接检查页面或产物才能定位。从 E2E 机制看e2e/farm-runner.mjs 的visitPage会监听页面console事件任何msg.type() error的控制台错误都会触发Browser console error: ...并让测试失败。因此页面代码里那行console.error一出现整个用例就被判定为失败。逐步排查清单1. 先审查 Worker 用例源码排查的第一步是回到用例源头。examples/rust-plugin-worker/src/index.tsx 针对同一份vue.worker.ts源文件同时使用了四种不同的引用语法// new URL 绝对路径以 / 开头 new Worker(new URL(/src/worker/vue.worker.ts, import.meta.url)) // new URL 相对路径 new Worker(new URL(./worker/vue.worker.ts, import.meta.url)) // ?worker 查询参数导入 Worker 构造函数 import WorkerCtor from ./worker/vue.worker.ts?worker // ?workerurl 查询参数导入 worker 脚本 URL import workerUrl from ./worker/vue.worker.ts?workerurl关键疑点就在这里如果同一份源文件被多种语法引用理论上应该产生多个公开的 Worker URL但 Farm 是按真实源ModuleId追踪动态入口的因此同一源文件只会保留一个动态入口名。若插件生成的各 wrapper 指向的 URL 不一致就会产生「产物只发出一个、引用却指向多个」的错位。2. 构建示例并对比 wrapper URL 与产物文件执行构建cd examples/rust-plugin-worker npm run build然后检查dist/index.*.js中生成的 wrapper 代码以及dist/目录下实际产出的 Worker 文件。一个典型的坏构建长这样function WorkerWrapper(options) { return new Worker(/vue.63ddc497.worker.js, options); } var vue_worker_ts_default /vue.c1e83ed7.worker.js;而输出目录里只有dist/vue.63ddc497.worker.js对比即可发现?workerurl导出的vue.c1e83ed7.worker.js指向了一个根本未被产出的文件。这就是「构建成功、运行时失败」的直接证据——构建阶段两个 wrapper 都成功生成但运行时只有被模块图选中产出的那一个 URL 是真实存在的。3. 不要轻信 preview 返回的 200排查时最容易踩的坑是Farm preview 服务器对缺失的 Worker URL 可能返回index.html兜底内容因此请求即使返回状态码200拿到的也可能是 HTML 而不是 Worker 脚本。检查响应体而不是只检查response.ok。以 PowerShell 为例直接查看响应内容的前 120 个字符$r Invoke-WebRequest -Uri http://localhost:1911/vue.c1e83ed7.worker.js -UseBasicParsing $r.Content.Substring(0, [Math]::Min(120, $r.Content.Length))如果响应以!doctype html开头说明该 Worker URL 确实缺失浏览器实际上把 HTML 当作 Worker 脚本加载了。这也是排查文档中反复强调的经验只断言fetch(url).ok的 E2E 检查在 preview 服务器存在 HTML 兜底时会漏掉缺失资源的缺陷。4. 修改 Rust 插件后必须先重建平台二进制farmfe/plugin-worker是 Rust 实现的 NAPI 插件rust-plugins/worker/scripts/index.js 会按平台、架构从npm/platform/index.farm加载对应的本地二进制。因此修改rust-plugins/worker/src/*.rs后必须先重新构建插件再运行示例否则farm build仍会加载旧的本地index.farm二进制改动不会生效pnpm --filter farmfe/plugin-worker build pnpm run test-e2e -- --example rust-plugin-worker其中pnpm run test-e2e -- --example rust-plugin-worker由 scripts/test-e2e.mjs 解析--example指定只跑单个示例并禁用并行。根因动态入口名与模块图去重的错位Worker 入口名是如何被计算的源码证据从当前已修复的源码看Worker 插件的核心逻辑集中在 rust-plugins/worker/src/lib.rs 与 rust-plugins/worker/src/codegen.rsload钩子识别带?worker/?sharedworker/?workerinline的虚拟模块返回 URL 型 wrapper 模块或 inline 占位模块transform钩子用 constants.rs 中定义的WORKER_IMPORT_META_URL_RE正则匹配new Worker(new URL(..., import.meta.url))将其改写为确定性的输出 URL并把(importer, worker 源路径, 入口名)记录到transform_worker_depsanalyze_deps钩子为上述两类发现注入ResolveKind::DynamicEntry { name: entry_name, ... }依赖让 Farm 把 Worker 源编译为独立 chunk。问题出在入口名的哈希输入。修复前的实现用「Worker 源文件名 导入时带查询参数的module_id字节」作为哈希输入导致同一个源文件因查询参数不同而算出不同的入口名src/worker/vue.worker.ts?worker - vue.63ddc497.worker.js src/worker/vue.worker.ts?workerurl - vue.c1e83ed7.worker.js模块图按真实源模块去重Farm 存储动态入口时按解析后的源模块进行去重。上面这些导入最终都解析到同一个vue.worker.ts源文件因此模块图对这份源只能保留一个动态入口名。错位由此产生wrapper 模块在生成阶段立即创建不同语法可能指向不同 URL模块图只对解析后的源发出一个 Worker 资源任何指向未被选中 URL 的 wrapper运行时会 404 / 加载到 HTML导致用例失败。此外还有一个平台敏感的细节解析出的路径在 Windows 上可能包含\在类 Unix 上使用/不同 resolve 分支也可能产生差异。若路径字符串未规范化就参与哈希等价源文件在不同平台或不同调用点仍会算出不同入口名。修复让入口名只依赖真实的 Worker 源路径修复的核心思路是让 Worker 入口名对真实的 Worker 源文件保持稳定。对应实现见 codegen.rs 的compute_worker_entry_name以解析后的 Worker 源路径resolved_path作为哈希输入而不是带查询参数的虚拟module_id函数签名中module_id已改为_module_id不再参与计算哈希前规范化路径分隔符resolved_path.replace(\\, /)把 Windows 反斜杠统一为/从规范化源路径中取文件名 stem去掉扩展名作为入口名的可读前缀。入口名随后经output.assets_filename模板如asserts/[resourceName].[hash].[ext]生成完整文件名并剥离扩展名得到vue.xxxx.worker这样的裸入口名codegen.rs 的compute_worker_url再套用output.entry_filename与public_path得到最终可访问的 URL。示例工程的配置见 examples/rust-plugin-worker/farm.config.ts其中插件选项里设置了assetsFilename: asserts/[resourceName].[hash].[ext]。回归覆盖需要包含两类场景同一源、不同查询参数?worker与?workerurl必须算出同一个入口名同一源、不同路径分隔符C:\project\...与C:/project/...必须算出同一个入口名。这两条已固化为 codegen.rs 中的单元测试worker_entry_name_is_stable_for_same_source_with_different_queries用C:\project\src\worker\vue.worker.ts分别以?worker、?workerurl两种 module_id 调用断言入口名相等worker_entry_name_is_stable_for_same_source_with_different_path_separators对比反斜杠路径与正斜杠路径断言入口名相等。验证与回归修复后的最小验证流程如下cargo test -p farmfe_plugin_worker worker_entry_name_is_stable pnpm --filter farmfe/plugin-worker build pnpm run test-e2e -- --example rust-plugin-worker期望结果cargo test ... 2 passed rust-plugin-worker › start passed rust-plugin-worker › preview passed最后再检查重建后的dist/index.*.js所有对同一份vue.worker.ts源的引用?worker、?workerurl、两种new URL写法都应指向同一个产出的vue.*.worker.js文件不再出现「wrapper 指向多个、产物只发一个」的错位。经验总结本次排查沉淀下来四条可复用的工程经验插件在编译器产出资源之前就创建 URL wrapper 时wrapper 预测的 URL 必须与编译器动态入口产出路径使用完全相同的身份标识否则任何一处不一致都会在运行时爆发如果模块图按解析后的源模块去重Worker 源的身份标识就不应包含查询参数?worker、?workerurl这类语法差异必须被归一化只断言fetch(url).ok的 E2E 检查可能漏掉缺失资源缺陷——preview 服务器对缺失脚本可能返回 HTML 兜底并给出 200排查 Worker 失败时务必校验生成 URL 的响应内容如检查是否以!doctype html开头修改 Rust 插件后验证示例前必须重新构建平台插件二进制避免farm build继续加载旧的index.farm本地产物导致「改了没生效」的假象。赞分享前端构建构建工具开发工具【免费下载链接】farmExtremely fast Vite-compatible web build tool written in Rust项目地址https://gitcode.com/gh_mirrors/fa/farm点击查看免费下载相关推荐Unison 中构造器缺失导致的 update 失败声明一致性检查与 alias.term 修复指南Unison 中构造器缺失导致的 update 失败声明一致性检查与 alias.term 修复指南 Unison 的 update 命令在替换类型定义时会对编程语言编译器语言运行时开发工具oh-my-openagent 的 CI 修复实践fileURLToPath 修复 Windows 上 file URL 转换导致的 ENOENT 失败oh my openagent 的 CI 修复实践fileURLToPath 修复 Windows 上 file URL 转换导致的 ENOENT 失败 本篇人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排slime RL Training实战指南一条命令跑通后训练slime RL Training实战指南一条命令跑通后训练 你正准备给 Qwen3 4B 做强化学习后训练训练引擎、推理引擎、奖励数据要自己接装环境就能人工智能大模型强化学习RLHF分布式训练上一篇Krita AI Diffusion插件SD3模型CLIP文件缺失问题的完整解决方案指南下一篇PaddleX 时序预测产线实战基于 Electricity 数据集完成用电量长期预测、调优与部署创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站