这是我参与「第四届青训营 」笔记创作活动的第2天
优化前后对比
这是全量导入Monaco-editor的情况
这是只导入editor核心的情况
可以看到全量导入的时候左边很多一小块一小块的都是一些并没有用到的语言
在Monaco-editor github官方“Integrating the ESM version of the Monaco Editor”
这篇使用说明中全部都是使用的全量导入。并且也没有说可以使用按需导入。
例如在Vite中使用
按需导入
直到我发现了这句话
// or import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// if shipping only a subset of the features & languages is desired
那就按照他的来试一下
// import * as monaco from 'monaco-editor';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// if shipping only a subset of the features & languages is desired
monaco.editor.create(document.getElementById('container'), {
value: 'console.log("Hello, world")',
language: 'javascript'
});
注意:这样只会导入编辑器核心,就算导入了对应语言的worker也不能进行语法着色,也没有右键,命名面板等功能
所有语言、特性都需要手动启用
按需启用语言
这里我的需求是启用特定某几个语言和全部的特性
我们可以直接去node_modules下,找到这个json文件
node_modules/monaco-editor/esm/metadata.js
比如我需要启用json、js和ts
就需要像这样导入
- entry字段直接import进来就好了
- worker字段需要导入进来并且注册到getWorker中
/**
* Using Vite
* @link https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md#using-vite
*/
import * as Monaco from 'monaco-editor/esm/vs/editor/editor.api'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import './use-features'
// 语言
// json
import 'monaco-editor/esm/vs/language/json/monaco.contribution'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
// js
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution'
// ts
import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution'
import 'monaco-editor/esm/vs/language/typescript/monaco.contribution'
import TSWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
self.MonacoEnvironment = {
getWorker(_: string, label: string) {
if (label === 'json') {
return new JsonWorker()
}
if (label === 'typescript' || label === 'javascript') {
return new TSWorker()
}
return new EditorWorker()
},
}
export default Monaco
启用所有特性
这里如果一个个手写import的话怎么可能。有两百多行。我们写一个函数让他自己生成就好了
import metadata from 'monaco-editor/esm/metadata'
const prefix = 'monaco-editor/esm/'
const autoImport = metadata.features.map((feat) => {
let entry =
Object.prototype.toString.call(feat.entry) === '[object String]'
? [feat.entry as string]
: (feat.entry as string[])
entry = entry.map((val) => `import '${prefix}${val}'`)
return `// ${feat.label}
${entry.join('\n')}`
})
console.log(autoImport.join('\n'))
效果如下,直接复制粘贴进代码就成了
手动分包
这里是默认情况下没有对monaco进行手动分包的打包结果
monaco-editor和业务代码和在了一个chunk里面,但是我们并不需要页面落地就完成monaco的加载
所以这里需要手动分包一下,让monaco这个庞然巨物自己分一个chunk
在vite.config.ts中
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: (e) => {
if (e.includes('/node_modules/monaco-editor/')) return 'monaco'
else if (...)
return 'vendor'
},
},
},
},
})
这下终于齐活了
worker分包
但是一看日志。为啥worker还是单独的包
于是去vite官网找了一圈
默认情况下,worker 脚本将在生产构建中编译成单独的 chunk。
不过这么大的语法解析器内联为base64肯定不行。
所以我们还是得对worker再进行一次分包
worker的可以配置的选项和build的配置一样的。
只不过位置换一个地方而已,位于worker.rollupOptions
打包时候给了我一个报错
[vite:worker] Invalid value "iife" for option "output.format" - UMD and IIFE output formats are not supported for code-splitting builds.
但是我并没有找到解决方案。我还不清楚vite中怎么对worker进行分包