WIP: vue support for app entrypoint
This commit is contained in:
parent
9d5ec1c8c7
commit
5ccb873096
8 changed files with 64 additions and 14 deletions
|
@ -4,5 +4,7 @@ import vue from '@astrojs/vue';
|
|||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
// Enable Vue to support Vue components.
|
||||
integrations: [vue()],
|
||||
integrations: [vue({
|
||||
appEntrypoint: '/src/pages/_app.ts'
|
||||
})],
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<pre>{{ count }}</pre>
|
||||
<button @click="add()">+</button>
|
||||
</div>
|
||||
<Test />
|
||||
<div class="counter-message">
|
||||
<slot />
|
||||
</div>
|
||||
|
|
15
examples/framework-vue/src/components/Test.vue
Normal file
15
examples/framework-vue/src/components/Test.vue
Normal file
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<div>Hello world!</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
onMounted(() => {
|
||||
console.log("Hello world!")
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
6
examples/framework-vue/src/pages/_app.ts
Normal file
6
examples/framework-vue/src/pages/_app.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import type { App } from 'vue';
|
||||
import Test from "../components/Test.vue"
|
||||
|
||||
export default (app: App) => {
|
||||
app.component('Test', Test)
|
||||
}
|
1
packages/integrations/vue/app.js
Normal file
1
packages/integrations/vue/app.js
Normal file
|
@ -0,0 +1 @@
|
|||
export default app => app;
|
|
@ -1,22 +1,24 @@
|
|||
import { h, createSSRApp, createApp } from 'vue';
|
||||
import { h, Teleport, defineComponent } from 'vue';
|
||||
import StaticHtml from './static-html.js';
|
||||
|
||||
export default (element) =>
|
||||
(Component, props, slotted, { client }) => {
|
||||
(Component, props, slotted) => {
|
||||
delete props['class'];
|
||||
if (!element.hasAttribute('ssr')) return;
|
||||
|
||||
// Expose name on host component for Vue devtools
|
||||
const name = Component.name ? `${Component.name} Host` : undefined;
|
||||
const slots = {};
|
||||
const { addChild } = globalThis['@astrojs/vue']
|
||||
for (const [key, value] of Object.entries(slotted)) {
|
||||
slots[key] = () => h(StaticHtml, { value, name: key === 'default' ? undefined : key });
|
||||
}
|
||||
if (client === 'only') {
|
||||
const app = createApp({ name, render: () => h(Component, props, slots) });
|
||||
app.mount(element, false);
|
||||
} else {
|
||||
const app = createSSRApp({ name, render: () => h(Component, props, slots) });
|
||||
app.mount(element, true);
|
||||
}
|
||||
// h(Teleport, { to: element }, ["AHHHHHH"])
|
||||
let host = defineComponent({
|
||||
name,
|
||||
setup() {
|
||||
return () => h(Component, props, slots)
|
||||
}
|
||||
});
|
||||
addChild(host)
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { h, createSSRApp } from 'vue';
|
||||
import { renderToString } from 'vue/server-renderer';
|
||||
import StaticHtml from './static-html.js';
|
||||
import setup from 'virtual:@astrojs/vue/app';
|
||||
|
||||
function check(Component) {
|
||||
return !!Component['ssrRender'];
|
||||
|
@ -12,6 +13,7 @@ async function renderToStaticMarkup(Component, props, slotted) {
|
|||
slots[key] = () => h(StaticHtml, { value, name: key === 'default' ? undefined : key });
|
||||
}
|
||||
const app = createSSRApp({ render: () => h(Component, props, slots) });
|
||||
setup(app)
|
||||
const html = await renderToString(app);
|
||||
return { html };
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ import type { Options } from '@vitejs/plugin-vue';
|
|||
import vue from '@vitejs/plugin-vue';
|
||||
import type { AstroIntegration, AstroRenderer } from 'astro';
|
||||
|
||||
function getRenderer(): AstroRenderer {
|
||||
function getRenderer(appEntrypoint?: string): AstroRenderer {
|
||||
return {
|
||||
name: '@astrojs/vue',
|
||||
clientEntrypoint: '@astrojs/vue/client.js',
|
||||
serverEntrypoint: '@astrojs/vue/server.js',
|
||||
appEntrypoint,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,12 +24,32 @@ function getViteConfiguration(options?: Options) {
|
|||
};
|
||||
}
|
||||
|
||||
export default function (options?: Options): AstroIntegration {
|
||||
export default function (options?: Options & { appEntrypoint?: string }): AstroIntegration {
|
||||
return {
|
||||
name: '@astrojs/vue',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ addRenderer, updateConfig }) => {
|
||||
addRenderer(getRenderer());
|
||||
'astro:config:setup': ({ addRenderer, updateConfig, injectScript }) => {
|
||||
injectScript('before-hydration', `import { h, Fragment, createApp } from 'vue';
|
||||
import setup from "virtual:@astrojs/vue/app";
|
||||
|
||||
const el = document.createElement('astro-app');
|
||||
el.setAttribute('renderer', '@astrojs/vue');
|
||||
document.body.appendChild(el);
|
||||
|
||||
const app = createApp({
|
||||
setup: () => {
|
||||
console.log('setup');
|
||||
const children = ref([]);
|
||||
return () => h(Fragment, {}, [])
|
||||
}
|
||||
});
|
||||
setup(app);
|
||||
app.mount(el, false)
|
||||
|
||||
globalThis['@astrojs/preact'] = {
|
||||
addChild
|
||||
}`)
|
||||
addRenderer(getRenderer(options?.appEntrypoint));
|
||||
updateConfig({ vite: getViteConfiguration(options) });
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue