Rails 6 + Webpacker 环境下加载 Web Worker 的正确实现方法
解决方案
错误原因
你当前将timer.js放在public目录下,文件没有经过Webpack编译处理,浏览器会直接将其作为普通脚本加载,无法识别ES Module的import语法,因此抛出对应的语法错误。
第一步:调整Worker文件存放位置
在app/javascript目录下新建workers文件夹,将你的timer.js移动到该路径下,最终路径为app/javascript/workers/timer.js。
第二步:配置Webpacker编译Worker文件
你需要将Worker文件配置为Webpack的独立入口,确保编译时能正确处理依赖导入,修改config/webpack/environment.js文件:
const { environment } = require('@rails/webpacker') // 添加Timer Worker的独立入口配置 environment.config.set('entry.timer_worker', 'app/javascript/workers/timer.js') module.exports = environment
配置完成后重新启动Webpacker服务,编译后会生成独立的packs/js/timer_worker-[哈希值].js文件。
第三步:在ERB中获取Worker的访问路径
Webpacker提供了asset_pack_path辅助方法用于获取编译后的静态资源路径,你可以将路径传递给Stimulus控制器,示例如下:
<!-- 示例:传递Worker路径给Stimulus控制器 --> <div data-controller="timer" data-timer-worker-url-value="<%= asset_pack_path('js/timer_worker.js') %>" > <!-- 你的页面内容 --> </div>
第四步:在Stimulus控制器中初始化Worker
在对应的Stimulus控制器中直接使用传入的路径实例化Worker即可:
import { Controller } from "@hotwired/stimulus" export default class extends Controller { static values = { workerUrl: String } connect() { // 初始化Worker this.worker = new Worker(this.workerUrlValue) // 监听Worker返回的消息,更新页面计时/处理错误 this.worker.addEventListener('message', (e) => { if (e.data.timeRemaining) { // 处理计时更新逻辑 } if (e.data.error) { alert(e.data.error) } }) // 向Worker传递请求地址、初始剩余时间等参数 this.worker.postMessage({ postUrl: '你的后端请求地址', timeRemaining: 60 // 示例初始时间 }) } disconnect() { // 页面卸载时销毁Worker,避免内存泄漏 this.worker.terminate() } }
修正Worker代码的问题
Web Worker运行在独立线程中,没有Window对象,无法调用alert等DOM相关API,你需要修改timer.js中的错误逻辑,将提示改为向主线程发消息:
// 将原alert逻辑替换为postMessage if (postFailures < 5) { setTimeout(finishActivity, 1000); } else { postMessage({ error: "请求失败,请刷新页面重试" }); }
内容的提问来源于stack exchange,提问作者David Gay
相关产品推荐
相关产品推荐

