mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 17:07:22 +00:00
Merge branch 'main' of github.com:nuxt/nuxt3 into main
This commit is contained in:
commit
b4251b1389
@ -1,25 +1,22 @@
|
|||||||
import { Ref, toRef, onMounted, watch, getCurrentInstance, onUnmounted } from 'vue'
|
import { Ref, ref, toRef, onMounted, watch, getCurrentInstance, onUnmounted } from 'vue'
|
||||||
import { Nuxt, useNuxt } from 'nuxt/app'
|
import { Nuxt, useNuxt } from 'nuxt/app'
|
||||||
import { $fetch } from 'ohmyfetch'
|
|
||||||
import { useData } from './data'
|
import { useData } from './data'
|
||||||
|
|
||||||
export type HTTPRequest = string | { method: string, url: string }
|
export type AsyncDataFn<T> = (ctx?: Nuxt) => Promise<T>
|
||||||
export type FetchRequest<T> = HTTPRequest | ((ctx: Nuxt) => HTTPRequest | Promise<T>)
|
|
||||||
|
|
||||||
export interface FetchOptions {
|
export interface AsyncDataOptions {
|
||||||
server?: boolean
|
server?: boolean
|
||||||
defer?: boolean
|
defer?: boolean
|
||||||
fetcher?: Function
|
|
||||||
key?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FetchObj<T> {
|
export interface AsyncDataObj<T> {
|
||||||
data: Ref<T>
|
data: Ref<T>
|
||||||
fetch: Function
|
pending: Ref<boolean>
|
||||||
|
refresh: Function
|
||||||
error?: any
|
error?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFetch (defaults?: FetchOptions) {
|
export function useAsyncData (defaults?: AsyncDataOptions) {
|
||||||
const nuxt = useNuxt()
|
const nuxt = useNuxt()
|
||||||
const vm = getCurrentInstance()
|
const vm = getCurrentInstance()
|
||||||
|
|
||||||
@ -40,31 +37,32 @@ export function useFetch (defaults?: FetchOptions) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return async function fetch<T = any> (request: FetchRequest<T>, options?: FetchOptions): Promise<FetchObj<T>> {
|
return async function asyncData<T = any> (handler: AsyncDataFn<T>, options?: AsyncDataOptions): Promise<AsyncDataObj<T>> {
|
||||||
|
if (typeof handler !== 'function') {
|
||||||
|
throw new TypeError('asyncData handler must be a function')
|
||||||
|
}
|
||||||
options = {
|
options = {
|
||||||
server: true,
|
server: true,
|
||||||
defer: false,
|
defer: false,
|
||||||
fetcher: globalThis.$fetch || $fetch,
|
|
||||||
...defaults,
|
...defaults,
|
||||||
...options
|
...options
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = String(dataRef++)
|
const key = String(dataRef++)
|
||||||
|
const pending = ref(true)
|
||||||
|
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
const _request = typeof request === 'function'
|
pending.value = true
|
||||||
? request(nuxt)
|
const _handler = handler(nuxt)
|
||||||
: request
|
|
||||||
|
|
||||||
if (_request instanceof Promise) {
|
if (_handler instanceof Promise) {
|
||||||
// Let user resolve if request is promise
|
// Let user resolve if request is promise
|
||||||
data[key] = await _request
|
// TODO: handle error
|
||||||
} else if (_request && (typeof _request === 'string' || _request.url)) {
|
data[key] = await _handler
|
||||||
// Make HTTP request when request is string (url) or { url, ...opts }
|
pending.value = false
|
||||||
data[key] = await options.fetcher(_request)
|
|
||||||
} else {
|
} else {
|
||||||
// Invalid request
|
// Invalid request
|
||||||
throw new Error('Invalid fetch request: ' + _request)
|
throw new TypeError('Invalid asyncData handler: ' + _handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +71,9 @@ export function useFetch (defaults?: FetchOptions) {
|
|||||||
// Client side
|
// Client side
|
||||||
if (process.client) {
|
if (process.client) {
|
||||||
// 1. Hydration (server: true): no fetch
|
// 1. Hydration (server: true): no fetch
|
||||||
|
if (nuxt.isHydrating && options.server) {
|
||||||
|
pending.value = false
|
||||||
|
}
|
||||||
// 2. Initial load (server: false): fetch on mounted
|
// 2. Initial load (server: false): fetch on mounted
|
||||||
if (nuxt.isHydrating && !options.server) {
|
if (nuxt.isHydrating && !options.server) {
|
||||||
// Fetch on mounted (initial load or deferred fetch)
|
// Fetch on mounted (initial load or deferred fetch)
|
||||||
@ -86,10 +87,8 @@ export function useFetch (defaults?: FetchOptions) {
|
|||||||
await fetch()
|
await fetch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Watch request
|
// Watch handler
|
||||||
if (typeof request === 'function') {
|
watch(handler.bind(null, nuxt), fetch)
|
||||||
watch(request, fetch)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server side
|
// Server side
|
||||||
@ -99,7 +98,8 @@ export function useFetch (defaults?: FetchOptions) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
data: toRef<any, string>(data, key),
|
data: toRef<any, string>(data, key),
|
||||||
fetch
|
pending,
|
||||||
|
refresh: fetch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
export { useFetch } from './fetch'
|
export { useAsyncData } from './asyncData'
|
||||||
export { useData } from './data'
|
export { useData } from './data'
|
||||||
export { useHydration } from './hydrate'
|
export { useHydration } from './hydrate'
|
||||||
|
@ -51,11 +51,13 @@ export function createNuxt (options: CreateOptions) {
|
|||||||
|
|
||||||
nuxt.provide = (name: string, value: any) => {
|
nuxt.provide = (name: string, value: any) => {
|
||||||
const $name = '$' + name
|
const $name = '$' + name
|
||||||
defineGetter(nuxt.app, $name, value)
|
defineGetter(nuxt, $name, value)
|
||||||
defineGetter(nuxt.app.config.globalProperties, $name, value)
|
defineGetter(nuxt.app.config.globalProperties, $name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
nuxt.provide('nuxt', nuxt)
|
// Inject $nuxt
|
||||||
|
defineGetter(nuxt.app, '$nuxt', nuxt)
|
||||||
|
defineGetter(nuxt.app.config.globalProperties, '$nuxt', nuxt)
|
||||||
|
|
||||||
// Expose nuxt to the renderContext
|
// Expose nuxt to the renderContext
|
||||||
if (nuxt.ssrContext) {
|
if (nuxt.ssrContext) {
|
||||||
|
6
packages/nuxt3/src/app/pages/404.vue
Normal file
6
packages/nuxt3/src/app/pages/404.vue
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- TODO: Move this page to @nuxt/nice -->
|
||||||
|
404 | Page Not Found
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -13,11 +13,6 @@ import routes from '~build/routes'
|
|||||||
export default <Plugin> function router (nuxt) {
|
export default <Plugin> function router (nuxt) {
|
||||||
const { app } = nuxt
|
const { app } = nuxt
|
||||||
|
|
||||||
// TODO: move this outside this plugin
|
|
||||||
if (!routes.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
app.component('NuxtPage', NuxtPage)
|
app.component('NuxtPage', NuxtPage)
|
||||||
app.component('NuxtLink', RouterLink)
|
app.component('NuxtLink', RouterLink)
|
||||||
|
|
||||||
|
@ -43,6 +43,16 @@ export async function createApp (
|
|||||||
if (app.pages) {
|
if (app.pages) {
|
||||||
app.routes.push(...(await resolvePagesRoutes(builder, app)))
|
app.routes.push(...(await resolvePagesRoutes(builder, app)))
|
||||||
}
|
}
|
||||||
|
// Add 404 page is not added
|
||||||
|
const page404 = app.routes.find(route => route.name === '404')
|
||||||
|
if (!page404) {
|
||||||
|
app.routes.push({
|
||||||
|
name: '404',
|
||||||
|
path: '/:catchAll(.*)*',
|
||||||
|
file: resolve(nuxt.options.appDir, 'pages/404.vue'),
|
||||||
|
children: []
|
||||||
|
})
|
||||||
|
}
|
||||||
// TODO: Hook to extend routes
|
// TODO: Hook to extend routes
|
||||||
app.templates.routes = serializeRoutes(app.routes)
|
app.templates.routes = serializeRoutes(app.routes)
|
||||||
|
|
||||||
@ -69,7 +79,7 @@ function formatRoute (route: NuxtRoute) {
|
|||||||
name: route.name,
|
name: route.name,
|
||||||
path: route.path,
|
path: route.path,
|
||||||
children: route.children.map(formatRoute),
|
children: route.children.map(formatRoute),
|
||||||
// TODO: avoid exposing to prod
|
// TODO: avoid exposing to prod, using process.env.NODE_ENV ?
|
||||||
__file: route.file,
|
__file: route.file,
|
||||||
component: `{() => import('${route.file}' /* webpackChunkName: '${route.name}' */)}`
|
component: `{() => import('${route.file}' /* webpackChunkName: '${route.name}' */)}`
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ function normalizeConfig (_options: CliConfiguration) {
|
|||||||
|
|
||||||
// Append ignorePrefix glob to ignore
|
// Append ignorePrefix glob to ignore
|
||||||
if (typeof options.ignorePrefix === 'string') {
|
if (typeof options.ignorePrefix === 'string') {
|
||||||
options.ignore.push(`**/${options.ignorePrefix}*.*`)
|
options.ignore.push(`${options.ignorePrefix}*`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compression middleware legacy
|
// Compression middleware legacy
|
||||||
|
Loading…
Reference in New Issue
Block a user