Merge branch 'main' of github.com:nuxt/nuxt3 into main

This commit is contained in:
Pooya Parsa 2021-02-09 15:56:21 +01:00
commit b4251b1389
7 changed files with 49 additions and 36 deletions

View File

@ -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 { $fetch } from 'ohmyfetch'
import { useData } from './data'
export type HTTPRequest = string | { method: string, url: string }
export type FetchRequest<T> = HTTPRequest | ((ctx: Nuxt) => HTTPRequest | Promise<T>)
export type AsyncDataFn<T> = (ctx?: Nuxt) => Promise<T>
export interface FetchOptions {
export interface AsyncDataOptions {
server?: boolean
defer?: boolean
fetcher?: Function
key?: string
}
export interface FetchObj<T> {
export interface AsyncDataObj<T> {
data: Ref<T>
fetch: Function
pending: Ref<boolean>
refresh: Function
error?: any
}
export function useFetch (defaults?: FetchOptions) {
export function useAsyncData (defaults?: AsyncDataOptions) {
const nuxt = useNuxt()
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 = {
server: true,
defer: false,
fetcher: globalThis.$fetch || $fetch,
...defaults,
...options
}
const key = String(dataRef++)
const pending = ref(true)
const fetch = async () => {
const _request = typeof request === 'function'
? request(nuxt)
: request
pending.value = true
const _handler = handler(nuxt)
if (_request instanceof Promise) {
if (_handler instanceof Promise) {
// Let user resolve if request is promise
data[key] = await _request
} else if (_request && (typeof _request === 'string' || _request.url)) {
// Make HTTP request when request is string (url) or { url, ...opts }
data[key] = await options.fetcher(_request)
// TODO: handle error
data[key] = await _handler
pending.value = false
} else {
// 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
if (process.client) {
// 1. Hydration (server: true): no fetch
if (nuxt.isHydrating && options.server) {
pending.value = false
}
// 2. Initial load (server: false): fetch on mounted
if (nuxt.isHydrating && !options.server) {
// Fetch on mounted (initial load or deferred fetch)
@ -86,10 +87,8 @@ export function useFetch (defaults?: FetchOptions) {
await fetch()
}
}
// Watch request
if (typeof request === 'function') {
watch(request, fetch)
}
// Watch handler
watch(handler.bind(null, nuxt), fetch)
}
// Server side
@ -99,7 +98,8 @@ export function useFetch (defaults?: FetchOptions) {
return {
data: toRef<any, string>(data, key),
fetch
pending,
refresh: fetch
}
}
}

View File

@ -1,3 +1,3 @@
export { useFetch } from './fetch'
export { useAsyncData } from './asyncData'
export { useData } from './data'
export { useHydration } from './hydrate'

View File

@ -51,11 +51,13 @@ export function createNuxt (options: CreateOptions) {
nuxt.provide = (name: string, value: any) => {
const $name = '$' + name
defineGetter(nuxt.app, $name, value)
defineGetter(nuxt, $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
if (nuxt.ssrContext) {

View File

@ -0,0 +1,6 @@
<template>
<div>
<!-- TODO: Move this page to @nuxt/nice -->
404 | Page Not Found
</div>
</template>

View File

@ -13,11 +13,6 @@ import routes from '~build/routes'
export default <Plugin> function router (nuxt) {
const { app } = nuxt
// TODO: move this outside this plugin
if (!routes.length) {
return
}
app.component('NuxtPage', NuxtPage)
app.component('NuxtLink', RouterLink)

View File

@ -43,6 +43,16 @@ export async function createApp (
if (app.pages) {
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
app.templates.routes = serializeRoutes(app.routes)
@ -69,7 +79,7 @@ function formatRoute (route: NuxtRoute) {
name: route.name,
path: route.path,
children: route.children.map(formatRoute),
// TODO: avoid exposing to prod
// TODO: avoid exposing to prod, using process.env.NODE_ENV ?
__file: route.file,
component: `{() => import('${route.file}' /* webpackChunkName: '${route.name}' */)}`
}

View File

@ -299,7 +299,7 @@ function normalizeConfig (_options: CliConfiguration) {
// Append ignorePrefix glob to ignore
if (typeof options.ignorePrefix === 'string') {
options.ignore.push(`**/${options.ignorePrefix}*.*`)
options.ignore.push(`${options.ignorePrefix}*`)
}
// Compression middleware legacy