diff --git a/packages/kit/src/compatibility.ts b/packages/kit/src/compatibility.ts index d1d7e50fda..d3d6e55875 100644 --- a/packages/kit/src/compatibility.ts +++ b/packages/kit/src/compatibility.ts @@ -89,9 +89,9 @@ export function isNuxt3 (nuxt: Nuxt = useNuxt()) { * Get nuxt version */ export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) { - const version = (nuxt?._version || nuxt?.version || nuxt?.constructor?.version || '').replace(/^v/g, '') - if (!version) { + const rawVersion = nuxt?._version || nuxt?.version || nuxt?.constructor?.version + if (!rawVersion) { throw new Error('Cannot determine nuxt version! Is current instance passed?') } - return version + return rawVersion.replace(/^v/g, '') } diff --git a/packages/kit/src/loader/nuxt.ts b/packages/kit/src/loader/nuxt.ts index aaec491fae..ab02f1bd5b 100644 --- a/packages/kit/src/loader/nuxt.ts +++ b/packages/kit/src/loader/nuxt.ts @@ -33,7 +33,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise { throw new Error(`Cannot find any nuxt version from ${opts.cwd}`) } const pkg = await readPackageJSON(nearestNuxtPkg) - const majorVersion = parseInt((pkg.version || '').split('.')[0]) + const majorVersion = pkg.version ? parseInt(pkg.version.split('.')[0]) : '' const rootDir = pathToFileURL(opts.cwd || process.cwd()).href diff --git a/packages/nuxt/src/app/components/nuxt-error-page.vue b/packages/nuxt/src/app/components/nuxt-error-page.vue index d3fa6e2636..50308e6604 100644 --- a/packages/nuxt/src/app/components/nuxt-error-page.vue +++ b/packages/nuxt/src/app/components/nuxt-error-page.vue @@ -13,21 +13,23 @@ const props = defineProps({ const _error = props.error // TODO: extract to a separate utility -const stacktrace = (_error.stack || '') - .split('\n') - .splice(1) - .map((line) => { - const text = line - .replace('webpack:/', '') - .replace('.vue', '.js') // TODO: Support sourcemap - .trim() - return { - text, - internal: (line.includes('node_modules') && !line.includes('.cache')) || - line.includes('internal') || - line.includes('new Promise') - } - }).map(i => `${i.text}`).join('\n') +const stacktrace = _error.stack + ? _error.stack + .split('\n') + .splice(1) + .map((line) => { + const text = line + .replace('webpack:/', '') + .replace('.vue', '.js') // TODO: Support sourcemap + .trim() + return { + text, + internal: (line.includes('node_modules') && !line.includes('.cache')) || + line.includes('internal') || + line.includes('new Promise') + } + }).map(i => `${i.text}`).join('\n') + : '' // Error page props const statusCode = Number(_error.statusCode || 500) diff --git a/packages/nuxt/src/core/app.ts b/packages/nuxt/src/core/app.ts index 467376d827..27fd87a0c0 100644 --- a/packages/nuxt/src/core/app.ts +++ b/packages/nuxt/src/core/app.ts @@ -233,7 +233,7 @@ export function checkForCircularDependencies (_plugins: Array checkDeps(dep, [...visited])) + return deps[name]?.length ? deps[name].flatMap(dep => checkDeps(dep, [...visited])) : [] } for (const name in deps) { checkDeps(name) diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index c0ca416fab..8a78dbfa75 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -287,13 +287,15 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { const routeRulesMatcher = toRouteMatcher( createRadixRouter({ routes: routeRules }) ) - const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js' - for (const route of nitro._prerenderedRoutes || []) { - if (!route.error && route.route.endsWith(payloadSuffix)) { - const url = route.route.slice(0, -payloadSuffix.length) || '/' - const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record - if (!rules.prerender) { - prerenderedRoutes.add(url) + if (nitro._prerenderedRoutes?.length) { + const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js' + for (const route of nitro._prerenderedRoutes) { + if (!route.error && route.route.endsWith(payloadSuffix)) { + const url = route.route.slice(0, -payloadSuffix.length) || '/' + const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record + if (!rules.prerender) { + prerenderedRoutes.add(url) + } } } } diff --git a/packages/nuxt/src/core/plugins/dev-only.ts b/packages/nuxt/src/core/plugins/dev-only.ts index f1f56122d0..6adc7a375a 100644 --- a/packages/nuxt/src/core/plugins/dev-only.ts +++ b/packages/nuxt/src/core/plugins/dev-only.ts @@ -21,11 +21,10 @@ export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => { if (!DEVONLY_COMP_SINGLE_RE.test(code)) { return } const s = new MagicString(code) - for (const match of code.matchAll(DEVONLY_COMP_RE) || []) { + for (const match of code.matchAll(DEVONLY_COMP_RE)) { const ast: Node = parse(match[0]).children[0] const fallback: Node | undefined = ast.children?.find((n: Node) => n.name === 'template' && Object.values(n.attributes).includes('#fallback')) const replacement = fallback ? match[0].slice(fallback.loc[0].end, fallback.loc[fallback.loc.length - 1].start) : '' - s.overwrite(match.index!, match.index! + match[0].length, replacement) } diff --git a/packages/nuxt/src/core/plugins/tree-shake.ts b/packages/nuxt/src/core/plugins/tree-shake.ts index 35030990ca..f6e3427e4a 100644 --- a/packages/nuxt/src/core/plugins/tree-shake.ts +++ b/packages/nuxt/src/core/plugins/tree-shake.ts @@ -31,7 +31,7 @@ export const TreeShakeComposablesPlugin = createUnplugin((options: TreeShakeComp const s = new MagicString(code) const strippedCode = stripLiteral(code) - for (const match of strippedCode.matchAll(COMPOSABLE_RE_GLOBAL) || []) { + for (const match of strippedCode.matchAll(COMPOSABLE_RE_GLOBAL)) { s.overwrite(match.index!, match.index! + match[0].length, `${match[1]} false && /*@__PURE__*/ ${match[2]}`) } diff --git a/packages/nuxt/src/core/utils/names.ts b/packages/nuxt/src/core/utils/names.ts index 64121414c5..b3a607980f 100644 --- a/packages/nuxt/src/core/utils/names.ts +++ b/packages/nuxt/src/core/utils/names.ts @@ -28,7 +28,7 @@ export function resolveComponentNameSegments (fileName: string, prefixParts: str let index = prefixParts.length - 1 const matchedSuffix: string[] = [] while (index >= 0) { - matchedSuffix.unshift(...splitByCase(prefixParts[index] || '').map(p => p.toLowerCase())) + matchedSuffix.unshift(...splitByCase(prefixParts[index]).map(p => p.toLowerCase())) const matchedSuffixContent = matchedSuffix.join('/') if ((fileNamePartsContent === matchedSuffixContent || fileNamePartsContent.startsWith(matchedSuffixContent + '/')) || // e.g Item/Item/Item.vue -> Item diff --git a/packages/nuxt/src/head/runtime/components.ts b/packages/nuxt/src/head/runtime/components.ts index 3ed7a1ee06..3969a082a6 100644 --- a/packages/nuxt/src/head/runtime/components.ts +++ b/packages/nuxt/src/head/runtime/components.ts @@ -86,10 +86,10 @@ export const NoScript = defineComponent({ }, setup: setupForUseMeta((props, { slots }) => { const noscript = { ...props } - const textContent = (slots.default?.() || []) - .filter(({ children }) => children) - .map(({ children }) => children) - .join('') + const slotVnodes = slots.default?.() + const textContent = slotVnodes + ? slotVnodes.filter(({ children }) => children).map(({ children }) => children).join('') + : '' if (textContent) { noscript.children = textContent } diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index bd6ae3b69d..8c74482f05 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -271,13 +271,15 @@ export default defineNuxtModule({ processPages(pages) }) nuxt.hook('nitro:build:before', (nitro) => { - for (const route of nitro.options.prerender.routes || []) { - // Skip default route value as we only generate it if it is already - // in the detected routes from `~/pages`. - if (route === '/') { continue } - prerenderRoutes.add(route) + if (nitro.options.prerender.routes.length) { + for (const route of nitro.options.prerender.routes) { + // Skip default route value as we only generate it if it is already + // in the detected routes from `~/pages`. + if (route === '/') { continue } + prerenderRoutes.add(route) + } + nitro.options.prerender.routes = Array.from(prerenderRoutes) } - nitro.options.prerender.routes = Array.from(prerenderRoutes) }) }) @@ -389,13 +391,13 @@ export default defineNuxtModule({ const getSources = (pages: NuxtPage[]): string[] => pages .filter(p => Boolean(p.file)) .flatMap(p => - [relative(nuxt.options.srcDir, p.file as string), ...getSources(p.children || [])] + [relative(nuxt.options.srcDir, p.file as string), ...(p.children?.length ? getSources(p.children) : [])] ) // Do not prefetch page chunks nuxt.hook('build:manifest', (manifest) => { if (nuxt.options.dev) { return } - const sourceFiles = getSources(nuxt.apps.default.pages || []) + const sourceFiles = nuxt.apps.default?.pages?.length ? getSources(nuxt.apps.default.pages) : [] for (const key in manifest) { if (manifest[key].isEntry) { diff --git a/packages/vite/src/plugins/ssr-styles.ts b/packages/vite/src/plugins/ssr-styles.ts index 56afc02312..37a810290e 100644 --- a/packages/vite/src/plugins/ssr-styles.ts +++ b/packages/vite/src/plugins/ssr-styles.ts @@ -144,6 +144,8 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin { if (id === options.entry && (options.shouldInline === true || (typeof options.shouldInline === 'function' && options.shouldInline(id)))) { const s = new MagicString(code) options.clientCSSMap[id] ||= new Set() + if (!options.globalCSS.length) { return } + for (const file of options.globalCSS) { const resolved = await this.resolve(file) ?? await this.resolve(file, id) const res = await this.resolve(file + '?inline&used') ?? await this.resolve(file + '?inline&used', id) diff --git a/packages/vite/src/utils/warmup.ts b/packages/vite/src/utils/warmup.ts index a16d2f6d9d..38f0ef705e 100644 --- a/packages/vite/src/utils/warmup.ts +++ b/packages/vite/src/utils/warmup.ts @@ -63,7 +63,7 @@ export async function warmupViteServer ( try { const mod = await server.moduleGraph.getModuleByUrl(url, isServer) - const deps = mod?.ssrTransformResult?.deps /* server */ || Array.from(mod?.importedModules /* client */ || []).map(m => m.url) + const deps = mod?.ssrTransformResult?.deps /* server */ || mod?.importedModules.size ? Array.from(mod?.importedModules /* client */).map(m => m.url) : [] await Promise.all(deps.map(m => warmup(m))) } catch (e) { logger.debug('[warmup] tracking dependencies for %s failed with: %s', url, e) diff --git a/test/basic.test.ts b/test/basic.test.ts index cc044801c7..1799771885 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -1986,6 +1986,7 @@ describe('component islands', () => { link.href = link.href.replace(fixtureDir, '/').replaceAll('//', '/') link.key = link.key.replace(/-[a-zA-Z0-9]+$/, '') } + result.head.link.sort((a, b) => b.href.localeCompare(a.href)) } // TODO: fix rendering of styles in webpack