Import monaco-editor using Vite 2 #1791
Replies: 14 comments 30 replies
-
I just looked into it and it seems Monaco Editor's ESM usage requires pre-bundling the workers: https://github.com/microsoft/monaco-editor/blob/master/docs/integrate-esm.md So essentially we need a Vite config like this: const prefix = `monaco-editor/esm/vs`
module.exports = {
optimizeDeps: {
include: [
`${prefix}/language/json/json.worker`,
`${prefix}/language/css/css.worker`,
`${prefix}/language/html/html.worker`,
`${prefix}/language/typescript/ts.worker`,
`${prefix}/editor/editor.worker`
]
}
} But it seems esbuild has issue pre-bundling this, so I created an issue there: evanw/esbuild#723 Another alternative is for Monaco editor to support initializing workers with |
Beta Was this translation helpful? Give feedback.
-
Ok! Just pushed a small fix and in the next release you should be able to use Monaco without the config: import * as monaco from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
self.MonacoEnvironment = {
getWorker(_, label) {
if (label === 'json') {
return new jsonWorker()
}
if (label === 'css' || label === 'scss' || label === 'less') {
return new cssWorker()
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return new htmlWorker()
}
if (label === 'typescript' || label === 'javascript') {
return new tsWorker()
}
return new editorWorker()
}
}
monaco.editor.create(document.getElementById('container'), {
value: "function hello() {\n\talert('Hello world!');\n}",
language: 'javascript'
}) |
Beta Was this translation helpful? Give feedback.
-
I'm using VanillaJS. For Safari and Firefox, which don't support module workers, I implemented a worker-bundling plugin using esbuild. First create a file
|
Beta Was this translation helpful? Give feedback.
-
Has anyone been able to successfully build self.MonacoEnvironment = {
globalAPI: true,
getWorker: function (workerId: string, label: string) {
console.log("worker: " + workerId); and it creates a monaco editor instance, but without any of the syntax highlighting, etc. that's normally done via a web worker... and it never logs anything from the above |
Beta Was this translation helpful? Give feedback.
-
@khalwat Monaco has a sample vite setup here https://github.com/microsoft/monaco-editor/tree/main/samples/browser-esm-vite-react |
Beta Was this translation helpful? Give feedback.
-
@ChrisShank appreciate it -- I tried that out, to no avail. I think it may be complications of the environment in which I'm trying to use it. |
Beta Was this translation helpful? Give feedback.
-
Using import loader from '@monaco-editor/loader'
loader.config({ paths: { vs: 'https://unpkg.com/[email protected]/min/vs' } }) // or local
let monaco = await loader.init() |
Beta Was this translation helpful? Give feedback.
-
I'm using ServiceWorker and some time ago Safari started crashing when I was using Vite in the dev environment. Finally, I found a minimal solution that works well in all browsers and in production and dev environments. import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp'
import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard'
// import * as monaco from 'monaco-editor'
import { editor } from 'monaco-editor/esm/vs/editor/editor.api'
export { editor }
const isDev = process.env.NODE_ENV === 'development'
console.debug(`* lazy imported monaco-editor, development: ${isDev}`)
// https://vitejs.dev/guide/features.html#web-workers
import monacoJsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import monacoCssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import monacoHtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import monacoTsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import monacoEditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
self.MonacoEnvironment = {
getWorker: function (workerId, label) {
console.debug(`* lazy imported Monaco Editor worker id '${workerId}', label '${label}'`)
const getWorkerModule = (moduleUrl, label) => {
return new Worker(new URL('/node_modules/monaco-editor/esm/vs/' + moduleUrl + '.js?worker', import.meta.url), {
name: label,
type: 'module'
})
}
switch (label) {
case 'json':
return isDev ? getWorkerModule('language/json/json.worker', label) : new monacoJsonWorker()
case 'css':
case 'scss':
case 'less':
return isDev ? getWorkerModule('language/css/css.worker', label) : new monacoCssWorker()
case 'html':
case 'handlebars':
case 'razor':
return isDev ? getWorkerModule('language/html/html.worker', label) : new monacoHtmlWorker()
case 'typescript':
case 'javascript':
return isDev ? getWorkerModule('language/typescript/ts.worker', label) : new monacoTsWorker()
default:
return isDev ? getWorkerModule('editor/editor.worker', label) : new monacoEditorWorker()
}
}
} Monaco started to spam all files to dist folder, delete not wanted after build: # fix-dist.sh
cd dist/assets # fix full path here to prevent errors
# remove extra Monaco files
rm abap.js apex.js azcli.js bat.js bicep.js cameligo.js clojure.js cpp.js coffee.js csharp.js csp.js cypher.js dart.js dockerfile.js ecl.js flow9.js elixir.js freemarker2.js fsharp.js go.js graphql.js handlebars.js hcl.js ini.js java.js julia.js kotlin.js less.js lexon.js liquid.js m3.js mips.js msdax.js mysql.js objective-c.js pascal.js pascaligo.js perl.js php.js pla.js postiats.js powerquery.js powershell.js protobuf.js python.js qsharp.js r.js razor.js redis.js redshift.js restructuredtext.js ruby.js rust.js sb.js scala.js scheme.js shell.js solidity.js sophia.js sparql.js st.js pgsql.js swift.js systemverilog.js tcl.js twig.js vb.js xml.js yaml.js lua.js sql.js |
Beta Was this translation helpful? Give feedback.
-
this works for me, in vite ^4.3.2 |
Beta Was this translation helpful? Give feedback.
-
import() works fine.
|
Beta Was this translation helpful? Give feedback.
-
it's works for me! import "./Monaco.less"
//https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md#using-vite
//https://github.com/vitejs/vite/discussions/1791
import * as monaco from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
export class Monaco extends HTMLElement {
private editor: monaco.editor.IStandaloneCodeEditor
private sizeObserver: ResizeObserver = new ResizeObserver(() => { this.editor.layout() })
constructor() {
super()
self.MonacoEnvironment = {
getWorker(_, label) {
if (label === 'json') { return new jsonWorker() }
if (label === 'css' || label === 'scss' || label === 'less') { return new cssWorker() }
if (label === 'html' || label === 'handlebars' || label === 'razor') { return new htmlWorker() }
if (label === 'typescript' || label === 'javascript') { return new tsWorker() }
return new editorWorker()
}
}
this.editor = monaco.editor.create(this, {
value: [
'function x() {',
'\tconsole.log("Hello world!");',
'}'
].join('\n'),
language: 'typescript'
});
this.editor.onDidChangeModelContent(() => {
if (this.editor) {
const value = this.editor.getValue() // 给父组件实时返回最新文本
this.emit('change', value)
}
})
monaco.editor.setTheme('vs-dark');//设置深色主题 需要在编辑器创建完毕以后使用
//在此类被创建的时候,可能还没有被添加到DOM树中
//因此不会存在parentElement,也无法计算实际大小大小
//我们需要等到上层代码将此类添加到DOM以后 再处理它们
//通常情况下 上层代码在创建完毕以后应立即将他添加到dom中
//使用requestAnimationFrame可以有效的解决这个问题
requestAnimationFrame(() => {
this.editor.layout();
if (this.parentElement) this.sizeObserver.observe(this.parentElement)
})
}
emit(en: string, data: string) {
this.dispatchEvent(new CustomEvent(en, { detail: data }))
}
destroy() {
this.sizeObserver.disconnect()
this.editor.dispose();
}
}
export default Monaco using vite:^5.0.8 monaco-editor:^0.45.0 |
Beta Was this translation helpful? Give feedback.
-
I'm using a component based on monaco-editor ,the error: |
Beta Was this translation helpful? Give feedback.
-
Working solution for vite "cannot use import statement outside module"The solution mentioned here (works on firefox asw well) helped me on my way Maybe this is remix specific but I could not find alot of other resources on the internet so posting it here for others: I got it working with Vite 5 (probably works with v2 as well) and react (remixjs) using the following approach:
import * as monaco from "monaco-editor";
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
self.MonacoEnvironment = {
getWorker(_: any, label: string) {
if (label === "json") {
return new jsonWorker();
}
if (label === "css" || label === "scss" || label === "less") {
return new cssWorker();
}
if (label === "html" || label === "handlebars" || label === "razor") {
return new htmlWorker();
}
if (label === "typescript" || label === "javascript") {
return new tsWorker();
}
return new editorWorker();
},
};
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
import "~/userWorker";
// import * as monaco from 'monaco-editor'; <- PROBLEM: Causes import errors with vite, probably related to
// https://github.com/sveltejs/kit/discussions/3539#discussioncomment-2048425
import type { editor } from "monaco-editor/esm/vs/editor/editor.api"; // you can still use type imports as far as I know
function MonacoEditor() {
const [editor, setEditor] = useState<editor.IStandaloneCodeEditor | null>(
null
);
const ref = useRef(null);
useEffect(() => {
// SOLUTION: instead use dynamic imports on the client side
import("monaco-editor/esm/vs/editor/editor.api").then((monaco) => {
if (ref) {
setEditor((editor: any) => {
if (editor) return editor;
return monaco.editor.create(ref.current!, {
value: [
"function x() {",
'\tconsole.log("Hello world!");',
"}",
].join("\n"),
language: "typescript",
automaticLayout: true,
});
});
}
});
return () => editor?.dispose();
}, [ref.current]);
return <div ref={ref} style={{ height: "100vh", width: "750px" }}></div>;
} |
Beta Was this translation helpful? Give feedback.
-
Hey there!
Currently, I have set up a Vite 2 project with
monaco-editor
as a dependency.Whenever I am trying to use it says that the workers are not imported.
Since I am using Vite 2 I have assumed that simply specifying the rollup plugin
rollup-plugin-monaco-editor
in the plugins array. However, I am still getting this issue.Is there any proper way to import
monaco-editor
into a Vite 2 project?Thanks!
Beta Was this translation helpful? Give feedback.
All reactions