Monaco Editor 支持
Nasti 内置 monacoEditorPlugin,为
Monaco Editor
(VS Code 使用的代码编辑器)提供一站式集成:预打包 Web Worker、注入
MonacoEnvironment、生产构建自动产出 Worker 资源。接口与
vite-plugin-monaco-editor 基本对齐,可无痛迁移。
- Monaco 的 Worker 是独立入口,必须单独打包。手动配置极易出错;
- monaco-editor 包含 2000+ 源文件。按 ESM 逐文件交给 dev server
会触发大量并发文件读取,在 macOS 等低
ulimit环境下 HMR 时抛出 EMFILE(too many open files)。本插件把 Worker 预打包成单文件缓存, 并显式把monaco-editor目录从 watcher 中剔除作为双保险。
安装
npm install monaco-editor npm install -D @nasti-toolchain/nasti
最小配置
// nasti.config.ts import { defineConfig, monacoEditorPlugin } from '@nasti-toolchain/nasti' export default defineConfig({ plugins: [monacoEditorPlugin()], })
在代码里直接 import * as monaco from 'monaco-editor',Worker 会自动从
/monacoeditorwork/<label>.worker.js 加载,不需要任何手工
new Worker(new URL(...)) 胶水代码。
使用示例
// src/main.ts import * as monaco from 'monaco-editor' monaco.editor.create(document.getElementById('editor')!, { value: 'function hi() {\n console.log("hello monaco")\n}', language: 'typescript', theme: 'vs-dark', automaticLayout: true, })
选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
languageWorkers |
MonacoEditorLanguageWorker[] |
['editorWorkerService','css','html','json','typescript'] |
启用的内置语言 Worker 列表 |
customWorkers |
{ label, entry }[] |
[] |
自定义 Worker,例如 monaco-graphql |
publicPath |
string |
'monacoeditorwork' |
Worker 在 URL 上的公共前缀;可填 CDN 绝对 URL |
globalAPI |
boolean |
false |
是否将 Monaco API 暴露到 window.monaco |
forceBuildCDN |
boolean |
false |
publicPath 是 CDN 时仍强制本地产出 Worker 文件 |
customDistPath |
(root, outDir, base) => string |
— | 自定义生产构建 Worker 产物目录(返回绝对路径) |
裁剪语言 Worker
只用到 JSON 和 TypeScript?只打包这两个,减小产物体积:
monacoEditorPlugin({ languageWorkers: ['editorWorkerService', 'json', 'typescript'], })
editorWorkerService 是 Monaco 的基础 Worker,
任何情况下都应保留。SCSS / Less 共用 css,Handlebars 共用
html,无需单独声明。
自定义 Worker
集成 GraphQL、YAML 等第三方 Worker:
monacoEditorPlugin({ customWorkers: [ { label: 'graphql', entry: 'monaco-graphql/esm/graphql.worker' }, { label: 'yaml', entry: 'monaco-yaml/yaml.worker' }, ], })
CDN 部署
将 Worker 放到 CDN 上,publicPath 传入绝对 URL:
monacoEditorPlugin({ publicPath: 'https://cdn.example.com/monacoeditorwork', forceBuildCDN: true, // 仍然生成本地产物,便于自行上传 CDN })
跨域 Worker 会被浏览器拒绝直接加载,插件注入的运行时会自动用
Blob + importScripts 包一层规避同源策略。
globalAPI
兼容旧 API 的 window.monaco 访问方式:
monacoEditorPlugin({ globalAPI: true }) // 然后在任意地方: window.monaco.editor.getModels()
工作原理
-
插件启动:以
monaco-editor/esm/vs/.../xxx.worker为入口,用 Rolldown 预打包为 单个 IIFE 文件,缓存到node_modules/.nasti/monaco/<版本hash>/<label>.worker.js, 并发请求做去重。 -
Dev 中间件:拦截
GET /<publicPath>/<label>.worker.js,直接从缓存磁盘流式返回, 不走 transform 管线 ⇒ 没有并发 fd 风暴。 -
HTML 注入:在
<head>头部注入一段内联脚本, 设置self.MonacoEnvironment.getWorkerUrl指向缓存 URL。 -
生产构建:
buildStart阶段把缓存产物拷到outDir/<publicPath>/下,随主包一起部署。 -
EMFILE 防御:
configureServer阶段显式watcher.unwatch(node_modules/monaco-editor),防止符号链接、嵌套node_modules等路径绕过默认忽略规则。
与 Vite 插件迁移差异
| vite-plugin-monaco-editor | @nasti-toolchain/nasti |
|---|---|
import monacoEditorPlugin from 'vite-plugin-monaco-editor' |
import { monacoEditorPlugin } from '@nasti-toolchain/nasti' |
| 默认命名导出 | 具名导出 |
| Worker 打包使用 esbuild | Worker 打包使用 Rolldown |
缓存目录 node_modules/.monaco |
缓存目录 node_modules/.nasti/monaco/<版本hash>(版本切换自动失效) |
排障
HMR 时仍然报 EMFILE
确认插件已注册并查看启动日志是否有
[nasti:monaco-editor] worker build failed。如果是 macOS,临时
ulimit -n 10240 可缓解;若依赖链中还有其它大包(如
ionicons、@mui/icons-material),也建议类似地预打包。
Worker 404
访问 /monacoeditorwork/editorWorkerService.worker.js 看是否能返回。
若 404:monaco-editor 未安装;若 500:看服务器日志里的打包错误。
跨框架集成
React(@monaco-editor/react)、Vue(@guolao/vue-monaco-editor)
等封装库底层仍使用 monaco-editor,无需额外配置。