mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat(nuxt3): create root component (#750)
This commit is contained in:
parent
b35b111032
commit
9cb9bb651e
@ -32,7 +32,7 @@ export default () => {
|
||||
}
|
||||
```
|
||||
|
||||
```vue [pages/index.vue]
|
||||
```vue [app.vue]
|
||||
<script setup>
|
||||
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
|
||||
</script>
|
||||
@ -68,7 +68,7 @@ Available options:
|
||||
|
||||
### Example
|
||||
|
||||
```vue [pages/index.vue]
|
||||
```vue [app.vue]
|
||||
<script setup>
|
||||
const { data } = await useFetch('/api/count')
|
||||
</script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "example-pages",
|
||||
"name": "example-use-async-data",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest"
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "example-meta",
|
||||
"name": "example-use-meta",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest"
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "example-wasm",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nuxt dev",
|
||||
"build": "nuxt build",
|
||||
"start": "node .output/server/index.mjs"
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "example-async-data",
|
||||
"name": "example-with-pages",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest"
|
@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
Hello Nuxt+Vite!
|
||||
</div>
|
||||
</template>
|
@ -1,5 +0,0 @@
|
||||
import { defineNuxtConfig } from 'nuxt3'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
vite: true
|
||||
})
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "example-with-vue-content-loader",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest",
|
||||
"vue": "^3",
|
||||
"vue-content-loader": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nuxt dev",
|
||||
"build": "nuxt build",
|
||||
"start": "node .output/server/index.mjs"
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<div class="profile">
|
||||
<ContentLoader v-if="pending" width="400" height="60">
|
||||
<rect
|
||||
x="70"
|
||||
y="15"
|
||||
rx="4"
|
||||
ry="4"
|
||||
width="117"
|
||||
height="6.4"
|
||||
/>
|
||||
<rect
|
||||
x="70"
|
||||
y="35"
|
||||
rx="3"
|
||||
ry="3"
|
||||
width="85"
|
||||
height="6.4"
|
||||
/>
|
||||
<circle cx="30" cy="30" r="30" />
|
||||
</ContentLoader>
|
||||
<div v-else>
|
||||
<img :src="data.avatar" height="55" width="55">
|
||||
<div>
|
||||
{{ data.text }}
|
||||
<br>
|
||||
{{ data.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ContentLoader } from 'vue-content-loader'
|
||||
export default defineNuxtComponent({
|
||||
components: { ContentLoader },
|
||||
setup () {
|
||||
const { data, pending } = useAsyncData(
|
||||
'time',
|
||||
() =>
|
||||
new Promise(resolve =>
|
||||
setTimeout(
|
||||
() =>
|
||||
resolve({
|
||||
text: 'finally done',
|
||||
avatar:
|
||||
'https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=256&h=256&q=80'
|
||||
}),
|
||||
2500
|
||||
)
|
||||
),
|
||||
{ defer: true, server: false }
|
||||
)
|
||||
|
||||
return {
|
||||
data,
|
||||
pending
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.profile {
|
||||
width: 400px;
|
||||
height: 60px;
|
||||
}
|
||||
.profile img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.profile > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "example-with-vite",
|
||||
"name": "example-with-wasm",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nuxt3": "latest"
|
@ -49,7 +49,8 @@ export interface NuxtPlugin {
|
||||
}
|
||||
|
||||
export interface NuxtApp {
|
||||
main?: string
|
||||
mainComponent?: string
|
||||
rootComponent?: string
|
||||
dir: string
|
||||
extensions: string[]
|
||||
plugins: NuxtPlugin[]
|
||||
|
5
packages/nuxt3/src/app/components/nuxt-root.vue
Normal file
5
packages/nuxt3/src/app/components/nuxt-root.vue
Normal file
@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<Suspense>
|
||||
<App />
|
||||
</Suspense>
|
||||
</template>
|
@ -4,7 +4,9 @@ import '#build/css'
|
||||
// @ts-ignore
|
||||
import _plugins from '#build/plugins'
|
||||
// @ts-ignore
|
||||
import App from '#build/app'
|
||||
import RootComponent from '#build/root-component.mjs'
|
||||
// @ts-ignore
|
||||
import AppComponent from '#build/app-component.mjs'
|
||||
|
||||
let entry: Function
|
||||
|
||||
@ -12,7 +14,8 @@ const plugins = normalizePlugins(_plugins)
|
||||
|
||||
if (process.server) {
|
||||
entry = async function createNuxtAppServer (ssrContext: CreateOptions['ssrContext'] = {}) {
|
||||
const app = createApp(App)
|
||||
const app = createApp(RootComponent)
|
||||
app.component('App', AppComponent)
|
||||
|
||||
const nuxt = createNuxtApp({ app, ssrContext })
|
||||
|
||||
@ -35,7 +38,8 @@ if (process.client) {
|
||||
|
||||
entry = async function initApp () {
|
||||
const isSSR = Boolean(window.__NUXT__?.serverRendered)
|
||||
const app = isSSR ? createSSRApp(App) : createApp(App)
|
||||
const app = isSSR ? createSSRApp(RootComponent) : createApp(RootComponent)
|
||||
app.component('App', AppComponent)
|
||||
|
||||
const nuxt = createNuxtApp({ app })
|
||||
|
||||
|
@ -8,10 +8,18 @@ type TemplateContext = {
|
||||
app: NuxtApp;
|
||||
}
|
||||
|
||||
export const appTemplate = {
|
||||
filename: 'app.mjs',
|
||||
// TODO: Use an alias
|
||||
export const appComponentTemplate = {
|
||||
filename: 'app-component.mjs',
|
||||
getContents (ctx: TemplateContext) {
|
||||
return `export { default } from '${ctx.app.main}'`
|
||||
return `export { default } from '${ctx.app.mainComponent}'`
|
||||
}
|
||||
}
|
||||
// TODO: Use an alias
|
||||
export const rootComponentTemplate = {
|
||||
filename: 'root-component.mjs',
|
||||
getContents (ctx: TemplateContext) {
|
||||
return `export { default } from '${ctx.app.rootComponent}'`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,13 +59,16 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
||||
}
|
||||
|
||||
// Resolve main (app.vue)
|
||||
if (!app.main) {
|
||||
app.main = tryResolvePath('~/App', resolveOptions) || tryResolvePath('~/app', resolveOptions)
|
||||
if (!app.mainComponent) {
|
||||
app.mainComponent = tryResolvePath('~/App', resolveOptions) || tryResolvePath('~/app', resolveOptions)
|
||||
}
|
||||
if (!app.main) {
|
||||
app.main = resolve(nuxt.options.appDir, 'components/nuxt-welcome.vue')
|
||||
if (!app.mainComponent) {
|
||||
app.mainComponent = resolve(nuxt.options.appDir, 'components/nuxt-welcome.vue')
|
||||
}
|
||||
|
||||
// Default root component
|
||||
app.rootComponent = resolve(nuxt.options.appDir, 'components/nuxt-root.vue')
|
||||
|
||||
// Resolve plugins
|
||||
app.plugins = [
|
||||
...nuxt.options.plugins,
|
||||
|
@ -15,7 +15,7 @@ export async function build (nuxt: Nuxt) {
|
||||
nuxt.hook('builder:watch', async (event, path) => {
|
||||
if (event !== 'change' && /app|plugins/i.test(path)) {
|
||||
if (path.match(/app/i)) {
|
||||
app.main = null
|
||||
app.mainComponent = null
|
||||
}
|
||||
await generateApp(nuxt, app)
|
||||
}
|
||||
|
@ -23,10 +23,12 @@ export default defineNuxtModule({
|
||||
}
|
||||
})
|
||||
|
||||
// Add default layout for pages
|
||||
nuxt.hook('app:resolve', (app) => {
|
||||
if (app.main.includes('nuxt-welcome')) {
|
||||
app.main = resolve(runtimeDir, 'app.vue')
|
||||
// Remove default root with Suspense
|
||||
app.rootComponent = resolve(runtimeDir, 'root.vue')
|
||||
// Add default layout for pages
|
||||
if (app.mainComponent.includes('nuxt-welcome')) {
|
||||
app.mainComponent = resolve(runtimeDir, 'app.vue')
|
||||
}
|
||||
})
|
||||
|
||||
|
3
packages/nuxt3/src/pages/runtime/root.vue
Normal file
3
packages/nuxt3/src/pages/runtime/root.vue
Normal file
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<App />
|
||||
</template>
|
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<NuxtPage />
|
||||
<img src="~/assets/logo.svg">
|
||||
<br>
|
||||
Hello Nuxt 3
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default defineNuxtComponent({
|
||||
})
|
||||
</script>
|
||||
|
@ -1,12 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<img src="~/assets/logo.svg">
|
||||
<br>
|
||||
Hello Nuxt 3
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default defineNuxtComponent({
|
||||
})
|
||||
</script>
|
49
yarn.lock
49
yarn.lock
@ -9199,14 +9199,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"example-async-data@workspace:examples/async-data":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-async-data@workspace:examples/async-data"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-hello-world@workspace:examples/hello-world":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-hello-world@workspace:examples/hello-world"
|
||||
@ -9215,17 +9207,9 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-meta@workspace:examples/meta":
|
||||
"example-use-async-data@workspace:examples/use-async-data":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-meta@workspace:examples/meta"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-pages@workspace:examples/pages":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-pages@workspace:examples/pages"
|
||||
resolution: "example-use-async-data@workspace:examples/use-async-data"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
@ -9239,17 +9223,17 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-use-state@workspace:examples/use-state":
|
||||
"example-use-meta@workspace:examples/use-meta":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-use-state@workspace:examples/use-state"
|
||||
resolution: "example-use-meta@workspace:examples/use-meta"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-wasm@workspace:examples/wasm":
|
||||
"example-use-state@workspace:examples/use-state":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-wasm@workspace:examples/wasm"
|
||||
resolution: "example-use-state@workspace:examples/use-state"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
@ -9271,21 +9255,19 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-with-vite@workspace:examples/with-vite":
|
||||
"example-with-pages@workspace:examples/with-pages":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-with-vite@workspace:examples/with-vite"
|
||||
resolution: "example-with-pages@workspace:examples/with-pages"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"example-with-vue-content-loader@workspace:examples/with-vue-content-loader":
|
||||
"example-with-wasm@workspace:examples/with-wasm":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "example-with-vue-content-loader@workspace:examples/with-vue-content-loader"
|
||||
resolution: "example-with-wasm@workspace:examples/with-wasm"
|
||||
dependencies:
|
||||
nuxt3: latest
|
||||
vue: ^3
|
||||
vue-content-loader: ^2.0.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -19251,15 +19233,6 @@ fsevents@~2.3.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vue-content-loader@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "vue-content-loader@npm:2.0.0"
|
||||
peerDependencies:
|
||||
vue: ^3
|
||||
checksum: 92efefe9e2aa4760a1e60ecfa2358bbc9a613f89a0e90a52cecef5a315ac247cb439d0cff58cab6891ef9fec900a9e232b96ed8d7e7dc051b00eb5f0ee0bd407
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vue-eslint-parser@npm:^7.10.0":
|
||||
version: 7.11.0
|
||||
resolution: "vue-eslint-parser@npm:7.11.0"
|
||||
@ -19405,7 +19378,7 @@ fsevents@~2.3.2:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vue@npm:3.2.20, vue@npm:^3, vue@npm:^3.2.20":
|
||||
"vue@npm:3.2.20, vue@npm:^3.2.20":
|
||||
version: 3.2.20
|
||||
resolution: "vue@npm:3.2.20"
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user