mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-18 09:25:54 +00:00
feat(app): make asyncData
working with <script setup nuxt>
(#220)
This commit is contained in:
parent
77e489aae3
commit
11a5a3e14f
@ -4,7 +4,7 @@ Nuxt provides `asyncData` to handle data fetching within you application.
|
|||||||
|
|
||||||
## `asyncData`
|
## `asyncData`
|
||||||
|
|
||||||
Within your pages and components you can use `asyncData` to get access to data that resolves asynchronously. (This helper only works within a component defined with `defineNuxtComponent`).
|
Within your pages and components you can use `asyncData` to get access to data that resolves asynchronously.
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
@ -20,6 +20,10 @@ asyncData(key: string, fn: () => Object, options?: { defer: boolean, server: boo
|
|||||||
|
|
||||||
Under the hood, `defer: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `defer: true` and implementing a loading state instead for a snappier user experience.
|
Under the hood, `defer: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `defer: true` and implementing a loading state instead for a snappier user experience.
|
||||||
|
|
||||||
|
This helper only works with:
|
||||||
|
- a component defined with `defineNuxtComponent`
|
||||||
|
- `<script setup nuxt>` syntax block
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
@ -39,3 +43,17 @@ export default defineNuxtComponent({
|
|||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When using with the `<script setup>` syntax, an addition attribute `nuxt` is required
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup nuxt>
|
||||||
|
import { asyncData } from '@nuxt/app'
|
||||||
|
|
||||||
|
const { data } = asyncData('time', () => $fetch('/api/count'))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
Page visits: {{ data.count }}
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
5
examples/async-data-setup/nuxt.config.ts
Normal file
5
examples/async-data-setup/nuxt.config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { defineNuxtConfig } from '@nuxt/kit'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
// vite: true
|
||||||
|
})
|
12
examples/async-data-setup/package.json
Normal file
12
examples/async-data-setup/package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "example-async-data-setup",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"nuxt3": "latest"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nu dev",
|
||||||
|
"build": "nu build",
|
||||||
|
"start": "node .output/server"
|
||||||
|
}
|
||||||
|
}
|
12
examples/async-data-setup/pages/index.vue
Normal file
12
examples/async-data-setup/pages/index.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<script nuxt setup lang="ts">
|
||||||
|
import { asyncData } from '@nuxt/app'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { data } = asyncData('time', () => $fetch('/api/count'))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
Page visits: {{ data.count }}
|
||||||
|
</div>
|
||||||
|
</template>
|
3
examples/async-data-setup/server/api/count.js
Normal file
3
examples/async-data-setup/server/api/count.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
let ctr = 0
|
||||||
|
|
||||||
|
export default () => ({ count: ++ctr })
|
@ -4,6 +4,7 @@ import vitePlugin from '@vitejs/plugin-vue'
|
|||||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||||
import { replace } from './plugins/replace'
|
import { replace } from './plugins/replace'
|
||||||
import { ViteBuildContext, ViteOptions } from './vite'
|
import { ViteBuildContext, ViteOptions } from './vite'
|
||||||
|
import { transformNuxtSetup } from './plugins/transformSetup'
|
||||||
|
|
||||||
export async function buildClient (ctx: ViteBuildContext) {
|
export async function buildClient (ctx: ViteBuildContext) {
|
||||||
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
const clientConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||||
@ -23,7 +24,8 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
plugins: [
|
plugins: [
|
||||||
replace({ 'process.env': 'import.meta.env' }),
|
replace({ 'process.env': 'import.meta.env' }),
|
||||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'client'),
|
cacheDirPlugin(ctx.nuxt.options.rootDir, 'client'),
|
||||||
vitePlugin(ctx.config.vue)
|
vitePlugin(ctx.config.vue),
|
||||||
|
transformNuxtSetup()
|
||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
middlewareMode: true
|
middlewareMode: true
|
||||||
|
31
packages/vite/src/plugins/transformSetup.ts
Normal file
31
packages/vite/src/plugins/transformSetup.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { Plugin } from 'vite'
|
||||||
|
import { getQuery } from 'ufo'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
|
||||||
|
const DEFINE_COMPONENT_VUE = '_defineComponent('
|
||||||
|
const DEFINE_COMPONENT_NUXT = '_defineNuxtComponent('
|
||||||
|
|
||||||
|
export function transformNuxtSetup () {
|
||||||
|
return <Plugin> {
|
||||||
|
name: 'nuxt:transform-setup',
|
||||||
|
transform (code, id) {
|
||||||
|
const query = getQuery(id)
|
||||||
|
if (!(id.endsWith('.vue') || (query.nuxt && query.setup && query.type === 'script'))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = code.indexOf(DEFINE_COMPONENT_VUE)
|
||||||
|
if (index < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const s = new MagicString(code)
|
||||||
|
s.overwrite(index, index + DEFINE_COMPONENT_VUE.length, DEFINE_COMPONENT_NUXT)
|
||||||
|
s.prepend('import { defineNuxtComponent as _defineNuxtComponent } from "@nuxt/app"\n')
|
||||||
|
return {
|
||||||
|
code: s.toString(),
|
||||||
|
map: s.generateMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import consola from 'consola'
|
|||||||
import { ViteBuildContext, ViteOptions } from './vite'
|
import { ViteBuildContext, ViteOptions } from './vite'
|
||||||
import { wpfs } from './utils/wpfs'
|
import { wpfs } from './utils/wpfs'
|
||||||
import { cacheDirPlugin } from './plugins/cache-dir'
|
import { cacheDirPlugin } from './plugins/cache-dir'
|
||||||
|
import { transformNuxtSetup } from './plugins/transformSetup'
|
||||||
|
|
||||||
export async function buildServer (ctx: ViteBuildContext) {
|
export async function buildServer (ctx: ViteBuildContext) {
|
||||||
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
||||||
@ -41,7 +42,8 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
cacheDirPlugin(ctx.nuxt.options.rootDir, 'server'),
|
cacheDirPlugin(ctx.nuxt.options.rootDir, 'server'),
|
||||||
vuePlugin()
|
vuePlugin(),
|
||||||
|
transformNuxtSetup()
|
||||||
]
|
]
|
||||||
} as ViteOptions)
|
} as ViteOptions)
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ import { defineBuildConfig } from 'unbuild'
|
|||||||
export default defineBuildConfig({
|
export default defineBuildConfig({
|
||||||
declaration: false,
|
declaration: false,
|
||||||
entries: [
|
entries: [
|
||||||
'src/index'
|
'src/index',
|
||||||
|
'src/loaders/nuxt-setup'
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
'@nuxt/kit',
|
'@nuxt/kit',
|
||||||
|
10
packages/webpack/src/loaders/nuxt-setup.ts
Normal file
10
packages/webpack/src/loaders/nuxt-setup.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const DEFINE_COMPONENT_VUE = '_defineComponent('
|
||||||
|
const DEFINE_COMPONENT_NUXT = '_defineNuxtComponent('
|
||||||
|
|
||||||
|
export default function NuxtSetupLoader (code: string) {
|
||||||
|
if (code && code.includes(DEFINE_COMPONENT_VUE)) {
|
||||||
|
// TODO: Add sourcemap hints
|
||||||
|
code = 'import { defineNuxtComponent as _defineNuxtComponent } from "@nuxt/app"\n' + code.replace(DEFINE_COMPONENT_VUE, DEFINE_COMPONENT_NUXT)
|
||||||
|
}
|
||||||
|
return code
|
||||||
|
}
|
17
packages/webpack/src/plugins/transform-setup.ts
Normal file
17
packages/webpack/src/plugins/transform-setup.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { getQuery } from 'ufo'
|
||||||
|
|
||||||
|
export default class NuxtSetupTransformerPlugin {
|
||||||
|
apply (compiler) {
|
||||||
|
compiler.options.module.rules.push({
|
||||||
|
include (id) {
|
||||||
|
const query = getQuery(id)
|
||||||
|
return id.endsWith('.vue') || (query.nuxt && query.setup && query.type === 'script')
|
||||||
|
},
|
||||||
|
enforce: 'post',
|
||||||
|
use: [{
|
||||||
|
ident: 'NuxtSetupTransformerPlugin',
|
||||||
|
loader: require.resolve('@nuxt/webpack-builder/dist/nuxt-setup')
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5'
|
import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5'
|
||||||
import { DefinePlugin } from 'webpack'
|
import { DefinePlugin } from 'webpack'
|
||||||
|
import NuxtSetupTransformerPlugin from '../plugins/transform-setup'
|
||||||
import VueSSRClientPlugin from '../plugins/vue/client'
|
import VueSSRClientPlugin from '../plugins/vue/client'
|
||||||
import VueSSRServerPlugin from '../plugins/vue/server'
|
import VueSSRServerPlugin from '../plugins/vue/server'
|
||||||
import { WebpackConfigContext } from '../utils/config'
|
import { WebpackConfigContext } from '../utils/config'
|
||||||
@ -26,6 +27,8 @@ export function vue (ctx: WebpackConfigContext) {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.plugins.push(new NuxtSetupTransformerPlugin())
|
||||||
|
|
||||||
// Feature flags
|
// Feature flags
|
||||||
// https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
|
// https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
|
||||||
// TODO: Provide options to toggle
|
// TODO: Provide options to toggle
|
||||||
|
@ -5957,6 +5957,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"example-async-data-setup@workspace:examples/async-data-setup":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "example-async-data-setup@workspace:examples/async-data-setup"
|
||||||
|
dependencies:
|
||||||
|
nuxt3: latest
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"example-async-data@workspace:examples/async-data":
|
"example-async-data@workspace:examples/async-data":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "example-async-data@workspace:examples/async-data"
|
resolution: "example-async-data@workspace:examples/async-data"
|
||||||
|
Loading…
Reference in New Issue
Block a user