Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/3.api/2.composables/use-cookie.md
  • Loading branch information
Ivan Bochkarev committed Jun 21, 2024
2 parents 953c96c + ae12d72 commit 14ed0e2
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 22 deletions.
8 changes: 8 additions & 0 deletions docs/3.api/2.composables/use-cookie.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ counter.value = counter.value || Math.round(Math.random() * 1000)

:link-example{to="/docs/examples/advanced/use-cookie"}

::note
Обновите значения `useCookie` вручную, когда cookies изменились, используя [`refreshCookie`](/api/utils/refresh-cookie).
::

## Параметры

Данный композабл принимает несколько опций, которые позволяют изменять поведение cookie.
Expand Down Expand Up @@ -148,6 +152,10 @@ counter.value = counter.value || Math.round(Math.random() * 1000)
- `shallow` - Будет следить за изменениями данных cookie ref только для свойств верхнего уровня.
- `false` - Не будет следить за изменениями данных cookie ref.

::note
Обновите значения `useCookie` вручную, когда cookies изменились, используя [`refreshCookie`](/api/utils/refresh-cookie).
::

**Пример 1:**

```vue
Expand Down
8 changes: 2 additions & 6 deletions packages/nuxt/src/app/components/nuxt-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import type {
} from 'vue'
import { computed, defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, resolveComponent } from 'vue'
import type { RouteLocation, RouteLocationRaw, Router, RouterLink, RouterLinkProps, useLink } from '#vue-router'
import { hasProtocol, joinURL, parseQuery, withQuery, withTrailingSlash, withoutTrailingSlash } from 'ufo'
import { hasProtocol, joinURL, parseQuery, withTrailingSlash, withoutTrailingSlash } from 'ufo'
import { preloadRouteComponents } from '../composables/preload'
import { onNuxtReady } from '../composables/ready'
import { navigateTo, useRouter } from '../composables/router'
import { navigateTo, resolveRouteObject, useRouter } from '../composables/router'
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { cancelIdleCallback, requestIdleCallback } from '../compat/idle-callback'

Expand Down Expand Up @@ -495,7 +495,3 @@ function isSlowConnection () {
if (cn && (cn.saveData || /2g/.test(cn.effectiveType))) { return true }
return false
}

function resolveRouteObject (to: Exclude<RouteLocationRaw, string>) {
return withQuery(to.path || '', to.query || {}) + (to.hash ? '#' + to.hash : '')
}
11 changes: 9 additions & 2 deletions packages/nuxt/src/app/composables/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getCurrentInstance, hasInjectionContext, inject, onScopeDispose } from 'vue'
import type { Ref } from 'vue'
import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, RouteLocationPathRaw, RouteLocationRaw, Router, useRoute as _useRoute, useRouter as _useRouter } from '#vue-router'
import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, RouteLocationRaw, Router, useRoute as _useRoute, useRouter as _useRouter } from '#vue-router'
import { sanitizeStatusCode } from 'h3'
import { hasProtocol, isScriptProtocol, joinURL, withQuery } from 'ufo'

Expand Down Expand Up @@ -120,7 +120,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
to = '/'
}

const toPath = typeof to === 'string' ? to : (withQuery((to as RouteLocationPathRaw).path || '/', to.query || {}) + (to.hash || ''))
const toPath = typeof to === 'string' ? to : 'path' in to ? resolveRouteObject(to) : useRouter().resolve(to).href

// Early open handler
if (import.meta.client && options?.open) {
Expand Down Expand Up @@ -252,3 +252,10 @@ export const setPageLayout = (layout: unknown extends PageMeta['layout'] ? strin
useRoute().meta.layout = layout as Exclude<PageMeta['layout'], Ref | false>
}
}

/**
* @internal
*/
export function resolveRouteObject (to: Exclude<RouteLocationRaw, string>) {
return withQuery(to.path || '', to.query || {}) + (to.hash || '')
}
19 changes: 19 additions & 0 deletions packages/nuxt/src/app/plugins/navigation-repaint.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineNuxtPlugin } from '../nuxt'
import { useRouter } from '../composables'

export default defineNuxtPlugin(() => {
useRouter().beforeResolve(async () => {
/**
* This gives an opportunity for the browser to repaint, acknowledging user interaction.
* It can reduce INP when navigating on prerendered routes.
*
* @see https://github.com/nuxt/nuxt/issues/26271#issuecomment-2178582037
* @see https://vercel.com/blog/demystifying-inp-new-tools-and-actionable-insights
*/
await new Promise((resolve) => {
// Ensure we always resolve, even if the animation frame never fires
setTimeout(resolve, 100)
requestAnimationFrame(() => { setTimeout(resolve, 0) })
})
})
})
5 changes: 4 additions & 1 deletion packages/nuxt/src/core/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createRouter as createRadixRouter, exportMatcher, toRouteMatcher } from
import { joinURL, withTrailingSlash } from 'ufo'
import { build, copyPublicAssets, createDevServer, createNitro, prepare, prerender, scanHandlers, writeTypes } from 'nitropack'
import type { Nitro, NitroConfig, NitroOptions } from 'nitropack'
import { findPath, logger, resolveIgnorePatterns, resolveNuxtModule, resolvePath } from '@nuxt/kit'
import { findPath, logger, resolveAlias, resolveIgnorePatterns, resolveNuxtModule, resolvePath } from '@nuxt/kit'
import escapeRE from 'escape-string-regexp'
import { defu } from 'defu'
import fsExtra from 'fs-extra'
Expand Down Expand Up @@ -218,6 +218,9 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
nitroConfig.srcDir = resolve(nuxt.options.rootDir, nuxt.options.srcDir, nitroConfig.srcDir!)
nitroConfig.ignore = [...(nitroConfig.ignore || []), ...resolveIgnorePatterns(nitroConfig.srcDir), `!${join(nuxt.options.buildDir, 'dist/client', nuxt.options.app.buildAssetsDir, '**/*')}`]

// Resolve aliases in user-provided input - so `~/server/test` will work
nitroConfig.plugins = nitroConfig.plugins?.map(plugin => plugin ? resolveAlias(plugin, nuxt.options.alias) : plugin)

// Add app manifest handler and prerender configuration
if (nuxt.options.experimental.appManifest) {
const buildId = nuxt.options.runtimeConfig.app.buildId ||= nuxt.options.buildId
Expand Down
16 changes: 11 additions & 5 deletions packages/nuxt/src/core/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ async function initNuxt (nuxt: Nuxt) {
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(() => ({}) as PackageJson)
const dependencies = new Set([...Object.keys(packageJSON.dependencies || {}), ...Object.keys(packageJSON.devDependencies || {})])
const paths = Object.fromEntries(await Promise.all(coreTypePackages.map(async (pkg) => {
// ignore packages that exist in `package.json` as these can be resolved by TypeScript
if (dependencies.has(pkg) && !(pkg in nightlies)) { return [] }

const [_pkg = pkg, _subpath] = /^[^@]+\//.test(pkg) ? pkg.split('/') : [pkg]
const subpath = _subpath ? '/' + _subpath : ''

// ignore packages that exist in `package.json` as these can be resolved by TypeScript
if (dependencies.has(_pkg) && !(_pkg in nightlies)) { return [] }

async function resolveTypePath (path: string) {
try {
const r = await _resolvePath(path, { url: nuxt.options.modulesDir, conditions: ['types', 'import', 'require'] })
Expand All @@ -120,14 +120,14 @@ async function initNuxt (nuxt: Nuxt) {

// deduplicate types for nightly releases
if (_pkg in nightlies) {
const nightly = nightlies[pkg as keyof typeof nightlies]
const nightly = nightlies[_pkg as keyof typeof nightlies]
const path = await resolveTypePath(nightly + subpath)
if (path) {
return [[pkg, [path]], [nightly + subpath, [path]]]
}
}

const path = await resolveTypePath(pkg + subpath)
const path = await resolveTypePath(_pkg + subpath)
if (path) {
return [[pkg, [path]]]
}
Expand Down Expand Up @@ -532,6 +532,12 @@ async function initNuxt (nuxt: Nuxt) {
}
}

if (nuxt.options.experimental.navigationRepaint) {
addPlugin({
src: resolve(nuxt.options.appDir, 'plugins/navigation-repaint.client'),
})
}

nuxt.hooks.hook('builder:watch', (event, relativePath) => {
const path = resolve(nuxt.options.srcDir, relativePath)
// Local module patterns
Expand Down
6 changes: 6 additions & 0 deletions packages/nuxt/src/pages/build.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare module '#build/router.options' {
import type { RouterOptions } from '@nuxt/schema'

const _default: RouterOptions
export default _default
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { defineNuxtPlugin } from '#app/nuxt'
import { prerenderRoutes } from '#app/composables/ssr'
// @ts-expect-error virtual file
import _routes from '#build/routes'
// @ts-expect-error virtual file
import routerOptions from '#build/router.options'

let routes: string[]
Expand Down
3 changes: 1 addition & 2 deletions packages/nuxt/src/pages/runtime/plugins/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { navigateTo } from '#app/composables/router'
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'
// @ts-expect-error virtual file
import _routes from '#build/routes'
// @ts-expect-error virtual file
import routerOptions from '#build/router.options'
// @ts-expect-error virtual file
import { globalMiddleware, namedMiddleware } from '#build/middleware'
Expand Down Expand Up @@ -67,7 +66,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
: createMemoryHistory(routerBase)
)

const routes = routerOptions.routes?.(_routes) ?? _routes
const routes = routerOptions.routes ? await routerOptions.routes(_routes) ?? _routes : _routes

let startPosition: Parameters<RouterScrollBehavior>[2] | null

Expand Down
4 changes: 4 additions & 0 deletions packages/nuxt/test/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ describe('resolveApp', () => {
"mode": "client",
"src": "<repoRoot>/packages/nuxt/src/app/plugins/payload.client.ts",
},
{
"mode": "client",
"src": "<repoRoot>/packages/nuxt/src/app/plugins/navigation-repaint.client.ts",
},
{
"mode": "client",
"src": "<repoRoot>/packages/nuxt/src/app/plugins/check-outdated-build.client.ts",
Expand Down
6 changes: 5 additions & 1 deletion packages/nuxt/test/nuxt-link.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import type { RouteLocation } from 'vue-router'
import type { RouteLocation, RouteLocationRaw } from 'vue-router'
import { withQuery } from 'ufo'
import type { NuxtLinkOptions, NuxtLinkProps } from '../src/app/components/nuxt-link'
import { defineNuxtLink } from '../src/app/components/nuxt-link'
import { useRuntimeConfig } from '../src/app/nuxt'
Expand All @@ -25,6 +26,9 @@ vi.mock('vue', async () => {

// Mocks Nuxt `useRouter()`
vi.mock('../src/app/composables/router', () => ({
resolveRouteObject (to: Exclude<RouteLocationRaw, string>) {
return withQuery(to.path || '', to.query || {}) + (to.hash || '')
},
useRouter: () => ({
resolve: (route: string | RouteLocation & { to?: string }): Partial<RouteLocation> & { href?: string } => {
if (typeof route === 'string') {
Expand Down
6 changes: 3 additions & 3 deletions packages/schema/src/config/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { existsSync } from 'node:fs'
import { readdir } from 'node:fs/promises'
import { defineUntypedSchema } from 'untyped'
import { join, relative, resolve } from 'pathe'
import { basename, join, relative, resolve } from 'pathe'
import { isDebug, isDevelopment, isTest } from 'std-env'
import { defu } from 'defu'
import { findWorkspaceDir } from 'pkg-types'
Expand Down Expand Up @@ -420,8 +420,8 @@ export default defineUntypedSchema({
'@': srcDir,
'~~': rootDir,
'@@': rootDir,
[assetsDir]: join(srcDir, assetsDir),
[publicDir]: join(srcDir, publicDir),
[basename(assetsDir)]: join(srcDir, assetsDir),
[basename(publicDir)]: join(srcDir, publicDir),
...val,
}
},
Expand Down
8 changes: 8 additions & 0 deletions packages/schema/src/config/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,5 +417,13 @@ export default defineUntypedSchema({
* @type {boolean}
*/
clientNodeCompat: false,

/**
* Wait for a single animation frame before navigation, which gives an opportunity
* for the browser to repaint, acknowledging user interaction.
*
* It can reduce INP when navigating on prerendered routes.
*/
navigationRepaint: true,
},
})
2 changes: 1 addition & 1 deletion packages/schema/src/types/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { RouterHistory, RouterOptions as _RouterOptions } from 'vue-router'

export type RouterOptions = Partial<Omit<_RouterOptions, 'history' | 'routes'>> & {
history?: (baseURL?: string) => RouterHistory
routes?: (_routes: _RouterOptions['routes']) => _RouterOptions['routes']
routes?: (_routes: _RouterOptions['routes']) => _RouterOptions['routes'] | Promise<_RouterOptions['routes']>
hashMode?: boolean
scrollBehaviorType?: 'smooth' | 'auto'
}
Expand Down

0 comments on commit 14ed0e2

Please sign in to comment.