fix: 修复preview生产打包的时候repl引入的monaco-editor里的worker跨域报错 (#245)

* fix: 修复preview生产打包的时候repl引入的monaco-editor里的worker跨域报错

* feat(design-core/preview): 预览增加调试按钮来打开vue-repl编辑模式,并实现编辑器懒加载

* fix(design-core/preview): 修复repl-patch引入脚本路径模块化不支持importScripts问题
This commit is contained in:
rhlin 2024-02-26 14:15:31 +08:00 committed by GitHub
parent 96def94945
commit 683fc51d52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 137 additions and 15 deletions

View File

@ -65,5 +65,10 @@
"engines": {
"node": ">=14",
"pnpm": ">=7"
},
"pnpm": {
"patchedDependencies": {
"@vue/repl@2.9.0": "patches/@vue__repl@2.9.0.patch"
}
}
}

View File

@ -105,6 +105,7 @@
"assert": "^2.0.0",
"buffer": "^6.0.3",
"cross-env": "^7.0.3",
"esbuild-plugin-copy": "^2.1.1",
"eslint": "^8.38.0",
"eslint-plugin-vue": "^8.0.0",
"fs-extra": "^10.1.0",

View File

@ -4,6 +4,7 @@
</template>
<script>
import { useDebugSwitch } from './preview/debugSwitch'
import Preview from './preview/Preview.vue'
import Toolbar from './Toolbar.vue'
import '@opentiny/tiny-engine-theme'
@ -18,6 +19,9 @@ export default {
type: Boolean,
default: true
}
},
setup() {
useDebugSwitch()
}
}
</script>

View File

