mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-22 08:29:46 +00:00
Compare commits
12 Commits
cf3335e942
...
8e0049e1d6
Author | SHA1 | Date | |
---|---|---|---|
|
8e0049e1d6 | ||
|
160efe7a7f | ||
|
323745d0d4 | ||
|
c3303373bc | ||
|
09ef60d057 | ||
|
24b91c5d8a | ||
|
49545e6bdf | ||
|
f18278fe28 | ||
|
359aeeec88 | ||
|
980ebb0fbe | ||
|
0a0ec349a1 | ||
|
4a25e2bb50 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -236,7 +236,7 @@ jobs:
|
|||||||
path: packages
|
path: packages
|
||||||
|
|
||||||
- name: Run benchmarks
|
- name: Run benchmarks
|
||||||
uses: CodSpeedHQ/action@da7c57859a7a565a3a92789ac64c41aca031ca1f # v3.3.0
|
uses: CodSpeedHQ/action@1015f4f828ff74b7a950909897fe581d6ba868cc # v3.3.1
|
||||||
with:
|
with:
|
||||||
run: pnpm vitest bench
|
run: pnpm vitest bench
|
||||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||||
|
36
package.json
36
package.json
@ -37,7 +37,7 @@
|
|||||||
"typecheck:docs": "DOCS_TYPECHECK=true pnpm nuxi prepare && nuxt-content-twoslash verify --content-dir docs --languages html"
|
"typecheck:docs": "DOCS_TYPECHECK=true pnpm nuxi prepare && nuxt-content-twoslash verify --content-dir docs --languages html"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@babel/core": "7.26.8",
|
"@babel/core": "7.26.9",
|
||||||
"@babel/helper-plugin-utils": "7.26.5",
|
"@babel/helper-plugin-utils": "7.26.5",
|
||||||
"@nuxt/cli": "3.21.1",
|
"@nuxt/cli": "3.21.1",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
@ -45,12 +45,12 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@types/node": "22.13.2",
|
"@types/node": "22.13.4",
|
||||||
"@unhead/dom": "1.11.18",
|
"@unhead/dom": "1.11.19",
|
||||||
"@unhead/schema": "1.11.18",
|
"@unhead/schema": "1.11.19",
|
||||||
"@unhead/shared": "1.11.18",
|
"@unhead/shared": "1.11.19",
|
||||||
"@unhead/ssr": "1.11.18",
|
"@unhead/ssr": "1.11.19",
|
||||||
"@unhead/vue": "1.11.18",
|
"@unhead/vue": "1.11.19",
|
||||||
"@vue/compiler-core": "3.5.13",
|
"@vue/compiler-core": "3.5.13",
|
||||||
"@vue/compiler-dom": "3.5.13",
|
"@vue/compiler-dom": "3.5.13",
|
||||||
"@vue/shared": "3.5.13",
|
"@vue/shared": "3.5.13",
|
||||||
@ -62,19 +62,19 @@
|
|||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"ohash": "1.1.4",
|
"ohash": "1.1.4",
|
||||||
"postcss": "8.5.2",
|
"postcss": "8.5.2",
|
||||||
"rollup": "4.34.6",
|
"rollup": "4.34.8",
|
||||||
"send": ">=1.1.0",
|
"send": ">=1.1.0",
|
||||||
"typescript": "5.7.3",
|
"typescript": "5.7.3",
|
||||||
"ufo": "1.5.4",
|
"ufo": "1.5.4",
|
||||||
"unbuild": "3.3.1",
|
"unbuild": "3.3.1",
|
||||||
"unhead": "1.11.18",
|
"unhead": "1.11.19",
|
||||||
"unimport": "4.1.1",
|
"unimport": "4.1.2",
|
||||||
"vite": "6.1.0",
|
"vite": "6.1.0",
|
||||||
"vue": "3.5.13"
|
"vue": "3.5.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@arethetypeswrong/cli": "0.17.3",
|
"@arethetypeswrong/cli": "0.17.3",
|
||||||
"@babel/core": "7.26.8",
|
"@babel/core": "7.26.9",
|
||||||
"@babel/helper-plugin-utils": "7.26.5",
|
"@babel/helper-plugin-utils": "7.26.5",
|
||||||
"@codspeed/vitest-plugin": "4.0.0",
|
"@codspeed/vitest-plugin": "4.0.0",
|
||||||
"@nuxt/cli": "3.21.1",
|
"@nuxt/cli": "3.21.1",
|
||||||
@ -86,10 +86,10 @@
|
|||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/babel__core": "7.20.5",
|
"@types/babel__core": "7.20.5",
|
||||||
"@types/babel__helper-plugin-utils": "7.10.3",
|
"@types/babel__helper-plugin-utils": "7.10.3",
|
||||||
"@types/node": "22.13.2",
|
"@types/node": "22.13.4",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"@unhead/schema": "1.11.18",
|
"@unhead/schema": "1.11.19",
|
||||||
"@unhead/vue": "1.11.18",
|
"@unhead/vue": "1.11.19",
|
||||||
"@vitest/coverage-v8": "3.0.5",
|
"@vitest/coverage-v8": "3.0.5",
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"acorn": "8.14.0",
|
"acorn": "8.14.0",
|
||||||
@ -120,12 +120,12 @@
|
|||||||
"pathe": "2.0.3",
|
"pathe": "2.0.3",
|
||||||
"pkg-pr-new": "0.0.39",
|
"pkg-pr-new": "0.0.39",
|
||||||
"playwright-core": "1.50.1",
|
"playwright-core": "1.50.1",
|
||||||
"rollup": "4.34.6",
|
"rollup": "4.34.8",
|
||||||
"semver": "7.7.1",
|
"semver": "7.7.1",
|
||||||
"sherif": "1.3.0",
|
"sherif": "1.3.0",
|
||||||
"std-env": "3.8.0",
|
"std-env": "3.8.0",
|
||||||
"tinyexec": "0.3.2",
|
"tinyexec": "0.3.2",
|
||||||
"tinyglobby": "0.2.10",
|
"tinyglobby": "0.2.11",
|
||||||
"ts-blank-space": "0.6.0",
|
"ts-blank-space": "0.6.0",
|
||||||
"typescript": "5.7.3",
|
"typescript": "5.7.3",
|
||||||
"ufo": "1.5.4",
|
"ufo": "1.5.4",
|
||||||
@ -133,9 +133,9 @@
|
|||||||
"vitest": "3.0.5",
|
"vitest": "3.0.5",
|
||||||
"vitest-environment-nuxt": "1.0.1",
|
"vitest-environment-nuxt": "1.0.1",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
"vue-tsc": "2.2.0",
|
"vue-tsc": "2.2.2",
|
||||||
"webpack": "5.98.0"
|
"webpack": "5.98.0"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.3.0",
|
"packageManager": "pnpm@10.4.1",
|
||||||
"version": ""
|
"version": ""
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
"std-env": "^3.8.0",
|
"std-env": "^3.8.0",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"unctx": "^2.4.1",
|
"unctx": "^2.4.1",
|
||||||
"unimport": "^4.1.1",
|
"unimport": "^4.1.2",
|
||||||
"untyped": "^1.5.2"
|
"untyped": "^1.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -119,9 +119,6 @@ export async function updateTemplates (options?: { filter?: (template: ResolvedN
|
|||||||
return await tryUseNuxt()?.hooks.callHook('builder:generateApp', options)
|
return await tryUseNuxt()?.hooks.callHook('builder:generateApp', options)
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXTENSION_RE = /\b\.\w+$/g
|
|
||||||
// Exclude bridge alias types to support Volar
|
|
||||||
const excludedAlias = [/^@vue\/.*$/, /^#internal\/nuxt/]
|
|
||||||
export async function _generateTypes (nuxt: Nuxt) {
|
export async function _generateTypes (nuxt: Nuxt) {
|
||||||
const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir)
|
const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir)
|
||||||
const relativeRootDir = relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir)
|
const relativeRootDir = relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir)
|
||||||
@ -233,7 +230,9 @@ export async function _generateTypes (nuxt: Nuxt) {
|
|||||||
} satisfies TSConfig)
|
} satisfies TSConfig)
|
||||||
|
|
||||||
const aliases: Record<string, string> = nuxt.options.alias
|
const aliases: Record<string, string> = nuxt.options.alias
|
||||||
|
const EXTENSION_RE = /\b\.\w+$/g
|
||||||
|
// Exclude bridge alias types to support Volar
|
||||||
|
const excludedAlias = [/^@vue\/.*$/, /^#internal\/nuxt/]
|
||||||
const basePath = tsConfig.compilerOptions!.baseUrl
|
const basePath = tsConfig.compilerOptions!.baseUrl
|
||||||
? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl)
|
? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl)
|
||||||
: nuxt.options.buildDir
|
: nuxt.options.buildDir
|
||||||
|
@ -66,15 +66,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/cli": "^3.21.1",
|
"@nuxt/cli": "^3.21.1",
|
||||||
"@nuxt/devalue": "^2.0.2",
|
"@nuxt/devalue": "^2.0.2",
|
||||||
"@nuxt/devtools": "^2.0.0",
|
"@nuxt/devtools": "^2.1.0",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@nuxt/telemetry": "^2.6.5",
|
"@nuxt/telemetry": "^2.6.5",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@unhead/dom": "^1.11.18",
|
"@unhead/dom": "^1.11.19",
|
||||||
"@unhead/shared": "^1.11.18",
|
"@unhead/shared": "^1.11.19",
|
||||||
"@unhead/ssr": "^1.11.18",
|
"@unhead/ssr": "^1.11.19",
|
||||||
"@unhead/vue": "^1.11.18",
|
"@unhead/vue": "^1.11.19",
|
||||||
"@vue/shared": "^3.5.13",
|
"@vue/shared": "^3.5.13",
|
||||||
"acorn": "8.14.0",
|
"acorn": "8.14.0",
|
||||||
"c12": "^2.0.2",
|
"c12": "^2.0.2",
|
||||||
@ -113,14 +113,14 @@
|
|||||||
"semver": "^7.7.1",
|
"semver": "^7.7.1",
|
||||||
"std-env": "^3.8.0",
|
"std-env": "^3.8.0",
|
||||||
"strip-literal": "^3.0.0",
|
"strip-literal": "^3.0.0",
|
||||||
"tinyglobby": "0.2.10",
|
"tinyglobby": "0.2.11",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"ultrahtml": "^1.5.3",
|
"ultrahtml": "^1.5.3",
|
||||||
"uncrypto": "^0.1.3",
|
"uncrypto": "^0.1.3",
|
||||||
"unctx": "^2.4.1",
|
"unctx": "^2.4.1",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unhead": "^1.11.18",
|
"unhead": "^1.11.19",
|
||||||
"unimport": "^4.1.1",
|
"unimport": "^4.1.2",
|
||||||
"unplugin": "^2.2.0",
|
"unplugin": "^2.2.0",
|
||||||
"unplugin-vue-router": "^0.11.2",
|
"unplugin-vue-router": "^0.11.2",
|
||||||
"unstorage": "^1.14.4",
|
"unstorage": "^1.14.4",
|
||||||
@ -131,7 +131,7 @@
|
|||||||
"vue-router": "^4.5.0"
|
"vue-router": "^4.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/scripts": "0.10.1",
|
"@nuxt/scripts": "0.10.3",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"@vitejs/plugin-vue": "5.2.1",
|
"@vitejs/plugin-vue": "5.2.1",
|
||||||
|
@ -3,6 +3,7 @@ import type { RendererNode, VNode } from 'vue'
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
||||||
import type { RouteLocationNormalized } from 'vue-router'
|
import type { RouteLocationNormalized } from 'vue-router'
|
||||||
|
import { ROUTE_KEY_NORMAL_RE, ROUTE_KEY_PARENTHESES_RE, ROUTE_KEY_SYMBOLS_RE } from '../../utils'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { START_LOCATION } from '#build/pages'
|
import { START_LOCATION } from '#build/pages'
|
||||||
|
|
||||||
@ -14,9 +15,6 @@ export const _wrapInTransition = (props: any, children: any) => {
|
|||||||
return { default: () => import.meta.client && props ? h(Transition, props === true ? {} : props, children) : children.default?.() }
|
return { default: () => import.meta.client && props ? h(Transition, props === true ? {} : props, children) : children.default?.() }
|
||||||
}
|
}
|
||||||
|
|
||||||
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
|
||||||
const ROUTE_KEY_SYMBOLS_RE = /(:\w+)[?+*]/g
|
|
||||||
const ROUTE_KEY_NORMAL_RE = /:\w+/g
|
|
||||||
// TODO: consider refactoring into single utility
|
// TODO: consider refactoring into single utility
|
||||||
// See https://github.com/nuxt/nuxt/tree/main/packages/nuxt/src/pages/runtime/utils.ts#L8-L19
|
// See https://github.com/nuxt/nuxt/tree/main/packages/nuxt/src/pages/runtime/utils.ts#L8-L19
|
||||||
function generateRouteKey (route: RouteLocationNormalized) {
|
function generateRouteKey (route: RouteLocationNormalized) {
|
||||||
|
@ -21,9 +21,6 @@ function compareDirByPathLength ({ path: pathA }: { path: string }, { path: path
|
|||||||
return pathB.split(SLASH_SEPARATOR_RE).filter(Boolean).length - pathA.split(SLASH_SEPARATOR_RE).filter(Boolean).length
|
return pathB.split(SLASH_SEPARATOR_RE).filter(Boolean).length - pathA.split(SLASH_SEPARATOR_RE).filter(Boolean).length
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_COMPONENTS_DIRS_RE = /\/components(?:\/(?:global|islands))?$/
|
|
||||||
const STARTER_DOT_RE = /^\./g
|
|
||||||
|
|
||||||
export type getComponentsT = (mode?: 'client' | 'server' | 'all') => Component[]
|
export type getComponentsT = (mode?: 'client' | 'server' | 'all') => Component[]
|
||||||
|
|
||||||
export default defineNuxtModule<ComponentsOptions>({
|
export default defineNuxtModule<ComponentsOptions>({
|
||||||
@ -78,6 +75,8 @@ export default defineNuxtModule<ComponentsOptions>({
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_COMPONENTS_DIRS_RE = /\/components(?:\/(?:global|islands))?$/
|
||||||
|
const STARTER_DOT_RE = /^\./g
|
||||||
// Resolve dirs
|
// Resolve dirs
|
||||||
nuxt.hook('app:resolve', async () => {
|
nuxt.hook('app:resolve', async () => {
|
||||||
// components/ dirs from all layers
|
// components/ dirs from all layers
|
||||||
|
@ -23,20 +23,54 @@ interface ComponentChunkOptions {
|
|||||||
buildDir: string
|
buildDir: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const SCRIPT_RE = /<script[^>]*>/gi
|
|
||||||
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 { 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
|
|
||||||
const KEY_RE = /:?key="[^"]"/g
|
|
||||||
|
|
||||||
function wrapWithVForDiv (code: string, vfor: string): string {
|
|
||||||
return `<div v-for="${vfor}" style="display: contents;">${code}</div>`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IslandsTransformPlugin = (options: ServerOnlyComponentTransformPluginOptions) => createUnplugin((_options, meta) => {
|
export const IslandsTransformPlugin = (options: ServerOnlyComponentTransformPluginOptions) => createUnplugin((_options, meta) => {
|
||||||
const isVite = meta.framework === 'vite'
|
const isVite = meta.framework === 'vite'
|
||||||
|
const SCRIPT_RE = /<script[^>]*>/gi
|
||||||
|
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 { 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
|
||||||
|
const KEY_RE = /:?key="[^"]"/g
|
||||||
|
|
||||||
|
function wrapWithVForDiv (code: string, vfor: string): string {
|
||||||
|
return `<div v-for="${vfor}" style="display: contents;">${code}</div>`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract attributes from a node
|
||||||
|
*/
|
||||||
|
function extractAttributes (attributes: Record<string, string>, names: string[]) {
|
||||||
|
const extracted: Record<string, string> = {}
|
||||||
|
for (const name of names) {
|
||||||
|
if (name in attributes) {
|
||||||
|
extracted[name] = attributes[name]!
|
||||||
|
delete attributes[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extracted
|
||||||
|
}
|
||||||
|
|
||||||
|
function attributeToString (attributes: Record<string, string>) {
|
||||||
|
return Object.entries(attributes).map(([name, value]) => value ? ` ${name}="${value}"` : ` ${name}`).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
function isBinding (attr: string): boolean {
|
||||||
|
return attr.startsWith(':')
|
||||||
|
}
|
||||||
|
|
||||||
|
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} }`
|
||||||
|
if (!vfor) {
|
||||||
|
return `[${data}]`
|
||||||
|
} else {
|
||||||
|
return `__vforToArray(${vfor[1]}).map(${vfor[0]} => (${data}))`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:server-only-component-transform',
|
name: 'nuxt:server-only-component-transform',
|
||||||
enforce: 'pre',
|
enforce: 'pre',
|
||||||
@ -142,40 +176,6 @@ export const IslandsTransformPlugin = (options: ServerOnlyComponentTransformPlug
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* extract attributes from a node
|
|
||||||
*/
|
|
||||||
function extractAttributes (attributes: Record<string, string>, names: string[]) {
|
|
||||||
const extracted: Record<string, string> = {}
|
|
||||||
for (const name of names) {
|
|
||||||
if (name in attributes) {
|
|
||||||
extracted[name] = attributes[name]!
|
|
||||||
delete attributes[name]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return extracted
|
|
||||||
}
|
|
||||||
|
|
||||||
function attributeToString (attributes: Record<string, string>) {
|
|
||||||
return Object.entries(attributes).map(([name, value]) => value ? ` ${name}="${value}"` : ` ${name}`).join('')
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBinding (attr: string): boolean {
|
|
||||||
return attr.startsWith(':')
|
|
||||||
}
|
|
||||||
|
|
||||||
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} }`
|
|
||||||
if (!vfor) {
|
|
||||||
return `[${data}]`
|
|
||||||
} else {
|
|
||||||
return `__vforToArray(${vfor[1]}).map(${vfor[0]} => (${data}))`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ComponentsChunkPlugin = createUnplugin((options: ComponentChunkOptions) => {
|
export const ComponentsChunkPlugin = createUnplugin((options: ComponentChunkOptions) => {
|
||||||
const { buildDir } = options
|
const { buildDir } = options
|
||||||
return {
|
return {
|
||||||
|
@ -16,11 +16,191 @@ interface TreeShakeTemplatePluginOptions {
|
|||||||
getComponents (): Component[]
|
getComponents (): Component[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const SSR_RENDER_RE = /ssrRenderComponent/
|
|
||||||
const PLACEHOLDER_EXACT_RE = /^(?:fallback|placeholder)$/
|
|
||||||
const CLIENT_ONLY_NAME_RE = /^(?:_unref\()?(?:_component_)?(?:Lazy|lazy_)?(?:client_only|ClientOnly\)?)$/
|
|
||||||
|
|
||||||
export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions) => createUnplugin(() => {
|
export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions) => createUnplugin(() => {
|
||||||
|
const SSR_RENDER_RE = /ssrRenderComponent/
|
||||||
|
const PLACEHOLDER_EXACT_RE = /^(?:fallback|placeholder)$/
|
||||||
|
const CLIENT_ONLY_NAME_RE = /^(?:_unref\()?(?:_component_)?(?:Lazy|lazy_)?(?:client_only|ClientOnly\)?)$/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find and remove all property with the name parameter from the setup return statement and the __returned__ object
|
||||||
|
*/
|
||||||
|
function removeFromSetupReturn (codeAst: Program, name: string, magicString: MagicString) {
|
||||||
|
let walkedInSetup = false
|
||||||
|
walk(codeAst, {
|
||||||
|
enter (node) {
|
||||||
|
if (walkedInSetup) {
|
||||||
|
this.skip()
|
||||||
|
} else if (node.type === 'Property' && node.key.type === 'Identifier' && node.key.name === 'setup' && (node.value.type === 'FunctionExpression' || node.value.type === 'ArrowFunctionExpression')) {
|
||||||
|
// walk into the setup function
|
||||||
|
walkedInSetup = true
|
||||||
|
if (node.value.body?.type === 'BlockStatement') {
|
||||||
|
const returnStatement = node.value.body.body.find(statement => statement.type === 'ReturnStatement') as ReturnStatement
|
||||||
|
if (returnStatement && returnStatement.argument?.type === 'ObjectExpression') {
|
||||||
|
// remove from return statement
|
||||||
|
removePropertyFromObject(returnStatement.argument, name, magicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove from __returned__
|
||||||
|
const variableList = node.value.body.body.filter((statement): statement is VariableDeclaration => statement.type === 'VariableDeclaration')
|
||||||
|
const returnedVariableDeclaration = variableList.find(declaration => declaration.declarations[0]?.id.type === 'Identifier' && declaration.declarations[0]?.id.name === '__returned__' && declaration.declarations[0]?.init?.type === 'ObjectExpression')
|
||||||
|
if (returnedVariableDeclaration) {
|
||||||
|
const init = returnedVariableDeclaration.declarations[0]?.init as ObjectExpression | undefined
|
||||||
|
if (init) {
|
||||||
|
removePropertyFromObject(init, name, magicString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove a property from an object expression
|
||||||
|
*/
|
||||||
|
function removePropertyFromObject (node: ObjectExpression, name: string, magicString: MagicString) {
|
||||||
|
for (const property of node.properties) {
|
||||||
|
if (property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === name) {
|
||||||
|
const _property = withLocations(property)
|
||||||
|
magicString.remove(_property.start, _property.end + 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is the node a call expression ssrRenderComponent()
|
||||||
|
*/
|
||||||
|
function isSsrRender (node: Node): node is CallExpression {
|
||||||
|
return node.type === 'CallExpression' && node.callee.type === 'Identifier' && SSR_RENDER_RE.test(node.callee.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeImportDeclaration (ast: Program, importName: string, magicString: MagicString): boolean {
|
||||||
|
for (const node of ast.body) {
|
||||||
|
if (node.type !== 'ImportDeclaration' || !node.specifiers) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const specifierIndex = node.specifiers.findIndex(s => s.local.name === importName)
|
||||||
|
if (specifierIndex > -1) {
|
||||||
|
if (node.specifiers!.length > 1) {
|
||||||
|
const specifier = withLocations(node.specifiers![specifierIndex])
|
||||||
|
magicString.remove(specifier.start, specifier.end + 1)
|
||||||
|
node.specifiers!.splice(specifierIndex, 1)
|
||||||
|
} else {
|
||||||
|
const specifier = withLocations(node)
|
||||||
|
magicString.remove(specifier.start, specifier.end)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* detect if the component is called else where
|
||||||
|
* ImportDeclarations and VariableDeclarations are ignored
|
||||||
|
* return the name of the component if is not called
|
||||||
|
*/
|
||||||
|
function isComponentNotCalledInSetup (code: string, id: string, name: string): string | void {
|
||||||
|
if (!name) { return }
|
||||||
|
let found = false
|
||||||
|
parseAndWalk(code, id, function (node) {
|
||||||
|
if ((node.type === 'Property' && node.key.type === 'Identifier' && node.value.type === 'FunctionExpression' && node.key.name === 'setup') || (node.type === 'FunctionDeclaration' && (node.id?.name === '_sfc_ssrRender' || node.id?.name === 'ssrRender'))) {
|
||||||
|
// walk through the setup function node or the ssrRender function
|
||||||
|
walk(node, {
|
||||||
|
enter (node) {
|
||||||
|
if (found || node.type === 'VariableDeclaration') {
|
||||||
|
this.skip()
|
||||||
|
} else if (node.type === 'Identifier' && node.name === name) {
|
||||||
|
found = true
|
||||||
|
} else if (node.type === 'MemberExpression') {
|
||||||
|
// dev only with $setup or _ctx
|
||||||
|
found = (node.property.type === 'Literal' && node.property.value === name) || (node.property.type === 'Identifier' && node.property.name === name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!found) { return name }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieve the component identifier being used on ssrRender callExpression
|
||||||
|
* @param ssrRenderNode - ssrRender callExpression
|
||||||
|
*/
|
||||||
|
function getComponentName (ssrRenderNode: CallExpression): string | undefined {
|
||||||
|
const componentCall = ssrRenderNode.arguments[0]
|
||||||
|
if (!componentCall) { return }
|
||||||
|
|
||||||
|
if (componentCall.type === 'Identifier') {
|
||||||
|
return componentCall.name
|
||||||
|
} else if (componentCall.type === 'MemberExpression') {
|
||||||
|
if (componentCall.property.type === 'Literal') {
|
||||||
|
return componentCall.property.value as string
|
||||||
|
}
|
||||||
|
} else if (componentCall.type === 'CallExpression') {
|
||||||
|
return getComponentName(componentCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove a variable declaration within the code
|
||||||
|
*/
|
||||||
|
function removeVariableDeclarator (codeAst: Program, name: string, magicString: MagicString, removedNodes: WeakSet<Node>): Node | void {
|
||||||
|
// remove variables
|
||||||
|
walk(codeAst, {
|
||||||
|
enter (node) {
|
||||||
|
if (node.type !== 'VariableDeclaration') { return }
|
||||||
|
for (const declarator of node.declarations) {
|
||||||
|
const toRemove = withLocations(findMatchingPatternToRemove(declarator.id, node, name, removedNodes))
|
||||||
|
if (toRemove) {
|
||||||
|
magicString.remove(toRemove.start, toRemove.end + 1)
|
||||||
|
removedNodes.add(toRemove)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find the Pattern to remove which the identifier is equal to the name parameter.
|
||||||
|
*/
|
||||||
|
function findMatchingPatternToRemove (node: Pattern, toRemoveIfMatched: Node, name: string, removedNodeSet: WeakSet<Node>): Node | undefined {
|
||||||
|
if (node.type === 'Identifier') {
|
||||||
|
if (node.name === name) {
|
||||||
|
return toRemoveIfMatched
|
||||||
|
}
|
||||||
|
} else if (node.type === 'ArrayPattern') {
|
||||||
|
const elements = node.elements.filter((e): e is Pattern => e !== null && !removedNodeSet.has(e))
|
||||||
|
|
||||||
|
for (const element of elements) {
|
||||||
|
const matched = findMatchingPatternToRemove(element, elements.length > 1 ? element : toRemoveIfMatched, name, removedNodeSet)
|
||||||
|
if (matched) { return matched }
|
||||||
|
}
|
||||||
|
} else if (node.type === 'ObjectPattern') {
|
||||||
|
const properties = node.properties.filter((e): e is AssignmentProperty => e.type === 'Property' && !removedNodeSet.has(e))
|
||||||
|
|
||||||
|
for (const [index, property] of properties.entries()) {
|
||||||
|
let nodeToRemove: Node = property
|
||||||
|
if (properties.length < 2) {
|
||||||
|
nodeToRemove = toRemoveIfMatched
|
||||||
|
}
|
||||||
|
|
||||||
|
const matched = findMatchingPatternToRemove(property.value, nodeToRemove, name, removedNodeSet)
|
||||||
|
if (matched) {
|
||||||
|
if (matched === property) {
|
||||||
|
properties.splice(index, 1)
|
||||||
|
}
|
||||||
|
return matched
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (node.type === 'AssignmentPattern') {
|
||||||
|
const matched = findMatchingPatternToRemove(node.left, toRemoveIfMatched, name, removedNodeSet)
|
||||||
|
if (matched) { return matched }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const regexpMap = new WeakMap<Component[], [RegExp, RegExp, string[]]>()
|
const regexpMap = new WeakMap<Component[], [RegExp, RegExp, string[]]>()
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:tree-shake-template',
|
name: 'nuxt:tree-shake-template',
|
||||||
@ -109,183 +289,3 @@ export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* find and remove all property with the name parameter from the setup return statement and the __returned__ object
|
|
||||||
*/
|
|
||||||
function removeFromSetupReturn (codeAst: Program, name: string, magicString: MagicString) {
|
|
||||||
let walkedInSetup = false
|
|
||||||
walk(codeAst, {
|
|
||||||
enter (node) {
|
|
||||||
if (walkedInSetup) {
|
|
||||||
this.skip()
|
|
||||||
} else if (node.type === 'Property' && node.key.type === 'Identifier' && node.key.name === 'setup' && (node.value.type === 'FunctionExpression' || node.value.type === 'ArrowFunctionExpression')) {
|
|
||||||
// walk into the setup function
|
|
||||||
walkedInSetup = true
|
|
||||||
if (node.value.body?.type === 'BlockStatement') {
|
|
||||||
const returnStatement = node.value.body.body.find(statement => statement.type === 'ReturnStatement') as ReturnStatement
|
|
||||||
if (returnStatement && returnStatement.argument?.type === 'ObjectExpression') {
|
|
||||||
// remove from return statement
|
|
||||||
removePropertyFromObject(returnStatement.argument, name, magicString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from __returned__
|
|
||||||
const variableList = node.value.body.body.filter((statement): statement is VariableDeclaration => statement.type === 'VariableDeclaration')
|
|
||||||
const returnedVariableDeclaration = variableList.find(declaration => declaration.declarations[0]?.id.type === 'Identifier' && declaration.declarations[0]?.id.name === '__returned__' && declaration.declarations[0]?.init?.type === 'ObjectExpression')
|
|
||||||
if (returnedVariableDeclaration) {
|
|
||||||
const init = returnedVariableDeclaration.declarations[0]?.init as ObjectExpression | undefined
|
|
||||||
if (init) {
|
|
||||||
removePropertyFromObject(init, name, magicString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove a property from an object expression
|
|
||||||
*/
|
|
||||||
function removePropertyFromObject (node: ObjectExpression, name: string, magicString: MagicString) {
|
|
||||||
for (const property of node.properties) {
|
|
||||||
if (property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === name) {
|
|
||||||
const _property = withLocations(property)
|
|
||||||
magicString.remove(_property.start, _property.end + 1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* is the node a call expression ssrRenderComponent()
|
|
||||||
*/
|
|
||||||
function isSsrRender (node: Node): node is CallExpression {
|
|
||||||
return node.type === 'CallExpression' && node.callee.type === 'Identifier' && SSR_RENDER_RE.test(node.callee.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeImportDeclaration (ast: Program, importName: string, magicString: MagicString): boolean {
|
|
||||||
for (const node of ast.body) {
|
|
||||||
if (node.type !== 'ImportDeclaration' || !node.specifiers) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const specifierIndex = node.specifiers.findIndex(s => s.local.name === importName)
|
|
||||||
if (specifierIndex > -1) {
|
|
||||||
if (node.specifiers!.length > 1) {
|
|
||||||
const specifier = withLocations(node.specifiers![specifierIndex])
|
|
||||||
magicString.remove(specifier.start, specifier.end + 1)
|
|
||||||
node.specifiers!.splice(specifierIndex, 1)
|
|
||||||
} else {
|
|
||||||
const specifier = withLocations(node)
|
|
||||||
magicString.remove(specifier.start, specifier.end)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* detect if the component is called else where
|
|
||||||
* ImportDeclarations and VariableDeclarations are ignored
|
|
||||||
* return the name of the component if is not called
|
|
||||||
*/
|
|
||||||
function isComponentNotCalledInSetup (code: string, id: string, name: string): string | void {
|
|
||||||
if (!name) { return }
|
|
||||||
let found = false
|
|
||||||
parseAndWalk(code, id, function (node) {
|
|
||||||
if ((node.type === 'Property' && node.key.type === 'Identifier' && node.value.type === 'FunctionExpression' && node.key.name === 'setup') || (node.type === 'FunctionDeclaration' && (node.id?.name === '_sfc_ssrRender' || node.id?.name === 'ssrRender'))) {
|
|
||||||
// walk through the setup function node or the ssrRender function
|
|
||||||
walk(node, {
|
|
||||||
enter (node) {
|
|
||||||
if (found || node.type === 'VariableDeclaration') {
|
|
||||||
this.skip()
|
|
||||||
} else if (node.type === 'Identifier' && node.name === name) {
|
|
||||||
found = true
|
|
||||||
} else if (node.type === 'MemberExpression') {
|
|
||||||
// dev only with $setup or _ctx
|
|
||||||
found = (node.property.type === 'Literal' && node.property.value === name) || (node.property.type === 'Identifier' && node.property.name === name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (!found) { return name }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* retrieve the component identifier being used on ssrRender callExpression
|
|
||||||
* @param ssrRenderNode - ssrRender callExpression
|
|
||||||
*/
|
|
||||||
function getComponentName (ssrRenderNode: CallExpression): string | undefined {
|
|
||||||
const componentCall = ssrRenderNode.arguments[0]
|
|
||||||
if (!componentCall) { return }
|
|
||||||
|
|
||||||
if (componentCall.type === 'Identifier') {
|
|
||||||
return componentCall.name
|
|
||||||
} else if (componentCall.type === 'MemberExpression') {
|
|
||||||
if (componentCall.property.type === 'Literal') {
|
|
||||||
return componentCall.property.value as string
|
|
||||||
}
|
|
||||||
} else if (componentCall.type === 'CallExpression') {
|
|
||||||
return getComponentName(componentCall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove a variable declaration within the code
|
|
||||||
*/
|
|
||||||
function removeVariableDeclarator (codeAst: Program, name: string, magicString: MagicString, removedNodes: WeakSet<Node>): Node | void {
|
|
||||||
// remove variables
|
|
||||||
walk(codeAst, {
|
|
||||||
enter (node) {
|
|
||||||
if (node.type !== 'VariableDeclaration') { return }
|
|
||||||
for (const declarator of node.declarations) {
|
|
||||||
const toRemove = withLocations(findMatchingPatternToRemove(declarator.id, node, name, removedNodes))
|
|
||||||
if (toRemove) {
|
|
||||||
magicString.remove(toRemove.start, toRemove.end + 1)
|
|
||||||
removedNodes.add(toRemove)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* find the Pattern to remove which the identifier is equal to the name parameter.
|
|
||||||
*/
|
|
||||||
function findMatchingPatternToRemove (node: Pattern, toRemoveIfMatched: Node, name: string, removedNodeSet: WeakSet<Node>): Node | undefined {
|
|
||||||
if (node.type === 'Identifier') {
|
|
||||||
if (node.name === name) {
|
|
||||||
return toRemoveIfMatched
|
|
||||||
}
|
|
||||||
} else if (node.type === 'ArrayPattern') {
|
|
||||||
const elements = node.elements.filter((e): e is Pattern => e !== null && !removedNodeSet.has(e))
|
|
||||||
|
|
||||||
for (const element of elements) {
|
|
||||||
const matched = findMatchingPatternToRemove(element, elements.length > 1 ? element : toRemoveIfMatched, name, removedNodeSet)
|
|
||||||
if (matched) { return matched }
|
|
||||||
}
|
|
||||||
} else if (node.type === 'ObjectPattern') {
|
|
||||||
const properties = node.properties.filter((e): e is AssignmentProperty => e.type === 'Property' && !removedNodeSet.has(e))
|
|
||||||
|
|
||||||
for (const [index, property] of properties.entries()) {
|
|
||||||
let nodeToRemove: Node = property
|
|
||||||
if (properties.length < 2) {
|
|
||||||
nodeToRemove = toRemoveIfMatched
|
|
||||||
}
|
|
||||||
|
|
||||||
const matched = findMatchingPatternToRemove(property.value, nodeToRemove, name, removedNodeSet)
|
|
||||||
if (matched) {
|
|
||||||
if (matched === property) {
|
|
||||||
properties.splice(index, 1)
|
|
||||||
}
|
|
||||||
return matched
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (node.type === 'AssignmentPattern') {
|
|
||||||
const matched = findMatchingPatternToRemove(node.left, toRemoveIfMatched, name, removedNodeSet)
|
|
||||||
if (matched) { return matched }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -9,10 +9,6 @@ import type { Component, ComponentsDir } from 'nuxt/schema'
|
|||||||
import { QUOTE_RE, resolveComponentNameSegments } from '../core/utils'
|
import { QUOTE_RE, resolveComponentNameSegments } from '../core/utils'
|
||||||
import { logger } from '../utils'
|
import { logger } from '../utils'
|
||||||
|
|
||||||
const ISLAND_RE = /\.island(?:\.global)?$/
|
|
||||||
const GLOBAL_RE = /\.global(?:\.island)?$/
|
|
||||||
const COMPONENT_MODE_RE = /(?<=\.)(client|server)(\.global|\.island)*$/
|
|
||||||
const MODE_REPLACEMENT_RE = /(\.(client|server))?(\.global|\.island)*$/
|
|
||||||
/**
|
/**
|
||||||
* Scan the components inside different components folders
|
* Scan the components inside different components folders
|
||||||
* and return a unique list of components
|
* and return a unique list of components
|
||||||
@ -30,6 +26,11 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr
|
|||||||
// All scanned paths
|
// All scanned paths
|
||||||
const scannedPaths: string[] = []
|
const scannedPaths: string[] = []
|
||||||
|
|
||||||
|
const ISLAND_RE = /\.island(?:\.global)?$/
|
||||||
|
const GLOBAL_RE = /\.global(?:\.island)?$/
|
||||||
|
const COMPONENT_MODE_RE = /(?<=\.)(client|server)(\.global|\.island)*$/
|
||||||
|
const MODE_REPLACEMENT_RE = /(\.(client|server))?(\.global|\.island)*$/
|
||||||
|
|
||||||
for (const dir of dirs) {
|
for (const dir of dirs) {
|
||||||
if (dir.enabled === false) {
|
if (dir.enabled === false) {
|
||||||
continue
|
continue
|
||||||
|
@ -102,10 +102,10 @@ export const componentsIslandsTemplate: NuxtTemplate = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const NON_VUE_RE = /\b\.(?!vue)\w+$/g
|
|
||||||
export const componentsTypeTemplate = {
|
export const componentsTypeTemplate = {
|
||||||
filename: 'components.d.ts' as const,
|
filename: 'components.d.ts' as const,
|
||||||
getContents: ({ app, nuxt }) => {
|
getContents: ({ app, nuxt }) => {
|
||||||
|
const NON_VUE_RE = /\b\.(?!vue)\w+$/g
|
||||||
const buildDir = nuxt.options.buildDir
|
const buildDir = nuxt.options.buildDir
|
||||||
const componentTypes = app.components.filter(c => !c.island).map((c) => {
|
const componentTypes = app.components.filter(c => !c.island).map((c) => {
|
||||||
const type = `typeof ${genDynamicImport(isAbsolute(c.filePath)
|
const type = `typeof ${genDynamicImport(isAbsolute(c.filePath)
|
||||||
|
@ -26,9 +26,9 @@ const logLevelMapReverse = {
|
|||||||
verbose: 3,
|
verbose: 3,
|
||||||
} satisfies Record<NuxtOptions['logLevel'], NitroConfig['logLevel']>
|
} satisfies Record<NuxtOptions['logLevel'], NitroConfig['logLevel']>
|
||||||
|
|
||||||
const NODE_MODULES_RE = /(?<=\/)node_modules\/(.+)$/
|
|
||||||
const PNPM_NODE_MODULES_RE = /\.pnpm\/.+\/node_modules\/(.+)$/
|
|
||||||
export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||||
|
const NODE_MODULES_RE = /(?<=\/)node_modules\/(.+)$/
|
||||||
|
const PNPM_NODE_MODULES_RE = /\.pnpm\/.+\/node_modules\/(.+)$/
|
||||||
// Resolve config
|
// Resolve config
|
||||||
const excludePaths = nuxt.options._layers
|
const excludePaths = nuxt.options._layers
|
||||||
.flatMap(l => [
|
.flatMap(l => [
|
||||||
|
@ -725,7 +725,7 @@ export default defineNuxtPlugin({
|
|||||||
})`,
|
})`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
||||||
nuxt.hooks.hook('builder:watch', (event, relativePath) => {
|
nuxt.hooks.hook('builder:watch', (event, relativePath) => {
|
||||||
const path = resolve(nuxt.options.srcDir, relativePath)
|
const path = resolve(nuxt.options.srcDir, relativePath)
|
||||||
// Local module patterns
|
// Local module patterns
|
||||||
@ -914,9 +914,6 @@ export async function checkDependencyVersion (name: string, nuxtVersion: string)
|
|||||||
console.warn(`[nuxt] Expected \`${name}\` to be at least \`${nuxtVersion}\` but got \`${version}\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`)
|
console.warn(`[nuxt] Expected \`${name}\` to be at least \`${nuxtVersion}\` but got \`${version}\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
|
||||||
|
|
||||||
function deduplicateArray<T = unknown> (maybeArray: T): T {
|
function deduplicateArray<T = unknown> (maybeArray: T): T {
|
||||||
if (!Array.isArray(maybeArray)) { return maybeArray }
|
if (!Array.isArray(maybeArray)) { return maybeArray }
|
||||||
|
|
||||||
|
@ -16,11 +16,6 @@ interface ComposableKeysOptions {
|
|||||||
composables: Array<{ name: string, source?: string | RegExp, argumentLength: number }>
|
composables: Array<{ name: string, source?: string | RegExp, argumentLength: number }>
|
||||||
}
|
}
|
||||||
|
|
||||||
const stringTypes: Array<string | undefined> = ['Literal', 'TemplateLiteral']
|
|
||||||
const NUXT_LIB_RE = /node_modules\/(?:nuxt|nuxt3|nuxt-nightly)\//
|
|
||||||
const SUPPORTED_EXT_RE = /\.(?:m?[jt]sx?|vue)/
|
|
||||||
const SCRIPT_RE = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i
|
|
||||||
|
|
||||||
export const ComposableKeysPlugin = (options: ComposableKeysOptions) => createUnplugin(() => {
|
export const ComposableKeysPlugin = (options: ComposableKeysOptions) => createUnplugin(() => {
|
||||||
const composableMeta: Record<string, any> = {}
|
const composableMeta: Record<string, any> = {}
|
||||||
const composableLengths = new Set<number>()
|
const composableLengths = new Set<number>()
|
||||||
@ -34,6 +29,10 @@ export const ComposableKeysPlugin = (options: ComposableKeysOptions) => createUn
|
|||||||
const maxLength = Math.max(...composableLengths)
|
const maxLength = Math.max(...composableLengths)
|
||||||
const KEYED_FUNCTIONS_RE = new RegExp(`\\b(${[...keyedFunctions].map(f => escapeRE(f)).join('|')})\\b`)
|
const KEYED_FUNCTIONS_RE = new RegExp(`\\b(${[...keyedFunctions].map(f => escapeRE(f)).join('|')})\\b`)
|
||||||
|
|
||||||
|
const stringTypes: Array<string | undefined> = ['Literal', 'TemplateLiteral']
|
||||||
|
const NUXT_LIB_RE = /node_modules\/(?:nuxt|nuxt3|nuxt-nightly)\//
|
||||||
|
const SUPPORTED_EXT_RE = /\.(?:m?[jt]sx?|vue)/
|
||||||
|
const SCRIPT_RE = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:composable-keys',
|
name: 'nuxt:composable-keys',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
|
@ -7,10 +7,9 @@ interface DevOnlyPluginOptions {
|
|||||||
sourcemap?: boolean
|
sourcemap?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEVONLY_COMP_SINGLE_RE = /<(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>[\s\S]*?<\/(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>/
|
|
||||||
const DEVONLY_COMP_RE = /<(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>[\s\S]*?<\/(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>/g
|
|
||||||
|
|
||||||
export const DevOnlyPlugin = (options: DevOnlyPluginOptions) => createUnplugin(() => {
|
export const DevOnlyPlugin = (options: DevOnlyPluginOptions) => createUnplugin(() => {
|
||||||
|
const DEVONLY_COMP_SINGLE_RE = /<(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>[\s\S]*?<\/(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>/
|
||||||
|
const DEVONLY_COMP_RE = /<(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>[\s\S]*?<\/(?:dev-only|DevOnly|lazy-dev-only|LazyDevOnly)>/g
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:server-devonly:transform',
|
name: 'nuxt:server-devonly:transform',
|
||||||
enforce: 'pre',
|
enforce: 'pre',
|
||||||
|
@ -11,9 +11,6 @@ interface LayerAliasingOptions {
|
|||||||
layers: NuxtConfigLayer[]
|
layers: NuxtConfigLayer[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALIAS_RE = /(?<=['"])[~@]{1,2}(?=\/)/g
|
|
||||||
const ALIAS_RE_SINGLE = /(?<=['"])[~@]{1,2}(?=\/)/
|
|
||||||
|
|
||||||
export const LayerAliasingPlugin = (options: LayerAliasingOptions) => createUnplugin((_options, meta) => {
|
export const LayerAliasingPlugin = (options: LayerAliasingOptions) => createUnplugin((_options, meta) => {
|
||||||
const aliases: Record<string, Record<string, string>> = {}
|
const aliases: Record<string, Record<string, string>> = {}
|
||||||
for (const layer of options.layers) {
|
for (const layer of options.layers) {
|
||||||
@ -27,6 +24,8 @@ export const LayerAliasingPlugin = (options: LayerAliasingOptions) => createUnpl
|
|||||||
'@@': layer.config?.alias?.['@@'] || rootDir,
|
'@@': layer.config?.alias?.['@@'] || rootDir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const ALIAS_RE = /(?<=['"])[~@]{1,2}(?=\/)/g
|
||||||
|
const ALIAS_RE_SINGLE = /(?<=['"])[~@]{1,2}(?=\/)/
|
||||||
const layers = Object.keys(aliases).sort((a, b) => b.length - a.length)
|
const layers = Object.keys(aliases).sort((a, b) => b.length - a.length)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -99,13 +99,13 @@ export const serverPluginTemplate: NuxtTemplate = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const TS_RE = /\.[cm]?tsx?$/
|
|
||||||
const JS_LETTER_RE = /\.(?<letter>[cm])?jsx?$/
|
|
||||||
const JS_RE = /\.[cm]jsx?$/
|
|
||||||
const JS_CAPTURE_RE = /\.[cm](jsx?)$/
|
|
||||||
export const pluginsDeclaration: NuxtTemplate = {
|
export const pluginsDeclaration: NuxtTemplate = {
|
||||||
filename: 'types/plugins.d.ts',
|
filename: 'types/plugins.d.ts',
|
||||||
getContents: async ({ nuxt, app }) => {
|
getContents: async ({ nuxt, app }) => {
|
||||||
|
const TS_RE = /\.[cm]?tsx?$/
|
||||||
|
const JS_LETTER_RE = /\.(?<letter>[cm])?jsx?$/
|
||||||
|
const JS_RE = /\.[cm]jsx?$/
|
||||||
|
const JS_CAPTURE_RE = /\.[cm](jsx?)$/
|
||||||
const EXTENSION_RE = new RegExp(`(?<=\\w)(${nuxt.options.extensions.map(e => escapeRE(e)).join('|')})$`, 'g')
|
const EXTENSION_RE = new RegExp(`(?<=\\w)(${nuxt.options.extensions.map(e => escapeRE(e)).join('|')})$`, 'g')
|
||||||
|
|
||||||
const typesDir = join(nuxt.options.buildDir, 'types')
|
const typesDir = join(nuxt.options.buildDir, 'types')
|
||||||
@ -177,11 +177,11 @@ export { }
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const IMPORT_NAME_RE = /\.\w+$/
|
|
||||||
const GIT_RE = /^git\+/
|
|
||||||
export const schemaTemplate: NuxtTemplate = {
|
export const schemaTemplate: NuxtTemplate = {
|
||||||
filename: 'types/schema.d.ts',
|
filename: 'types/schema.d.ts',
|
||||||
getContents: async ({ nuxt }) => {
|
getContents: async ({ nuxt }) => {
|
||||||
|
const IMPORT_NAME_RE = /\.\w+$/
|
||||||
|
const GIT_RE = /^git\+/
|
||||||
const relativeRoot = relative(resolve(nuxt.options.buildDir, 'types'), nuxt.options.rootDir)
|
const relativeRoot = relative(resolve(nuxt.options.buildDir, 'types'), nuxt.options.rootDir)
|
||||||
const getImportName = (name: string) => (name[0] === '.' ? './' + join(relativeRoot, name) : name).replace(IMPORT_NAME_RE, '')
|
const getImportName = (name: string) => (name[0] === '.' ? './' + join(relativeRoot, name) : name).replace(IMPORT_NAME_RE, '')
|
||||||
|
|
||||||
@ -538,13 +538,12 @@ export const nuxtConfigTemplate: NuxtTemplate = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const TYPE_FILENAME_RE = /\.([cm])?[jt]s$/
|
|
||||||
const DECLARATION_RE = /\.d\.[cm]?ts$/
|
|
||||||
export const buildTypeTemplate: NuxtTemplate = {
|
export const buildTypeTemplate: NuxtTemplate = {
|
||||||
filename: 'types/build.d.ts',
|
filename: 'types/build.d.ts',
|
||||||
getContents ({ app }) {
|
getContents ({ app }) {
|
||||||
|
const TYPE_FILENAME_RE = /\.([cm])?[jt]s$/
|
||||||
|
const DECLARATION_RE = /\.d\.[cm]?ts$/
|
||||||
let declarations = ''
|
let declarations = ''
|
||||||
|
|
||||||
for (const file of app.templates) {
|
for (const file of app.templates) {
|
||||||
if (file.write || !file.filename || DECLARATION_RE.test(file.filename)) {
|
if (file.write || !file.filename || DECLARATION_RE.test(file.filename)) {
|
||||||
continue
|
continue
|
||||||
|
@ -7,10 +7,9 @@ import type { ImportsOptions } from 'nuxt/schema'
|
|||||||
import { isJS, isVue } from '../core/utils'
|
import { isJS, isVue } from '../core/utils'
|
||||||
import { installNuxtModule } from '../core/features'
|
import { installNuxtModule } from '../core/features'
|
||||||
|
|
||||||
const NODE_MODULES_RE = /[\\/]node_modules[\\/]/
|
|
||||||
const IMPORTS_RE = /(['"])#imports\1/
|
|
||||||
|
|
||||||
export const TransformPlugin = ({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial<ImportsOptions>, sourcemap?: boolean }) => createUnplugin(() => {
|
export const TransformPlugin = ({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial<ImportsOptions>, sourcemap?: boolean }) => createUnplugin(() => {
|
||||||
|
const NODE_MODULES_RE = /[\\/]node_modules[\\/]/
|
||||||
|
const IMPORTS_RE = /(['"])#imports\1/
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:imports-transform',
|
name: 'nuxt:imports-transform',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
|
@ -20,8 +20,6 @@ import { extractRouteRules, getMappedPages } from './route-rules'
|
|||||||
import { PageMetaPlugin } from './plugins/page-meta'
|
import { PageMetaPlugin } from './plugins/page-meta'
|
||||||
import { RouteInjectionPlugin } from './plugins/route-injection'
|
import { RouteInjectionPlugin } from './plugins/route-injection'
|
||||||
|
|
||||||
const OPTIONAL_PARAM_RE = /^\/?:.*(?:\?|\(\.\*\)\*)$/
|
|
||||||
|
|
||||||
export default defineNuxtModule({
|
export default defineNuxtModule({
|
||||||
meta: {
|
meta: {
|
||||||
name: 'nuxt:pages',
|
name: 'nuxt:pages',
|
||||||
@ -305,6 +303,7 @@ export default defineNuxtModule({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const OPTIONAL_PARAM_RE = /^\/?:.*(?:\?|\(\.\*\)\*)$/
|
||||||
// Record all pages for use in prerendering
|
// Record all pages for use in prerendering
|
||||||
const prerenderRoutes = new Set<string>()
|
const prerenderRoutes = new Set<string>()
|
||||||
|
|
||||||
|
@ -24,19 +24,20 @@ interface PageMetaPluginOptions {
|
|||||||
routesPath?: string
|
routesPath?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const HAS_MACRO_RE = /\bdefinePageMeta\s*\(\s*/
|
export const PageMetaPlugin = (options: PageMetaPluginOptions = {}) => createUnplugin(() => {
|
||||||
|
const HAS_MACRO_RE = /\bdefinePageMeta\s*\(\s*/
|
||||||
|
|
||||||
const CODE_EMPTY = `
|
const CODE_EMPTY = `
|
||||||
const __nuxt_page_meta = null
|
const __nuxt_page_meta = null
|
||||||
export default __nuxt_page_meta
|
export default __nuxt_page_meta
|
||||||
`
|
`
|
||||||
|
|
||||||
const CODE_DEV_EMPTY = `
|
const CODE_DEV_EMPTY = `
|
||||||
const __nuxt_page_meta = {}
|
const __nuxt_page_meta = {}
|
||||||
export default __nuxt_page_meta
|
export default __nuxt_page_meta
|
||||||
`
|
`
|
||||||
|
|
||||||
const CODE_HMR = `
|
const CODE_HMR = `
|
||||||
// Vite
|
// Vite
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
import.meta.hot.accept(mod => {
|
import.meta.hot.accept(mod => {
|
||||||
@ -49,8 +50,28 @@ if (import.meta.webpackHot) {
|
|||||||
if (err) { window.location = window.location.href }
|
if (err) { window.location = window.location.href }
|
||||||
})
|
})
|
||||||
}`
|
}`
|
||||||
|
// https://github.com/vuejs/vue-loader/pull/1911
|
||||||
|
// https://github.com/vitejs/vite/issues/8473
|
||||||
|
const QUERY_START_RE = /^\?/
|
||||||
|
const MACRO_RE = /¯o=true/
|
||||||
|
function rewriteQuery (id: string) {
|
||||||
|
return id.replace(/\?.+$/, r => '?macro=true&' + r.replace(QUERY_START_RE, '').replace(MACRO_RE, ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseMacroQuery (id: string) {
|
||||||
|
const { search } = parseURL(decodeURIComponent(isAbsolute(id) ? pathToFileURL(id).href : id).replace(/\?macro=true$/, ''))
|
||||||
|
const query = parseQuery(search)
|
||||||
|
if (id.includes('?macro=true')) {
|
||||||
|
return { macro: 'true', ...query }
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUOTED_SPECIFIER_RE = /(["']).*\1/
|
||||||
|
function getQuotedSpecifier (id: string) {
|
||||||
|
return id.match(QUOTED_SPECIFIER_RE)?.[0]
|
||||||
|
}
|
||||||
|
|
||||||
export const PageMetaPlugin = (options: PageMetaPluginOptions = {}) => createUnplugin(() => {
|
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:pages-macros-transform',
|
name: 'nuxt:pages-macros-transform',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
@ -301,25 +322,3 @@ export const PageMetaPlugin = (options: PageMetaPluginOptions = {}) => createUnp
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// https://github.com/vuejs/vue-loader/pull/1911
|
|
||||||
// https://github.com/vitejs/vite/issues/8473
|
|
||||||
const QUERY_START_RE = /^\?/
|
|
||||||
const MACRO_RE = /¯o=true/
|
|
||||||
function rewriteQuery (id: string) {
|
|
||||||
return id.replace(/\?.+$/, r => '?macro=true&' + r.replace(QUERY_START_RE, '').replace(MACRO_RE, ''))
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseMacroQuery (id: string) {
|
|
||||||
const { search } = parseURL(decodeURIComponent(isAbsolute(id) ? pathToFileURL(id).href : id).replace(/\?macro=true$/, ''))
|
|
||||||
const query = parseQuery(search)
|
|
||||||
if (id.includes('?macro=true')) {
|
|
||||||
return { macro: 'true', ...query }
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
const QUOTED_SPECIFIER_RE = /(["']).*\1/
|
|
||||||
function getQuotedSpecifier (id: string) {
|
|
||||||
return id.match(QUOTED_SPECIFIER_RE)?.[0]
|
|
||||||
}
|
|
||||||
|
@ -4,12 +4,11 @@ import type { Nuxt } from '@nuxt/schema'
|
|||||||
import { stripLiteral } from 'strip-literal'
|
import { stripLiteral } from 'strip-literal'
|
||||||
import { isVue } from '../../core/utils'
|
import { isVue } from '../../core/utils'
|
||||||
|
|
||||||
const INJECTION_RE_TEMPLATE = /\b_ctx\.\$route\b/g
|
|
||||||
const INJECTION_RE_SCRIPT = /\bthis\.\$route\b/g
|
|
||||||
|
|
||||||
const INJECTION_SINGLE_RE = /\bthis\.\$route\b|\b_ctx\.\$route\b/
|
|
||||||
|
|
||||||
export const RouteInjectionPlugin = (nuxt: Nuxt) => createUnplugin(() => {
|
export const RouteInjectionPlugin = (nuxt: Nuxt) => createUnplugin(() => {
|
||||||
|
const INJECTION_RE_TEMPLATE = /\b_ctx\.\$route\b/g
|
||||||
|
const INJECTION_RE_SCRIPT = /\bthis\.\$route\b/g
|
||||||
|
|
||||||
|
const INJECTION_SINGLE_RE = /\bthis\.\$route\b|\b_ctx\.\$route\b/
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:route-injection-plugin',
|
name: 'nuxt:route-injection-plugin',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { KeepAlive, h } from 'vue'
|
import { KeepAlive, h } from 'vue'
|
||||||
import type { RouteLocationMatched, RouteLocationNormalizedLoaded, RouterView } from 'vue-router'
|
import type { RouteLocationMatched, RouteLocationNormalizedLoaded, RouterView } from 'vue-router'
|
||||||
|
import { ROUTE_KEY_NORMAL_RE, ROUTE_KEY_PARENTHESES_RE, ROUTE_KEY_SYMBOLS_RE } from '../../utils'
|
||||||
|
|
||||||
type InstanceOf<T> = T extends new (...args: any[]) => infer R ? R : never
|
type InstanceOf<T> = T extends new (...args: any[]) => infer R ? R : never
|
||||||
type RouterViewSlot = Exclude<InstanceOf<typeof RouterView>['$slots']['default'], undefined>
|
type RouterViewSlot = Exclude<InstanceOf<typeof RouterView>['$slots']['default'], undefined>
|
||||||
export type RouterViewSlotProps = Parameters<RouterViewSlot>[0]
|
export type RouterViewSlotProps = Parameters<RouterViewSlot>[0]
|
||||||
|
|
||||||
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
|
||||||
const ROUTE_KEY_SYMBOLS_RE = /(:\w+)[?+*]/g
|
|
||||||
const ROUTE_KEY_NORMAL_RE = /:\w+/g
|
|
||||||
const interpolatePath = (route: RouteLocationNormalizedLoaded, match: RouteLocationMatched) => {
|
const interpolatePath = (route: RouteLocationNormalizedLoaded, match: RouteLocationMatched) => {
|
||||||
return match.path
|
return match.path
|
||||||
.replace(ROUTE_KEY_PARENTHESES_RE, '$1')
|
.replace(ROUTE_KEY_PARENTHESES_RE, '$1')
|
||||||
|
@ -10,4 +10,8 @@ export async function isDirectory (path: string) {
|
|||||||
return (await fsp.lstat(path)).isDirectory()
|
return (await fsp.lstat(path)).isDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
||||||
|
export const ROUTE_KEY_SYMBOLS_RE = /(:\w+)[?+*]/g
|
||||||
|
export const ROUTE_KEY_NORMAL_RE = /:\w+/g
|
||||||
|
|
||||||
export const logger = useLogger('nuxt')
|
export const logger = useLogger('nuxt')
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.34.6",
|
"rollup": "4.34.8",
|
||||||
"unbuild": "3.3.1",
|
"unbuild": "3.3.1",
|
||||||
"vue": "3.5.13"
|
"vue": "3.5.13"
|
||||||
},
|
},
|
||||||
|
@ -40,12 +40,12 @@
|
|||||||
"@types/rollup-plugin-visualizer": "4.2.4",
|
"@types/rollup-plugin-visualizer": "4.2.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"@unhead/schema": "1.11.18",
|
"@unhead/schema": "1.11.19",
|
||||||
"@vitejs/plugin-vue": "5.2.1",
|
"@vitejs/plugin-vue": "5.2.1",
|
||||||
"@vitejs/plugin-vue-jsx": "4.1.1",
|
"@vitejs/plugin-vue-jsx": "4.1.1",
|
||||||
"@vue/compiler-core": "3.5.13",
|
"@vue/compiler-core": "3.5.13",
|
||||||
"@vue/compiler-sfc": "3.5.13",
|
"@vue/compiler-sfc": "3.5.13",
|
||||||
"@vue/language-core": "2.2.0",
|
"@vue/language-core": "2.2.2",
|
||||||
"c12": "2.0.2",
|
"c12": "2.0.2",
|
||||||
"chokidar": "4.0.3",
|
"chokidar": "4.0.3",
|
||||||
"compatx": "0.1.8",
|
"compatx": "0.1.8",
|
||||||
@ -61,11 +61,11 @@
|
|||||||
"ofetch": "1.4.1",
|
"ofetch": "1.4.1",
|
||||||
"pkg-types": "1.3.1",
|
"pkg-types": "1.3.1",
|
||||||
"postcss": "8.5.2",
|
"postcss": "8.5.2",
|
||||||
"sass-loader": "16.0.4",
|
"sass-loader": "16.0.5",
|
||||||
"scule": "1.3.0",
|
"scule": "1.3.0",
|
||||||
"unbuild": "3.3.1",
|
"unbuild": "3.3.1",
|
||||||
"unctx": "2.4.1",
|
"unctx": "2.4.1",
|
||||||
"unimport": "4.1.1",
|
"unimport": "4.1.2",
|
||||||
"untyped": "1.5.2",
|
"untyped": "1.5.2",
|
||||||
"vite": "6.1.0",
|
"vite": "6.1.0",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
"prerender": "pnpm build && jiti ./lib/prerender"
|
"prerender": "pnpm build && jiti ./lib/prerender"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@unocss/reset": "65.4.3",
|
"@unocss/reset": "66.0.0",
|
||||||
"beasties": "0.2.0",
|
"beasties": "0.2.0",
|
||||||
"html-validate": "9.2.2",
|
"html-validate": "9.3.0",
|
||||||
"htmlnano": "2.1.1",
|
"htmlnano": "2.1.1",
|
||||||
"jiti": "2.4.2",
|
"jiti": "2.4.2",
|
||||||
"knitwork": "1.2.0",
|
"knitwork": "1.2.0",
|
||||||
@ -28,8 +28,8 @@
|
|||||||
"scule": "1.3.0",
|
"scule": "1.3.0",
|
||||||
"svgo": "3.3.2",
|
"svgo": "3.3.2",
|
||||||
"tinyexec": "0.3.2",
|
"tinyexec": "0.3.2",
|
||||||
"tinyglobby": "0.2.10",
|
"tinyglobby": "0.2.11",
|
||||||
"unocss": "65.4.3",
|
"unocss": "66.0.0",
|
||||||
"vite": "6.1.0"
|
"vite": "6.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"rollup": "4.34.6",
|
"rollup": "4.34.8",
|
||||||
"unbuild": "3.3.1",
|
"unbuild": "3.3.1",
|
||||||
"vue": "3.5.13"
|
"vue": "3.5.13"
|
||||||
},
|
},
|
||||||
|
@ -7,11 +7,6 @@ import { dirname, relative } from 'pathe'
|
|||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import { isCSSRequest } from 'vite'
|
import { isCSSRequest } from 'vite'
|
||||||
|
|
||||||
const PREFIX = 'virtual:public?'
|
|
||||||
const CSS_URL_RE = /url\((\/[^)]+)\)/g
|
|
||||||
const CSS_URL_SINGLE_RE = /url\(\/[^)]+\)/
|
|
||||||
const RENDER_CHUNK_RE = /(?<= = )['"`]/
|
|
||||||
|
|
||||||
interface VitePublicDirsPluginOptions {
|
interface VitePublicDirsPluginOptions {
|
||||||
dev?: boolean
|
dev?: boolean
|
||||||
sourcemap?: boolean
|
sourcemap?: boolean
|
||||||
@ -21,6 +16,11 @@ interface VitePublicDirsPluginOptions {
|
|||||||
export const VitePublicDirsPlugin = createUnplugin((options: VitePublicDirsPluginOptions) => {
|
export const VitePublicDirsPlugin = createUnplugin((options: VitePublicDirsPluginOptions) => {
|
||||||
const { resolveFromPublicAssets } = useResolveFromPublicAssets()
|
const { resolveFromPublicAssets } = useResolveFromPublicAssets()
|
||||||
|
|
||||||
|
const PREFIX = 'virtual:public?'
|
||||||
|
const CSS_URL_RE = /url\((\/[^)]+)\)/g
|
||||||
|
const CSS_URL_SINGLE_RE = /url\(\/[^)]+\)/
|
||||||
|
const RENDER_CHUNK_RE = /(?<= = )['"`]/
|
||||||
|
|
||||||
const devTransformPlugin: UnpluginOptions = {
|
const devTransformPlugin: UnpluginOptions = {
|
||||||
name: 'nuxt:vite-public-dir-resolution-dev',
|
name: 'nuxt:vite-public-dir-resolution-dev',
|
||||||
vite: {
|
vite: {
|
||||||
|
@ -21,8 +21,6 @@ interface SSRStylePluginOptions {
|
|||||||
mode: 'server' | 'client'
|
mode: 'server' | 'client'
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUPPORTED_FILES_RE = /\.(?:vue|(?:[cm]?j|t)sx?)$/
|
|
||||||
|
|
||||||
export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
|
export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
|
||||||
const cssMap: Record<string, { files: string[], inBundle?: boolean }> = {}
|
const cssMap: Record<string, { files: string[], inBundle?: boolean }> = {}
|
||||||
const idRefMap: Record<string, string> = {}
|
const idRefMap: Record<string, string> = {}
|
||||||
@ -35,6 +33,7 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
|
|||||||
// .server components without a corresponding .client component will need to be rendered as an island
|
// .server components without a corresponding .client component will need to be rendered as an island
|
||||||
(component.mode === 'server' && !options.components.some(c => c.pascalName === component.pascalName && c.mode === 'client')),
|
(component.mode === 'server' && !options.components.some(c => c.pascalName === component.pascalName && c.mode === 'client')),
|
||||||
)
|
)
|
||||||
|
const SUPPORTED_FILES_RE = /\.(?:vue|(?:[cm]?j|t)sx?)$/
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'ssr-styles',
|
name: 'ssr-styles',
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import type { Plugin } from 'vite'
|
import type { Plugin } from 'vite'
|
||||||
|
|
||||||
const QUERY_RE = /\?.+$/
|
|
||||||
|
|
||||||
export function typeCheckPlugin (options: { sourcemap?: boolean } = {}): Plugin {
|
export function typeCheckPlugin (options: { sourcemap?: boolean } = {}): Plugin {
|
||||||
let entry: string
|
let entry: string
|
||||||
|
const QUERY_RE = /\?.+$/
|
||||||
return {
|
return {
|
||||||
name: 'nuxt:type-check',
|
name: 'nuxt:type-check',
|
||||||
configResolved (config) {
|
configResolved (config) {
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.34.6",
|
"rollup": "4.34.8",
|
||||||
"unbuild": "3.3.1",
|
"unbuild": "3.3.1",
|
||||||
"vue": "3.5.13"
|
"vue": "3.5.13"
|
||||||
},
|
},
|
||||||
|
@ -4,11 +4,6 @@ import { resolve } from 'pathe'
|
|||||||
import type { Plugin } from 'rollup'
|
import type { Plugin } from 'rollup'
|
||||||
import { importModule } from '@nuxt/kit'
|
import { importModule } from '@nuxt/kit'
|
||||||
|
|
||||||
const PLUGIN_NAME = 'dynamic-require'
|
|
||||||
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.mjs`
|
|
||||||
const DYNAMIC_REQUIRE_RE = /import\("\.\/" ?\+(.*)\).then/g
|
|
||||||
const BACKWARD_SLASH_RE = /\\/g
|
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
dir: string
|
dir: string
|
||||||
inline: boolean
|
inline: boolean
|
||||||
@ -33,6 +28,47 @@ interface TemplateContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
||||||
|
const PLUGIN_NAME = 'dynamic-require'
|
||||||
|
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.mjs`
|
||||||
|
const DYNAMIC_REQUIRE_RE = /import\("\.\/" ?\+(.*)\).then/g
|
||||||
|
const BACKWARD_SLASH_RE = /\\/g
|
||||||
|
async function getWebpackChunkMeta (src: string) {
|
||||||
|
const chunk = await importModule<WebpackChunk>(src) || {}
|
||||||
|
const { __webpack_id__, __webpack_ids__, __webpack_modules__, id = __webpack_id__, ids = __webpack_ids__, modules = __webpack_modules__ } = chunk
|
||||||
|
if (!id && !ids) {
|
||||||
|
return null // Not a webpack chunk
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
ids,
|
||||||
|
moduleIds: Object.keys(modules || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TMPL_INLINE ({ chunks }: TemplateContext) {
|
||||||
|
return `${chunks
|
||||||
|
.map(i => `import * as ${i.name} from '${i.src}'`)
|
||||||
|
.join('\n')}
|
||||||
|
const dynamicChunks = {
|
||||||
|
${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function dynamicRequire(id) {
|
||||||
|
return Promise.resolve(dynamicChunks[id]);
|
||||||
|
};`
|
||||||
|
}
|
||||||
|
|
||||||
|
function TMPL_LAZY ({ chunks }: TemplateContext) {
|
||||||
|
return `
|
||||||
|
const dynamicChunks = {
|
||||||
|
${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function dynamicRequire(id) {
|
||||||
|
return dynamicChunks[id]();
|
||||||
|
};`
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: PLUGIN_NAME,
|
name: PLUGIN_NAME,
|
||||||
transform (code: string, _id: string) {
|
transform (code: string, _id: string) {
|
||||||
@ -96,40 +132,3 @@ type WebpackChunk = {
|
|||||||
__webpack_ids__?: string[]
|
__webpack_ids__?: string[]
|
||||||
__webpack_modules__?: Record<string, unknown>
|
__webpack_modules__?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getWebpackChunkMeta (src: string) {
|
|
||||||
const chunk = await importModule<WebpackChunk>(src) || {}
|
|
||||||
const { __webpack_id__, __webpack_ids__, __webpack_modules__, id = __webpack_id__, ids = __webpack_ids__, modules = __webpack_modules__ } = chunk
|
|
||||||
if (!id && !ids) {
|
|
||||||
return null // Not a webpack chunk
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
ids,
|
|
||||||
moduleIds: Object.keys(modules || {}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function TMPL_INLINE ({ chunks }: TemplateContext) {
|
|
||||||
return `${chunks
|
|
||||||
.map(i => `import * as ${i.name} from '${i.src}'`)
|
|
||||||
.join('\n')}
|
|
||||||
const dynamicChunks = {
|
|
||||||
${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function dynamicRequire(id) {
|
|
||||||
return Promise.resolve(dynamicChunks[id]);
|
|
||||||
};`
|
|
||||||
}
|
|
||||||
|
|
||||||
function TMPL_LAZY ({ chunks }: TemplateContext) {
|
|
||||||
return `
|
|
||||||
const dynamicChunks = {
|
|
||||||
${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function dynamicRequire(id) {
|
|
||||||
return dynamicChunks[id]();
|
|
||||||
};`
|
|
||||||
}
|
|
||||||
|
1447
pnpm-lock.yaml
1447
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user