mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-16 21:58:19 +00:00
Merge branch 'nuxt:main' into main
This commit is contained in:
commit
f38cf6b65f
2
.github/workflows/benchmark.yml
vendored
2
.github/workflows/benchmark.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
run: pnpm build
|
||||
|
||||
- name: Run benchmarks
|
||||
uses: CodSpeedHQ/action@0b631f8998f2389eb5144632b6f9f8fabd33a86e # v2.4.1
|
||||
uses: CodSpeedHQ/action@f11c406b8c87cda176ff341ed4925bc98086f6d1 # v2.4.2
|
||||
with:
|
||||
run: pnpm vitest bench
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
|
@ -5,7 +5,7 @@
|
||||
<p>
|
||||
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/v/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Version"></a>
|
||||
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/dm/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Downloads"></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/github/license/nuxt/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="License"></a>
|
||||
<a href="https://github.com/nuxt/nuxt/tree/main/LICENSE"><img src="https://img.shields.io/github/license/nuxt/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="License"></a>
|
||||
<a href="https://nuxt.com"><img src="https://img.shields.io/badge/Nuxt%20Docs-18181B?logo=nuxt.js" alt="Website"></a>
|
||||
<a href="https://chat.nuxt.dev"><img src="https://img.shields.io/badge/Nuxt%20Discord-18181B?logo=discord" alt="Discord"></a>
|
||||
</p>
|
||||
@ -120,4 +120,4 @@ If you expect to be using Nuxt 2 beyond the EOL (End of Life) date (June 30, 202
|
||||
|
||||
## <a name="license">⚖️ License</a>
|
||||
|
||||
[MIT](./LICENSE)
|
||||
[MIT](https://github.com/nuxt/nuxt/tree/main/LICENSE)
|
||||
|
@ -117,10 +117,13 @@ In most cases, Nuxt can work with third-party content that is not generated or c
|
||||
|
||||
Accordingly, you should make sure that the following options are unchecked / disabled in Cloudflare. Otherwise, unnecessary re-rendering or hydration errors could impact your production application.
|
||||
|
||||
1. Speed > Optimization > Auto Minify: Uncheck JavaScript, CSS and HTML
|
||||
2. Speed > Optimization > Disable "Rocket Loader™"
|
||||
3. Speed > Optimization > Disable "Mirage"
|
||||
1. Speed > Optimization > Content Optimization > Auto Minify: Uncheck JavaScript, CSS and HTML
|
||||
2. Speed > Optimization > Content Optimization > Disable "Rocket Loader™"
|
||||
3. Speed > Optimization > Image Optimization > Disable "Mirage"
|
||||
4. Scrape Shield > Disable "Email Address Obfuscation"
|
||||
5. Scrape Shield > Disable "Server-side Excludes"
|
||||
|
||||
With these settings, you can be sure that Cloudflare won't inject scripts into your Nuxt application that may cause unwanted side effects.
|
||||
|
||||
::tip
|
||||
Their location on the Cloudfalre dashboard sometimes changes so don't hesitate to look around.
|
||||
::
|
||||
|
@ -150,10 +150,10 @@ Read more about `useError` composable.
|
||||
### `createError`
|
||||
|
||||
```ts [TS Signature]
|
||||
function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
|
||||
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
|
||||
```
|
||||
|
||||
Create an error object with additional metadata. It is usable in both the Vue and Server portions of your app, and is meant to be thrown.
|
||||
Create an error object with additional metadata. You can pass a string to be set as the error `message` or an object containing error properties. It is usable in both the Vue and Server portions of your app, and is meant to be thrown.
|
||||
|
||||
If you throw an error created with `createError`:
|
||||
- on server-side, it will trigger a full-screen error page which you can clear with [`clearError`](#clearerror).
|
||||
|
@ -155,7 +155,7 @@ export default defineNuxtModule({
|
||||
// Compatibility constraints
|
||||
compatibility: {
|
||||
// Semver version of supported nuxt versions
|
||||
nuxt: '^3.0.0'
|
||||
nuxt: '>=3.0.0'
|
||||
}
|
||||
},
|
||||
// Default configuration options for your module, can also be a function returning those
|
||||
|
@ -18,7 +18,7 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
|
||||
|
||||
```vue [pages/index.vue]
|
||||
<script setup lang="ts">
|
||||
const { data, pending, error, refresh } = await useAsyncData(
|
||||
const { data, pending, error, refresh, clear } = await useAsyncData(
|
||||
'mountains',
|
||||
() => $fetch('https://api.nuxtjs.dev/mountains')
|
||||
)
|
||||
@ -26,7 +26,7 @@ const { data, pending, error, refresh } = await useAsyncData(
|
||||
```
|
||||
|
||||
::note
|
||||
`data`, `pending`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` is a plain function for refetching data.
|
||||
`data`, `pending`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
|
||||
::
|
||||
|
||||
### Watch Params
|
||||
@ -92,6 +92,7 @@ Learn how to use `transform` and `getCachedData` to avoid superfluous calls to a
|
||||
- `refresh`/`execute`: a function that can be used to refresh the data returned by the `handler` function.
|
||||
- `error`: an error object if the data fetching failed.
|
||||
- `status`: a string indicating the status of the data request (`"idle"`, `"pending"`, `"success"`, `"error"`).
|
||||
- `clear`: a function which will set `data` to `undefined`, set `error` to `null`, set `pending` to `false`, set `status` to `'idle'`, and mark any currently pending requests as cancelled.
|
||||
|
||||
By default, Nuxt waits until a `refresh` is finished before it can be executed again.
|
||||
|
||||
|
@ -19,14 +19,14 @@ It automatically generates a key based on URL and fetch options, provides type h
|
||||
|
||||
```vue [pages/modules.vue]
|
||||
<script setup lang="ts">
|
||||
const { data, pending, error, refresh } = await useFetch('/api/modules', {
|
||||
const { data, pending, error, refresh, clear } = await useFetch('/api/modules', {
|
||||
pick: ['title']
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
::note
|
||||
`data`, `pending`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` is a plain function for refetching data.
|
||||
`data`, `pending`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions..
|
||||
::
|
||||
|
||||
Using the `query` option, you can add search parameters to your query. This option is extended from [unjs/ofetch](https://github.com/unjs/ofetch) and is using [unjs/ufo](https://github.com/unjs/ufo) to create the URL. Objects are automatically stringified.
|
||||
@ -43,7 +43,7 @@ The above example results in `https://api.nuxt.com/modules?param1=value1¶m2=
|
||||
You can also use [interceptors](https://github.com/unjs/ofetch#%EF%B8%8F-interceptors):
|
||||
|
||||
```ts
|
||||
const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
|
||||
const { data, pending, error, refresh, clear } = await useFetch('/api/auth/login', {
|
||||
onRequest({ request, options }) {
|
||||
// Set the request headers
|
||||
options.headers = options.headers || {}
|
||||
@ -128,6 +128,7 @@ Learn how to use `transform` and `getCachedData` to avoid superfluous calls to a
|
||||
- `refresh`/`execute`: a function that can be used to refresh the data returned by the `handler` function.
|
||||
- `error`: an error object if the data fetching failed.
|
||||
- `status`: a string indicating the status of the data request (`"idle"`, `"pending"`, `"success"`, `"error"`).
|
||||
- `clear`: a function which will set `data` to `undefined`, set `error` to `null`, set `pending` to `false`, set `status` to `'idle'`, and mark any currently pending requests as cancelled.
|
||||
|
||||
By default, Nuxt waits until a `refresh` is finished before it can be executed again.
|
||||
|
||||
|
@ -12,7 +12,9 @@ You can use this function to create an error object with additional metadata. It
|
||||
|
||||
## Parameters
|
||||
|
||||
- `err`: `{ cause, data, message, name, stack, statusCode, statusMessage, fatal }`
|
||||
- `err`: `string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }`
|
||||
|
||||
You can pass either a string or an object to the `createError` function. If you pass a string, it will be used as the error `message`, and the `statusCode` will default to `500`. If you pass an object, you can set multiple properties of the error, such as `statusCode`, `message`, and other error properties.
|
||||
|
||||
## In Vue App
|
||||
|
||||
@ -48,4 +50,6 @@ export default eventHandler(() => {
|
||||
})
|
||||
```
|
||||
|
||||
In API routes, using `createError` by passing an object with a short `statusMessage` is recommended because it can be accessed on the client side. Otherwise, a `message` passed to `createError` on an API route will not propagate to the client. Alternatively, you can use the `data` property to pass data back to the client. In any case, always consider avoiding to put dynamic user input to the message to avoid potential security issues.
|
||||
|
||||
:read-more{to="/docs/getting-started/error-handling"}
|
||||
|
10
package.json
10
package.json
@ -42,11 +42,11 @@
|
||||
"magic-string": "^0.30.10",
|
||||
"nuxt": "workspace:*",
|
||||
"rollup": "^4.18.0",
|
||||
"vite": "5.3.0",
|
||||
"vue": "3.4.27"
|
||||
"vite": "5.3.1",
|
||||
"vue": "3.4.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.4.0",
|
||||
"@eslint/js": "9.5.0",
|
||||
"@nuxt/eslint-config": "0.3.13",
|
||||
"@nuxt/kit": "workspace:*",
|
||||
"@nuxt/test-utils": "3.13.1",
|
||||
@ -64,7 +64,7 @@
|
||||
"changelogen": "0.5.5",
|
||||
"consola": "3.2.3",
|
||||
"devalue": "5.0.0",
|
||||
"eslint": "9.4.0",
|
||||
"eslint": "9.5.0",
|
||||
"eslint-plugin-no-only-tests": "3.1.0",
|
||||
"eslint-plugin-perfectionist": "2.11.0",
|
||||
"eslint-typegen": "0.2.4",
|
||||
@ -89,7 +89,7 @@
|
||||
"ufo": "1.5.3",
|
||||
"vitest": "1.6.0",
|
||||
"vitest-environment-nuxt": "1.0.0",
|
||||
"vue": "3.4.27",
|
||||
"vue": "3.4.29",
|
||||
"vue-router": "4.3.3",
|
||||
"vue-tsc": "2.0.21"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxt/kit",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.git",
|
||||
@ -54,7 +54,7 @@
|
||||
"lodash-es": "4.17.21",
|
||||
"nitropack": "2.9.6",
|
||||
"unbuild": "latest",
|
||||
"vite": "5.3.0",
|
||||
"vite": "5.3.1",
|
||||
"vitest": "1.6.0",
|
||||
"webpack": "5.92.0"
|
||||
},
|
||||
|
@ -43,8 +43,11 @@ export function normalizePlugin (plugin: NuxtPlugin | string): NuxtPlugin {
|
||||
* Note: By default plugin is prepended to the plugins array. You can use second argument to append (push) instead.
|
||||
* @example
|
||||
* ```js
|
||||
* import { createResolver } from '@nuxt/kit'
|
||||
* const resolver = createResolver(import.meta.url)
|
||||
*
|
||||
* addPlugin({
|
||||
* src: path.resolve(__dirname, 'templates/foo.js'),
|
||||
* src: resolver.resolve('templates/foo.js'),
|
||||
* filename: 'foo.server.js' // [optional] only include in server bundle
|
||||
* })
|
||||
* ```
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nuxt",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.git",
|
||||
@ -68,8 +68,8 @@
|
||||
"@unhead/dom": "^1.9.13",
|
||||
"@unhead/ssr": "^1.9.13",
|
||||
"@unhead/vue": "^1.9.13",
|
||||
"@vue/shared": "^3.4.27",
|
||||
"acorn": "8.11.3",
|
||||
"@vue/shared": "^3.4.29",
|
||||
"acorn": "8.12.0",
|
||||
"c12": "^1.11.1",
|
||||
"chokidar": "^3.6.0",
|
||||
"cookie-es": "^1.1.0",
|
||||
@ -112,7 +112,7 @@
|
||||
"unplugin-vue-router": "^0.7.0",
|
||||
"unstorage": "^1.10.2",
|
||||
"untyped": "^1.4.2",
|
||||
"vue": "^3.4.27",
|
||||
"vue": "^3.4.29",
|
||||
"vue-bundle-renderer": "^2.1.0",
|
||||
"vue-devtools-stub": "^0.1.0",
|
||||
"vue-router": "^4.3.3"
|
||||
@ -124,9 +124,9 @@
|
||||
"@types/estree": "1.0.5",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"@vue/compiler-sfc": "3.4.27",
|
||||
"@vue/compiler-sfc": "3.4.29",
|
||||
"unbuild": "latest",
|
||||
"vite": "5.3.0",
|
||||
"vite": "5.3.1",
|
||||
"vitest": "1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -311,6 +311,11 @@ export function useAsyncData<
|
||||
result = pick(result as any, options.pick) as DataT
|
||||
}
|
||||
|
||||
if (import.meta.dev && import.meta.server && !result) {
|
||||
// @ts-expect-error private property
|
||||
console.warn(`[nuxt] \`${options._functionName || 'useAsyncData'}\` should return a value that is not \`null\` or \`undefined\` or the request may be duplicated on the client side.`)
|
||||
}
|
||||
|
||||
nuxtApp.payload.data[key] = result
|
||||
|
||||
asyncData.data.value = result
|
||||
|
@ -198,6 +198,7 @@ function cookieRef<T> (value: T | undefined, delay: number, shouldWatch: boolean
|
||||
if (shouldWatch) { unsubscribe = watch(internalRef, trigger) }
|
||||
|
||||
function createExpirationTimeout () {
|
||||
elapsed = 0
|
||||
clearTimeout(timeout)
|
||||
const timeRemaining = delay - elapsed
|
||||
const timeoutLength = timeRemaining < MAX_TIMEOUT_DELAY ? timeRemaining : MAX_TIMEOUT_DELAY
|
||||
|
@ -60,9 +60,15 @@ export function useScriptGoogleTagManager (...args: unknown[]) {
|
||||
export function useScriptSegment (...args: unknown[]) {
|
||||
renderStubMessage('useScriptSegment')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function useScriptFacebookPixel (...args: unknown[]) {
|
||||
renderStubMessage('useScriptFacebookPixel')
|
||||
export function useScriptClarity (...args: unknown[]) {
|
||||
renderStubMessage('useScriptClarity')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function useScriptMetaPixel (...args: unknown[]) {
|
||||
renderStubMessage('useScriptMetaPixel')
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function useScriptXPixel (...args: unknown[]) {
|
||||
@ -100,3 +106,13 @@ export function useScriptGoogleMaps (...args: unknown[]) {
|
||||
export function useScriptNpm (...args: unknown[]) {
|
||||
renderStubMessage('useScriptNpm')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function useScriptGoogleAdsense (...args: unknown[]) {
|
||||
renderStubMessage('useScriptGoogleAdsense')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function useScriptYouTubePlayer (...args: unknown[]) {
|
||||
renderStubMessage('useScriptYouTubePlayer')
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ const SCRIPT_RE = /<script[^>]*>/g
|
||||
const HAS_SLOT_OR_CLIENT_RE = /<slot[^>]*>|nuxt-client/
|
||||
const TEMPLATE_RE = /<template>([\s\S]*)<\/template>/
|
||||
const NUXTCLIENT_ATTR_RE = /\s:?nuxt-client(="[^"]*")?/g
|
||||
const IMPORT_CODE = '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
|
||||
const IMPORT_CODE = '\nimport { mergeProps as __mergeProps } from \'vue\'' + '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
|
||||
const EXTRACTED_ATTRS_RE = /v-(?:if|else-if|else)(="[^"]*")?/g
|
||||
|
||||
function wrapWithVForDiv (code: string, vfor: string): string {
|
||||
@ -156,7 +156,7 @@ function getPropsToString (bindings: Record<string, string>): string {
|
||||
const vfor = bindings['v-for']?.split(' in ').map((v: string) => v.trim()) as [string, string] | undefined
|
||||
if (Object.keys(bindings).length === 0) { return 'undefined' }
|
||||
const content = Object.entries(bindings).filter(b => b[0] && (b[0] !== '_bind' && b[0] !== 'v-for')).map(([name, value]) => isBinding(name) ? `[\`${name.slice(1)}\`]: ${value}` : `[\`${name}\`]: \`${value}\``).join(',')
|
||||
const data = bindings._bind ? `mergeProps(${bindings._bind}, { ${content} })` : `{ ${content} }`
|
||||
const data = bindings._bind ? `__mergeProps(${bindings._bind}, { ${content} })` : `{ ${content} }`
|
||||
if (!vfor) {
|
||||
return `[${data}]`
|
||||
} else {
|
||||
|
@ -46,10 +46,12 @@ export async function build (nuxt: Nuxt) {
|
||||
if (!nuxt.options._prepare) {
|
||||
await Promise.all([checkForExternalConfigurationFiles(), bundle(nuxt)])
|
||||
await nuxt.callHook('build:done')
|
||||
}
|
||||
|
||||
if (!nuxt.options.dev) {
|
||||
await nuxt.callHook('close', nuxt)
|
||||
if (!nuxt.options.dev) {
|
||||
await nuxt.callHook('close', nuxt)
|
||||
}
|
||||
} else {
|
||||
nuxt.hook('prepare:types', () => nuxt.close())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,6 +355,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
nitroConfig.rollupConfig!.plugins!.push(
|
||||
ImportProtectionPlugin.rollup({
|
||||
rootDir: nuxt.options.rootDir,
|
||||
modulesDir: nuxt.options.modulesDir,
|
||||
patterns: nuxtImportProtections(nuxt, { isNitro: true }),
|
||||
exclude: [/core[\\/]runtime[\\/]nitro[\\/]renderer/],
|
||||
}),
|
||||
@ -497,7 +498,11 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||
for (const route of ['/200.html', '/404.html']) {
|
||||
routes.add(route)
|
||||
}
|
||||
if (!nuxt.options.ssr) {
|
||||
if (nuxt.options.ssr) {
|
||||
if (nitro.options.prerender.crawlLinks) {
|
||||
routes.add('/')
|
||||
}
|
||||
} else {
|
||||
routes.add('/index.html')
|
||||
}
|
||||
})
|
||||
|
@ -49,14 +49,13 @@ export function createNuxt (options: NuxtOptions): Nuxt {
|
||||
addHooks: hooks.addHooks,
|
||||
hook: hooks.hook,
|
||||
ready: () => initNuxt(nuxt),
|
||||
close: async () => {
|
||||
await hooks.callHook('close', nuxt)
|
||||
hooks.removeAllHooks()
|
||||
},
|
||||
close: () => hooks.callHook('close', nuxt),
|
||||
vfs: {},
|
||||
apps: {},
|
||||
}
|
||||
|
||||
hooks.hookOnce('close', () => { hooks.removeAllHooks() })
|
||||
|
||||
return nuxt
|
||||
}
|
||||
|
||||
@ -168,6 +167,7 @@ async function initNuxt (nuxt: Nuxt) {
|
||||
// Exclude top-level resolutions by plugins
|
||||
exclude: [join(nuxt.options.srcDir, 'index.html')],
|
||||
patterns: nuxtImportProtections(nuxt),
|
||||
modulesDir: nuxt.options.modulesDir,
|
||||
}
|
||||
addVitePlugin(() => ImportProtectionPlugin.vite(config))
|
||||
addWebpackPlugin(() => ImportProtectionPlugin.webpack(config))
|
||||
@ -664,7 +664,9 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||
|
||||
const nuxt = createNuxt(options)
|
||||
|
||||
await Promise.all(keyDependencies.map(dependency => checkDependencyVersion(dependency, nuxt._version)))
|
||||
for (const dep of keyDependencies) {
|
||||
checkDependencyVersion(dep, nuxt._version)
|
||||
}
|
||||
|
||||
// We register hooks layer-by-layer so any overrides need to be registered separately
|
||||
if (opts.overrides?.hooks) {
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { createUnplugin } from 'unplugin'
|
||||
import { logger } from '@nuxt/kit'
|
||||
import { resolvePath } from 'mlly'
|
||||
import { isAbsolute, join, relative, resolve } from 'pathe'
|
||||
import escapeRE from 'escape-string-regexp'
|
||||
import type { NuxtOptions } from 'nuxt/schema'
|
||||
|
||||
const _require = createRequire(import.meta.url)
|
||||
|
||||
interface ImportProtectionOptions {
|
||||
rootDir: string
|
||||
modulesDir: string[]
|
||||
patterns: [importPattern: string | RegExp, warning?: string][]
|
||||
exclude?: Array<RegExp | string>
|
||||
}
|
||||
@ -58,6 +57,7 @@ export const nuxtImportProtections = (nuxt: { options: NuxtOptions }, options: {
|
||||
export const ImportProtectionPlugin = createUnplugin(function (options: ImportProtectionOptions) {
|
||||
const cache: Record<string, Map<string | RegExp, boolean>> = {}
|
||||
const importersToExclude = options?.exclude || []
|
||||
const proxy = resolvePath('unenv/runtime/mock/proxy', { url: options.modulesDir })
|
||||
return {
|
||||
name: 'nuxt:import-protection',
|
||||
enforce: 'pre',
|
||||
@ -85,7 +85,7 @@ export const ImportProtectionPlugin = createUnplugin(function (options: ImportPr
|
||||
matched = true
|
||||
}
|
||||
if (matched) {
|
||||
return _require.resolve('unenv/runtime/mock/proxy')
|
||||
return proxy
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
@ -698,7 +698,7 @@ function replaceIslandTeleports (ssrContext: NuxtSSRContext, html: string) {
|
||||
if (matchClientComp) {
|
||||
const [, uid, clientId] = matchClientComp
|
||||
if (!uid || !clientId) { continue }
|
||||
html = html.replace(new RegExp(` data-island-component="${clientId}"[^>]*>`), (full) => {
|
||||
html = html.replace(new RegExp(` data-island-uid="${uid}" data-island-component="${clientId}"[^>]*>`), (full) => {
|
||||
return full + teleports[key]
|
||||
})
|
||||
continue
|
||||
|
@ -426,7 +426,7 @@ export const nuxtConfigTemplate: NuxtTemplate = {
|
||||
`export const resetAsyncDataToUndefined = ${ctx.nuxt.options.experimental.resetAsyncDataToUndefined}`,
|
||||
`export const nuxtDefaultErrorValue = ${ctx.nuxt.options.future.compatibilityVersion === 4 ? 'undefined' : 'null'}`,
|
||||
`export const fetchDefaults = ${JSON.stringify(fetchDefaults)}`,
|
||||
`export const vueAppRootContainer = ${ctx.nuxt.options.app.rootId ? `'#${ctx.nuxt.options.app.rootId}'` : `'body > ${ctx.nuxt.options.app.rootTag}'`}`,
|
||||
`export const vueAppRootContainer = ${ctx.nuxt.options.app.rootAttrs.id ? `'#${ctx.nuxt.options.app.rootAttrs.id}'` : `'body > ${ctx.nuxt.options.app.rootTag}'`}`,
|
||||
`export const viewTransition = ${ctx.nuxt.options.experimental.viewTransition}`,
|
||||
`export const appId = ${JSON.stringify(ctx.nuxt.options.appId)}`,
|
||||
`export const outdatedBuildInterval = ${ctx.nuxt.options.experimental.checkOutdatedBuildInterval}`,
|
||||
|
@ -275,20 +275,6 @@ export default defineNuxtModule({
|
||||
}
|
||||
})
|
||||
|
||||
// TODO: inject routes in `200.html` in next nitro upgrade (2.9.7+) via https://github.com/unjs/nitro/pull/2517
|
||||
if (!nuxt.options.dev && !nuxt.options._prepare) {
|
||||
nuxt.hook('app:templatesGenerated', (app) => {
|
||||
const nitro = useNitro()
|
||||
if (nitro.options.prerender.crawlLinks) {
|
||||
for (const page of app.pages!) {
|
||||
if (page.path && !page.path.includes(':')) {
|
||||
nitro.options.prerender.routes.push(page.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
nuxt.hook('imports:extend', (imports) => {
|
||||
imports.push(
|
||||
{ name: 'definePageMeta', as: 'definePageMeta', from: resolve(runtimeDir, 'composables') },
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { join } from 'pathe'
|
||||
import { createCommonJS, findExports } from 'mlly'
|
||||
import { findExports } from 'mlly'
|
||||
import * as VueFunctions from 'vue'
|
||||
import type { Import } from 'unimport'
|
||||
import { createUnimport } from 'unimport'
|
||||
@ -59,8 +59,8 @@ const excludedNuxtHelpers = ['useHydration', 'useHead', 'useSeoMeta', 'useServer
|
||||
|
||||
describe('imports:nuxt', () => {
|
||||
try {
|
||||
const { __dirname } = createCommonJS(import.meta.url)
|
||||
const entrypointContents = readFileSync(join(__dirname, '../src/app/composables/index.ts'), 'utf8')
|
||||
const entrypointPath = fileURLToPath(new URL('../src/app/composables/index.ts', import.meta.url))
|
||||
const entrypointContents = readFileSync(entrypointPath, 'utf8')
|
||||
|
||||
const names = findExports(entrypointContents).flatMap(i => i.names || i.name)
|
||||
for (let name of names) {
|
||||
|
@ -2,6 +2,7 @@ import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { Component, Nuxt } from '@nuxt/schema'
|
||||
import { kebabCase } from 'scule'
|
||||
import { normalize } from 'pathe'
|
||||
|
||||
import { createTransformPlugin } from '../src/components/transform'
|
||||
|
||||
@ -92,7 +93,7 @@ function createTransformer (components: Component[], mode: 'client' | 'server' |
|
||||
|
||||
return async (code: string, id: string) => {
|
||||
const result = await (plugin as any).transform!(code, id)
|
||||
return (typeof result === 'string' ? result : result?.code)?.replaceAll(rootDir, '<repo>/')
|
||||
return (typeof result === 'string' ? result : result?.code)?.replaceAll(normalize(rootDir), '<repo>/')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { normalize } from 'pathe'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { ImportProtectionPlugin, nuxtImportProtections } from '../src/core/plugins/import-protection'
|
||||
@ -40,6 +41,7 @@ describe('import protection', () => {
|
||||
const transformWithImportProtection = (id: string, importer: string) => {
|
||||
const plugin = ImportProtectionPlugin.rollup({
|
||||
rootDir: '/root',
|
||||
modulesDir: [fileURLToPath(new URL('..', import.meta.url))],
|
||||
patterns: nuxtImportProtections({
|
||||
options: {
|
||||
modules: ['some-nuxt-module'],
|
||||
|
@ -71,6 +71,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -80,6 +81,42 @@ describe('islandTransform - server and island components', () => {
|
||||
`)
|
||||
})
|
||||
|
||||
it('generates bindings when props are needed to be merged', async () => {
|
||||
const result = await viteTransform(`<script setup lang="ts">
|
||||
withDefaults(defineProps<{ things?: any[]; somethingElse?: string }>(), {
|
||||
things: () => [],
|
||||
somethingElse: "yay",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-for="thing in things">
|
||||
<slot name="thing" v-bind="thing" />
|
||||
</template>
|
||||
</template>
|
||||
`, 'hello.server.vue')
|
||||
|
||||
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
|
||||
"<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
withDefaults(defineProps<{ things?: any[]; somethingElse?: string }>(), {
|
||||
things: () => [],
|
||||
somethingElse: "yay",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-for="thing in things">
|
||||
<NuxtTeleportSsrSlot name="thing" :props="[__mergeProps(thing, { })]"><slot name="thing" v-bind="thing" /></NuxtTeleportSsrSlot>
|
||||
</template>
|
||||
</template>
|
||||
"
|
||||
`)
|
||||
})
|
||||
|
||||
it('expect slot fallback transform to match inline snapshot', async () => {
|
||||
const result = await viteTransform(`<template>
|
||||
<div>
|
||||
@ -103,6 +140,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -168,6 +206,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -195,6 +234,7 @@ describe('islandTransform - server and island components', () => {
|
||||
|
||||
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
|
||||
"<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -234,6 +274,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -267,6 +308,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -302,6 +344,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
@ -325,6 +368,7 @@ describe('islandTransform - server and island components', () => {
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"<script setup>
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'</script><template>
|
||||
@ -351,6 +395,7 @@ describe('islandTransform - server and island components', () => {
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"<script setup>
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'</script><template>
|
||||
@ -396,6 +441,7 @@ describe('islandTransform - server and island components', () => {
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mergeProps as __mergeProps } from 'vue'
|
||||
import { vforToArray as __vforToArray } from '#app/components/utils'
|
||||
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
|
||||
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { resolve } from 'pathe'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import type { ComponentsDir } from 'nuxt/schema'
|
||||
|
||||
import { scanComponents } from '../src/components/scan'
|
||||
|
||||
const fixtureDir = resolve(__dirname, 'fixture')
|
||||
const fixtureDir = fileURLToPath(new URL('fixture', import.meta.url))
|
||||
const rFixture = (...p: string[]) => resolve(fixtureDir, ...p)
|
||||
|
||||
vi.mock('@nuxt/kit', () => ({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { resolve } from 'pathe'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
export const fixtureDir = resolve(__dirname, 'fixture')
|
||||
export const fixtureDir = fileURLToPath(new URL('fixture', import.meta.url))
|
||||
|
||||
export function normalizeLineEndings (str: string, normalized = '\n') {
|
||||
return str.replace(/\r?\n/g, normalized)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxt/schema",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.git",
|
||||
@ -42,8 +42,8 @@
|
||||
"@unhead/schema": "1.9.13",
|
||||
"@vitejs/plugin-vue": "5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "4.0.0",
|
||||
"@vue/compiler-core": "3.4.27",
|
||||
"@vue/compiler-sfc": "3.4.27",
|
||||
"@vue/compiler-core": "3.4.29",
|
||||
"@vue/compiler-sfc": "3.4.29",
|
||||
"@vue/language-core": "2.0.21",
|
||||
"c12": "1.11.1",
|
||||
"esbuild-loader": "4.1.0",
|
||||
@ -54,8 +54,8 @@
|
||||
"unbuild": "latest",
|
||||
"unctx": "2.3.1",
|
||||
"unenv": "1.9.0",
|
||||
"vite": "5.3.0",
|
||||
"vue": "3.4.27",
|
||||
"vite": "5.3.1",
|
||||
"vue": "3.4.29",
|
||||
"vue-bundle-renderer": "2.1.0",
|
||||
"vue-loader": "17.4.2",
|
||||
"vue-router": "4.3.3",
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { consola } from 'consola'
|
||||
import { resolve } from 'pathe'
|
||||
import { isTest } from 'std-env'
|
||||
import { withoutLeadingSlash } from 'ufo'
|
||||
import { defineUntypedSchema } from 'untyped'
|
||||
@ -109,5 +110,8 @@ export default defineUntypedSchema({
|
||||
},
|
||||
},
|
||||
},
|
||||
cacheDir: {
|
||||
$resolve: async (val, get) => val ?? resolve(await get('rootDir') as string, 'node_modules/.cache/vite'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { applyDefaults } from 'untyped'
|
||||
|
||||
import { normalize } from 'pathe'
|
||||
import { NuxtConfigSchema } from '../src'
|
||||
import type { NuxtOptions } from '../src'
|
||||
|
||||
@ -75,7 +76,9 @@ describe('nuxt folder structure', () => {
|
||||
})
|
||||
|
||||
function getDirs (options: NuxtOptions) {
|
||||
const stripRoot = (dir: string) => dir.replace(process.cwd(), '<cwd>')
|
||||
const stripRoot = (dir: string) => {
|
||||
return normalize(dir).replace(normalize(process.cwd()), '<cwd>')
|
||||
}
|
||||
return {
|
||||
rootDir: stripRoot(options.rootDir),
|
||||
serverDir: stripRoot(options.serverDir),
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { join, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import type { Plugin } from 'vite'
|
||||
import { template } from 'lodash-es'
|
||||
import genericMessages from '../templates/messages.json'
|
||||
|
||||
const r = (...path: string[]) => resolve(join(__dirname, '..', ...path))
|
||||
const templatesRoot = fileURLToPath(new URL('..', import.meta.url))
|
||||
|
||||
const r = (...path: string[]) => resolve(join(templatesRoot, ...path))
|
||||
|
||||
export const DevRenderingPlugin = () => {
|
||||
return <Plugin>{
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { join, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import { globby } from 'globby'
|
||||
|
||||
const r = (...path: string[]) => resolve(join(__dirname, '..', ...path))
|
||||
const templatesRoot = fileURLToPath(new URL('..', import.meta.url))
|
||||
|
||||
const r = (...path: string[]) => resolve(join(templatesRoot, ...path))
|
||||
|
||||
async function main () {
|
||||
const templates = await globby(r('dist/templates/*.js'))
|
||||
|
@ -33,6 +33,6 @@
|
||||
"prettier": "3.3.2",
|
||||
"scule": "1.3.0",
|
||||
"unocss": "0.61.0",
|
||||
"vite": "5.3.0"
|
||||
"vite": "5.3.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { join } from 'node:path'
|
||||
import { resolve } from 'node:path'
|
||||
import { readdirSync } from 'node:fs'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
@ -8,7 +8,8 @@ import UnoCSS from 'unocss/vite'
|
||||
import { DevRenderingPlugin } from './lib/dev'
|
||||
import { RenderPlugin } from './lib/render'
|
||||
|
||||
const r = (...path: string[]) => fileURLToPath(new URL(join(...path), import.meta.url))
|
||||
const rootDir = fileURLToPath(new URL('.', import.meta.url))
|
||||
const r = (...path: string[]) => resolve(rootDir, ...path)
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
@ -32,7 +33,7 @@ export default defineConfig({
|
||||
],
|
||||
server: {
|
||||
fs: {
|
||||
allow: ['./templates', __dirname],
|
||||
allow: ['./templates', rootDir],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxt/vite-builder",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.git",
|
||||
@ -30,7 +30,7 @@
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"rollup": "4.18.0",
|
||||
"unbuild": "latest",
|
||||
"vue": "3.4.27"
|
||||
"vue": "3.4.29"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "workspace:*",
|
||||
@ -63,7 +63,7 @@
|
||||
"ufo": "^1.5.3",
|
||||
"unenv": "^1.9.0",
|
||||
"unplugin": "^1.10.1",
|
||||
"vite": "^5.3.0",
|
||||
"vite": "^5.3.1",
|
||||
"vite-node": "^1.6.0",
|
||||
"vite-plugin-checker": "^0.6.4",
|
||||
"vue-bundle-renderer": "^2.1.0"
|
||||
|
@ -118,7 +118,7 @@ export async function buildClient (ctx: ViteBuildContext) {
|
||||
'vue',
|
||||
],
|
||||
},
|
||||
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite', 'client'),
|
||||
cacheDir: resolve(ctx.nuxt.options.rootDir, ctx.config.cacheDir ?? 'node_modules/.cache/vite', 'client'),
|
||||
build: {
|
||||
sourcemap: ctx.nuxt.options.sourcemap.client ? ctx.config.build?.sourcemap ?? ctx.nuxt.options.sourcemap.client : false,
|
||||
manifest: 'manifest.json',
|
||||
|
@ -19,6 +19,7 @@ export function resolveCSSOptions (nuxt: Nuxt): ViteConfig['css'] {
|
||||
|
||||
for (const [name, opts] of plugins) {
|
||||
if (opts) {
|
||||
// TODO: remove use of requireModule in favour of ESM import
|
||||
const plugin = requireModule(name, {
|
||||
paths: [
|
||||
...nuxt.options.modulesDir,
|
||||
|
@ -71,7 +71,7 @@ export async function buildServer (ctx: ViteBuildContext) {
|
||||
/(nuxt|nuxt3|nuxt-nightly)\/(dist|src|app)/,
|
||||
],
|
||||
},
|
||||
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite', 'server'),
|
||||
cacheDir: resolve(ctx.nuxt.options.rootDir, ctx.config.cacheDir ?? 'node_modules/.cache/vite', 'server'),
|
||||
build: {
|
||||
// we'll display this in nitro build output
|
||||
reportCompressedSize: false,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxt/webpack-builder",
|
||||
"version": "3.12.1",
|
||||
"version": "3.12.2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.git",
|
||||
@ -42,7 +42,7 @@
|
||||
"hash-sum": "^2.0.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"magic-string": "^0.30.10",
|
||||
"memfs": "^4.9.2",
|
||||
"memfs": "^4.9.3",
|
||||
"mini-css-extract-plugin": "^2.9.0",
|
||||
"mlly": "^1.7.1",
|
||||
"ohash": "^1.1.3",
|
||||
@ -77,9 +77,8 @@
|
||||
"@types/pify": "5.0.4",
|
||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||
"@types/webpack-hot-middleware": "2.25.9",
|
||||
"@types/webpack-virtual-modules": "0.4.2",
|
||||
"unbuild": "latest",
|
||||
"vue": "3.4.27"
|
||||
"vue": "3.4.29"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.3.4"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import createResolver from 'postcss-import-resolver'
|
||||
import { createCommonJS } from 'mlly'
|
||||
import { requireModule } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { defu } from 'defu'
|
||||
@ -61,9 +61,10 @@ export const getPostcssConfig = (nuxt: Nuxt) => {
|
||||
// Keep the order of default plugins
|
||||
if (!Array.isArray(postcssOptions.plugins) && isPureObject(postcssOptions.plugins)) {
|
||||
// Map postcss plugins into instances on object mode once
|
||||
const cjs = createCommonJS(import.meta.url)
|
||||
const cwd = fileURLToPath(new URL('.', import.meta.url))
|
||||
postcssOptions.plugins = sortPlugins(postcssOptions).map((pluginName: string) => {
|
||||
const pluginFn = requireModule(pluginName, { paths: [cjs.__dirname] })
|
||||
// TODO: remove use of requireModule in favour of ESM import
|
||||
const pluginFn = requireModule(pluginName, { paths: [cwd] })
|
||||
const pluginOptions = postcssOptions.plugins[pluginName]
|
||||
if (!pluginOptions || typeof pluginFn !== 'function') { return null }
|
||||
return pluginFn(pluginOptions)
|
||||
|
1277
pnpm-lock.yaml
1277
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,9 @@ if [[ ! -z ${NODE_AUTH_TOKEN} ]] ; then
|
||||
npm whoami
|
||||
fi
|
||||
|
||||
# use absolute urls for better rendering on npm
|
||||
sed -i '' 's/\.\/\.github\/assets/https:\/\/github.com\/nuxt\/nuxt\/tree\/main\/\.github\/assets/g' README.md
|
||||
|
||||
# Release packages
|
||||
for p in packages/* ; do
|
||||
if [[ $p == "packages/nuxi" ]] ; then
|
||||
|
@ -8,6 +8,9 @@ git restore -s@ -SW -- packages examples
|
||||
# Build all once to ensure things are nice
|
||||
pnpm build
|
||||
|
||||
# use absolute urls for better rendering on npm
|
||||
sed -i '' 's/\.\/\.github\/assets/https:\/\/github.com\/nuxt\/nuxt\/tree\/main\/\.github\/assets/g' README.md
|
||||
|
||||
# Release packages
|
||||
for PKG in packages/* ; do
|
||||
if [[ $PKG == "packages/nuxi" ]] ; then
|
||||
|
@ -8,6 +8,9 @@ git restore -s@ -SW -- packages examples
|
||||
# Build all once to ensure things are nice
|
||||
pnpm build
|
||||
|
||||
# use absolute urls for better rendering on npm
|
||||
sed -i '' 's/\.\/\.github\/assets/https:\/\/github.com\/nuxt\/nuxt\/tree\/main\/\.github\/assets/g' README.md
|
||||
|
||||
# Release packages
|
||||
for PKG in packages/* ; do
|
||||
if [[ $PKG == "packages/nuxi" ]] ; then
|
||||
|
@ -19,7 +19,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
for (const outputDir of ['.output', '.output-inline']) {
|
||||
it('default client bundle size', async () => {
|
||||
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
|
||||
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot(`"105k"`)
|
||||
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot(`"106k"`)
|
||||
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
||||
[
|
||||
"_nuxt/entry.js",
|
||||
@ -35,7 +35,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"209k"`)
|
||||
|
||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1338k"`)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"1340k"`)
|
||||
|
||||
const packages = modules.files
|
||||
.filter(m => m.endsWith('package.json'))
|
||||
@ -72,7 +72,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
||||
const serverDir = join(rootDir, '.output-inline/server')
|
||||
|
||||
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"528k"`)
|
||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"530k"`)
|
||||
|
||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"76.2k"`)
|
||||
|
Loading…
Reference in New Issue
Block a user