@ -7,6 +7,7 @@
<component :is="ToolbarMedia" :isCanvas="false" @setViewPort="setViewPort"></component>
</div>
<div class="toolbar-right">
<span><tiny-switch v-model="debugSwitch"></tiny-switch><span class="toolbar-button-text">调试模式</span></span>
<component :is="ChangeLang" :langChannel="previewLangChannel"></component>
</div>
</div>
@ -15,9 +16,11 @@
<script lang="jsx">
import { defineAsyncComponent } from 'vue'
import { useBreadcrumb } from '@opentiny/tiny-engine-controller'
import { Switch as TinySwitch } from '@opentiny/vue'
import { getSearchParams } from './preview/http'
import { BROADCAST_CHANNEL } from '../src/preview/srcFiles/constant'
import addons from '@opentiny/tiny-engine-app-addons'
import { injectDebugSwitch } from './preview/debugSwitch'
const getToolbars = (pluginId) => {
return defineAsyncComponent(() =>
@ -26,7 +29,11 @@ const getToolbars = (pluginId) => {
}
export default {
components: {
TinySwitch
},
setup() {
const debugSwitch = injectDebugSwitch()
const tools = ['breadcrumb', 'lang', 'media']
const [Breadcrumb, ChangeLang, ToolbarMedia] = tools.map(getToolbars)
@ -47,7 +54,8 @@ export default {
Breadcrumb,
ChangeLang,
ToolbarMedia,
setViewPort
setViewPort,
debugSwitch
}
}
}
@ -71,6 +79,13 @@ export default {
.toolbar-left,
.toolbar-right {
margin: 0 12px;
display: flex;
gap: 12px;
}
.toolbar-button-text {
color: #191919;
margin-left: 4px;
font-size: 12px;
}
:deep(.top-panel-breadcrumb) {
width: auto;

View File

@ -1,18 +1,21 @@
<template>
<Repl
:editor="Monaco"
:store="store"
:sfcOptions="sfcOptions"
:showCompileOutput="false"
:showImportMap="false"
:clearConsole="false"
:autoResize="false"
/>
<div :class="['vue-repl-container', debugSwitch ? 'preview-debug-mode' : '']">
<Repl
:editor="editorComponent"
:store="store"
:sfcOptions="sfcOptions"
:showCompileOutput="false"
:showTsConfig="false"
:showImportMap="true"
:clearConsole="false"
:autoResize="false"
/>
</div>
</template>
<script>
import { defineComponent, computed, defineAsyncComponent } from 'vue'
import { Repl, ReplStore } from '@vue/repl'
import Monaco from '@vue/repl/monaco-editor'
import vueJsx from '@vue/babel-plugin-jsx'
import { transformSync } from '@babel/core'
import { Notify } from '@opentiny/vue'
@ -21,8 +24,17 @@ import srcFiles from './srcFiles'
import generateMetaFiles, { processAppJsCode } from './generate'
import { getSearchParams, fetchCode, fetchMetaData } from './http'
import { PanelType, PreviewTips } from '../constant'
import { injectDebugSwitch } from './debugSwitch'
import '@vue/repl/style.css'
const Monaco = defineAsyncComponent(() => import('@vue/repl/monaco-editor')) // debug
const EmptyEditor = defineComponent({
setup() {
return () => null
}
})
const importNames = [
'createVNode',
'Fragment',
@ -51,6 +63,8 @@ export default {
Repl
},
setup() {
const debugSwitch = injectDebugSwitch()
const editorComponent = computed(() => (debugSwitch?.value ? Monaco : EmptyEditor))
const store = new ReplStore()
const compiler = store.compiler
@ -96,6 +110,7 @@ export default {
await store.setFiles(newFiles, mainFileName)
// codeSandbox
store.state.resetFlip = !store.state.resetFlip
store['initTsConfig']() // d.ts便
}
const addUtilsImportMap = (utils = []) => {
@ -173,7 +188,8 @@ export default {
return {
store,
sfcOptions,
Monaco
editorComponent,
debugSwitch
}
}
}
@ -181,8 +197,7 @@ export default {
<style lang="less">
.vue-repl {
width: 100vw;
height: 100vh;
height: 100%;
.split-pane {
.left {
@ -206,4 +221,16 @@ export default {
}
}
}
.vue-repl-container {
height: calc(100vh - 48px);
&.preview-debug-mode .vue-repl .split-pane {
.left,
.right .tab-buttons {
display: block;
}
.right .output-container {
height: calc(100% - 38px);
}
}
}
</style>

View File

@ -0,0 +1,10 @@
import { ref, provide, inject } from 'vue'
export const debuggerSwitchTokenKey = Symbol('tiny-engine-preview-debug-switch')
export function useDebugSwitch() {
const debugSwitch = ref(false)
provide(debuggerSwitchTokenKey, debugSwitch)
return debugSwitch
}
export function injectDebugSwitch() {
return inject(debuggerSwitchTokenKey)
}

View File

@ -7,6 +7,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
import nodeGlobalsPolyfillPlugin from '@esbuild-plugins/node-globals-polyfill'
import nodeModulesPolyfillPlugin from '@esbuild-plugins/node-modules-polyfill'
import nodePolyfill from 'rollup-plugin-polyfill-node'
import esbuildCopy from 'esbuild-plugin-copy'
import lowcodeConfig from './config/lowcode.config'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { importmapPlugin } from './scripts/externalDeps'
@ -79,7 +80,16 @@ const config = {
process: true,
buffer: true
}),
nodeModulesPolyfillPlugin()
nodeModulesPolyfillPlugin(),
esbuildCopy({
//@vue/repl monaco编辑器需要
resolveFrom: 'cwd',
assets: {
from: ['./node_modules/@vue/repl/dist/assets/*'], // worker.js文件以url形式引用不会被esbuild拉起需要手动复制
to: ['./node_modules/.vite/assets'] // 开发态js文件被缓存在.vite/deps请求相对路径为.vite/assets
},
watch: true
})
]
}
},

View File

@ -0,0 +1,50 @@
diff --git a/dist/chunks/MonacoEditor-KSgTEMrh.js b/dist/chunks/MonacoEditor-KSgTEMrh.js
index c9668cbf8c44ba3c816246b746127204839f8349..e893c59a432e53372c18aa2e70d7b7bb9fd666ba 100644
--- a/dist/chunks/MonacoEditor-KSgTEMrh.js
+++ b/dist/chunks/MonacoEditor-KSgTEMrh.js
@@ -1,5 +1,13 @@
import { watchEffect, defineComponent, ref, shallowRef, inject, computed, onMounted, nextTick, watch, onBeforeUnmount, openBlock, createElementBlock, createBlock } from 'vue';
import { c as commonjsGlobal, a as getAugmentedNamespace } from './_commonjsHelpers-9Q-OoQuc.js';
+function getWorkerURL(url){
+ if (typeof document !== 'undefined' && document.location && document.location.origin !== url.origin) {
+ return URL.createObjectURL(new Blob([`import '${url.href}'`], {
+ type: 'application/javascript'
+ }))
+ }
+ return url.href;
+}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
@@ -170640,7 +170648,7 @@ var languages;
function WorkerWrapper$1(options) {
return new Worker(
- ""+new URL('../assets/editor.worker-FXpxnIqv.js', import.meta.url).href+"",
+ ""+getWorkerURL(new URL('../assets/editor.worker-FXpxnIqv.js', import.meta.url))+"",
{
type: "module",
name: options?.name
@@ -172020,7 +172028,7 @@ function getOrCreateModel(uri, lang, value) {
function WorkerWrapper(options) {
return new Worker(
- ""+new URL('../assets/vue.worker-eqEbSb3e.js', import.meta.url).href+"",
+ ""+getWorkerURL(new URL('../assets/vue.worker-eqEbSb3e.js', import.meta.url))+"",
{
type: "module",
name: options?.name
diff --git a/dist/vue-repl.js b/dist/vue-repl.js
index 43bfd22a1a7d6f831e3f85228d809750317c4bfb..d5f5cb335533295c63e4cfa8aaa02770d16babca 100644
--- a/dist/vue-repl.js
+++ b/dist/vue-repl.js
@@ -528,7 +528,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
"allow-popups",
"allow-same-origin",
"allow-scripts",
- "allow-top-navigation-by-user-activation"
+ "allow-top-navigation-by-user-activation",
+ "allow-downloads"
].join(" ")
);
const importMap = store.getImportMap();