如何在 Parcel 项目中构建 Monaco Editor 的语言 Web Worker 并配置 getWorkerUrl?
【免费下载链接】monaco-editorA browser based code editor项目地址: https://gitcode.com/gh_mirrors/mo/monaco-editor
如果你用 Parcel 打包 Monaco Editor 的 ESM 版本,会遇到一个必须解决的问题:编辑器的语言服务(JSON、CSS、HTML、TypeScript 等)运行在 Web Worker 里,而 Parcel 不会自动处理这些 worker,你需要在self.MonacoEnvironment上配置getWorkerUrl,告诉编辑器每个语言的 worker 从哪里加载。monaco-editor 仓库里有一个可运行的 Parcel 示例(samples/browser-esm-parcel),示例使用的依赖版本是monaco-editor ^0.32.0和parcel ^2.2.1(见 package.json),本文按这个示例给出两种可用的 worker 构建与配置方式,并说明各自的适用位置。
准备项目与依赖
示例项目的 package.json 内容如下,两个依赖都在devDependencies中:
{ "name": "helloworld", "scripts": { "start": "parcel ./src/index.html" }, "devDependencies": { "monaco-editor": "^0.32.0", "parcel": "^2.2.1" } }入口 HTML 需要一个编辑器挂载容器,并以 module 方式引入入口脚本,参考示例的 src/index.html:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> </head> <body> <div id="container" style="width: 800px; height: 600px; border: 1px solid #ccc"></div> <script type="module" src="index.js"></script> </body> </html>在browser-esm-parcel目录下执行安装:
npm install .主路径:用url:导入 worker,由 getWorkerUrl 返回对应 URL
仓库自带的可运行示例(src/index.js)不单独构建 worker,而是用 Parcel 的url:导入让 Parcel 自己输出每个 worker 的 URL,getWorkerUrl直接返回这些 URL:
import JSONWorker from 'url:monaco-editor/esm/vs/language/json/json.worker.js'; import CSSWorker from 'url:monaco-editor/esm/vs/language/css/css.worker.js'; import HTMLWorker from 'url:monaco-editor/esm/vs/language/html/html.worker.js'; import TSWorker from 'url:monaco-editor/esm/vs/language/typescript/ts.worker.js'; import EditorWorker from 'url:monaco-editor/esm/vs/editor/editor.worker.js'; import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js'; self.MonacoEnvironment = { getWorkerUrl: function (moduleId, label) { if (label === 'json') { return JSONWorker; } if (label === 'css' || label === 'scss' || label === 'less') { return CSSWorker; } if (label === 'html' || label === 'handlebars' || label === 'razor') { return HTMLWorker; } if (label === 'typescript' || label === 'javascript') { return TSWorker; } return EditorWorker; } }; monaco.editor.create(document.getElementById('container'), { value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'), language: 'javascript' });getWorkerUrl的第二个参数label是编辑器根据当前语言请求 worker 时给出的标签,上面对应关系就是:json用 JSON worker;css、scss、less共用 CSS worker;html、handlebars、razor共用 HTML worker;typescript、javascript共用 TS worker;其余情况落到默认的editor.worker。如果你不用某些语言,可以只保留用到的分支。
备选路径:用 shell 脚本单独构建每个 worker 打包文件
integrate-esm.md 的 Parcel 小节给出了另一条路径:把 worker 从主入口中拆出来单独parcel build,getWorkerUrl返回 worker 文件相对于主 bundle 的静态路径(如./json.worker.js)。文档建议用一个 bash 脚本完成,内容如下:
ROOT=$PWD/node_modules/monaco-editor/esm/vs OPTS="--no-source-maps --log-level 1" # Parcel 选项 parcel build $ROOT/language/json/json.worker.js $OPTS parcel build $ROOT/language/css/css.worker.js $OPTS parcel build $ROOT/language/html/html.worker.js $OPTS parcel build $ROOT/language/typescript/ts.worker.js $OPTS parcel build $ROOT/editor/editor.worker.js $OPTS保存为build_workers.sh后,文档给出的运行方式是:
sh ./build_workers.sh && parcel index.html这条路径有两个必须注意的限制(文档原文说明):
- worker 会构建到与主 bundle 相同的目录(通常是
./dist); - 如果你想修改 worker 的
--out-dir,必须同步修改index.js中getWorkerUrl返回的路径;getWorkerUrl中的路径是相对于 src bundle 的构建目录的。
也就是说,这条路径下getWorkerUrl不再返回url:导入的变量,而是返回./json.worker.js、./css.worker.js、./html.worker.js、./ts.worker.js、./editor.worker.js这类固定相对路径(各分支与主路径的 label 匹配逻辑一致)。
运行与验证
启动命令来自示例package.json的start脚本,等价于parcel ./src/index.html:
npm start启动后按示例 index.html 的说明打开http://localhost:9999/。验证时看两点:
- 页面
#container中渲染出编辑器,并加载示例中的 JavaScript 代码function x() { ... }; - 编辑器以
language: 'javascript'创建,按上面的 label 映射会请求ts.worker。若某个语言的补全、诊断等功能异常,优先检查getWorkerUrl中该语言的分支是否存在、返回的 URL 是否指向真实构建出的 worker 文件(备选路径下还要确认 worker 确实被构建到了主 bundle 同级目录)。
两条路径任选其一即可:主路径由 Parcel 在正常打包流程内产出 worker,配置简单;备选路径把 worker 的构建显式拆成独立命令,适合需要单独控制 worker 构建参数(如--no-source-maps、--out-dir)的情况,代价是路径要手工保持一致。
【免费下载链接】monaco-editorA browser based code editor项目地址: https://gitcode.com/gh_mirrors/mo/monaco-editor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考