diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b809f16..5891f9a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [4.6.2](https://github.com/vuejs/repl/compare/v4.6.1...v4.6.2) (2025-07-16) + + +### Bug Fixes + +* handle Vue 3.6+ vapor runtime imports correctly ([#357](https://github.com/vuejs/repl/issues/357)) ([c4bac9c](https://github.com/vuejs/repl/commit/c4bac9c9d22813cdb343f850da516e84a0700e4d)), closes [#356](https://github.com/vuejs/repl/issues/356) + + + ## [4.6.1](https://github.com/vuejs/repl/compare/v4.6.0...v4.6.1) (2025-06-13) diff --git a/package.json b/package.json index f903b846..274fc7c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vue/repl", - "version": "4.6.1", + "version": "4.6.2", "description": "Vue component for editing Vue components", "packageManager": "pnpm@9.15.5", "type": "module", diff --git a/src/import-map.ts b/src/import-map.ts index bc11cd50..328cb40b 100644 --- a/src/import-map.ts +++ b/src/import-map.ts @@ -1,5 +1,15 @@ import { computed, version as currentVersion, ref } from 'vue' +export function getVersions(version: string): number[] { + return version.split('.').map((v) => parseInt(v, 10)) +} + +export function isVaporSupported(version: string): boolean{ + const [major, minor] = getVersions(version) + // vapor mode is supported in v3.6+ + return major > 3 || (major === 3 && minor >= 6) +} + export function useVueImportMap( defaults: { runtimeDev?: string | (() => string) @@ -15,15 +25,21 @@ export function useVueImportMap( const productionMode = ref(false) const vueVersion = ref(defaults.vueVersion || null) + + function getVueURL() { + const version = vueVersion.value || currentVersion + return isVaporSupported(version) + ? `https://cdn.jsdelivr.net/npm/vue@${version}/dist/vue.runtime-with-vapor.esm-browser${productionMode.value ? `.prod` : ``}.js` + : `https://cdn.jsdelivr.net/npm/@vue/runtime-dom@${version}/dist/runtime-dom.esm-browser${productionMode.value ? `.prod` : ``}.js` + } + const importMap = computed(() => { const vue = (!vueVersion.value && normalizeDefaults( productionMode.value ? defaults.runtimeProd : defaults.runtimeDev, )) || - `https://cdn.jsdelivr.net/npm/@vue/runtime-dom@${ - vueVersion.value || currentVersion - }/dist/runtime-dom.esm-browser${productionMode.value ? `.prod` : ``}.js` + getVueURL() const serverRenderer = (!vueVersion.value && normalizeDefaults(defaults.serverRenderer)) || diff --git a/src/output/Sandbox.vue b/src/output/Sandbox.vue index d580fa45..c62f480c 100644 --- a/src/output/Sandbox.vue +++ b/src/output/Sandbox.vue @@ -16,6 +16,7 @@ import { PreviewProxy } from './PreviewProxy' import { compileModulesForPreview } from './moduleCompiler' import type { Store } from '../store' import { injectKeyProps } from '../types' +import { getVersions, isVaporSupported } from '../import-map' export interface SandboxProps { store: Store @@ -202,9 +203,7 @@ async function updatePreview() { let isSSR = props.ssr if (store.value.vueVersion) { - const [major, minor, patch] = store.value.vueVersion - .split('.') - .map((v) => parseInt(v, 10)) + const [major, minor, patch] = getVersions(store.value.vueVersion) if (major === 3 && (minor < 2 || (minor === 2 && patch < 27))) { alert( `The selected version of Vue (${store.value.vueVersion}) does not support in-browser SSR.` + @@ -214,6 +213,10 @@ async function updatePreview() { } } + const vaporSupported = isVaporSupported( + store.value.vueVersion || store.value.compiler?.version + ) + try { const { mainFile } = store.value @@ -228,10 +231,11 @@ async function updatePreview() { `const __modules__ = {};`, ...ssrModules, `import { renderToString as _renderToString } from 'vue/server-renderer' - import { createSSRApp as _createApp } from 'vue' + import { createSSRApp as _createApp ${vaporSupported ? ', createVaporSSRApp as _createVaporApp' : ''} } from 'vue' const AppComponent = __modules__["${mainFile}"].default AppComponent.name = 'Repl' - const app = _createApp(AppComponent) + const vaporSupported = ${vaporSupported} + const app = (vaporSupported && AppComponent.__vapor ? _createVaporApp : _createApp)(AppComponent) if (!app.config.hasOwnProperty('unwrapInjectedRef')) { app.config.unwrapInjectedRef = true } @@ -297,14 +301,19 @@ async function updatePreview() { // if main file is a vue file, mount it. if (mainFile.endsWith('.vue')) { codeToEval.push( - `import { ${ - isSSR ? `createSSRApp` : `createApp` - } as _createApp } from "vue" + `import { ${isSSR ? `createSSRApp` : `createApp`} as _createApp ${ + vaporSupported + ? `, ${ + isSSR ? 'createVaporSSRApp' : 'createVaporApp' + } as _createVaporApp` + : '' + } } from "vue" ${previewOptions.value?.customCode?.importCode || ''} const _mount = () => { const AppComponent = __modules__["${mainFile}"].default AppComponent.name = 'Repl' - const app = window.__app__ = _createApp(AppComponent) + const vaporSupported = ${vaporSupported} + const app = window.__app__ = (vaporSupported && AppComponent.__vapor ? _createVaporApp : _createApp)(AppComponent) if (!app.config.hasOwnProperty('unwrapInjectedRef')) { app.config.unwrapInjectedRef = true }