Compare commits

...

14 Commits

Author SHA1 Message Date
Michael Brevard
20fbd51328
Merge 16984b7c7e into edc299a043 2024-11-20 06:35:52 -05:00
renovate[bot]
edc299a043
chore(deps): update all non-major dependencies (main) (#29995)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-20 06:35:43 -05:00
renovate[bot]
ad3ab4d310
chore(deps): update all non-major dependencies (main) (#29986)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-19 23:36:17 -05:00
tbitw2549
16984b7c7e fix: mark chunk as existent 2024-10-23 21:13:08 +03:00
tbitw2549
c6c4f4efc8 Merge branch 'patch-26' of https://github.com/GalacticHypernova/nuxt into patch-26 2024-10-23 21:10:40 +03:00
tbitw2549
f5bb1aad1c perf: object iterators 2024-10-23 21:09:22 +03:00
Michael Brevard
e155e0483e
perf: initial vite impl 2024-10-23 20:39:54 +03:00
tbitw2549
6613d9fedf Merge branch 'patch-26' of https://github.com/GalacticHypernova/nuxt into patch-26 2024-10-20 21:40:05 +03:00
tbitw2549
f2a9a568b0 perf(kit): unify mode regex 2024-10-20 21:39:35 +03:00
autofix-ci[bot]
9b501e1dd3
[autofix.ci] apply automated fixes 2024-10-20 18:35:23 +00:00
tbitw2549
ee6f91b7e3 perf: unify (j/t)sx regex 2024-10-20 21:33:03 +03:00
tbitw2549
dc4d032246 perf: unify shared patterns 2024-10-20 21:28:29 +03:00
tbitw2549
f49c0497ad perf: extract regex patterns 2024-10-20 21:18:12 +03:00
Michael Brevard
83465c241a
perf: cache regex patterns 2024-10-20 20:11:31 +03:00
16 changed files with 50 additions and 35 deletions

View File

@ -248,7 +248,7 @@ jobs:
TEST_PAYLOAD: ${{ matrix.payload }} TEST_PAYLOAD: ${{ matrix.payload }}
SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || matrix.payload == 'js' || runner.os == 'Windows' }} SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || matrix.payload == 'js' || runner.os == 'Windows' }}
- uses: codecov/codecov-action@5c47607acb93fed5485fdbf7232e8a31425f672a # v5.0.2 - uses: codecov/codecov-action@985343d70564a82044c1b7fcb84c2fa05405c1a2 # v5.0.4
if: github.event_name != 'push' && matrix.env == 'built' && matrix.builder == 'vite' && matrix.context == 'default' && matrix.os == 'ubuntu-latest' && matrix.manifest == 'manifest-on' if: github.event_name != 'push' && matrix.env == 'built' && matrix.builder == 'vite' && matrix.context == 'default' && matrix.os == 'ubuntu-latest' && matrix.manifest == 'manifest-on'
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}

View File

@ -91,7 +91,7 @@
"devalue": "5.1.1", "devalue": "5.1.1",
"eslint": "9.15.0", "eslint": "9.15.0",
"eslint-plugin-no-only-tests": "3.3.0", "eslint-plugin-no-only-tests": "3.3.0",
"eslint-plugin-perfectionist": "4.0.2", "eslint-plugin-perfectionist": "4.0.3",
"eslint-typegen": "0.3.2", "eslint-typegen": "0.3.2",
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e", "h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
"happy-dom": "15.11.6", "happy-dom": "15.11.6",
@ -118,7 +118,7 @@
"vue-router": "4.4.5", "vue-router": "4.4.5",
"vue-tsc": "2.1.10" "vue-tsc": "2.1.10"
}, },
"packageManager": "pnpm@9.13.2", "packageManager": "pnpm@9.14.1",
"engines": { "engines": {
"node": "^16.10.0 || >=18.0.0" "node": "^16.10.0 || >=18.0.0"
}, },

View File

@ -34,7 +34,8 @@ async function loadComponents (source = appBaseURL, paths: NuxtIslandResponse['c
const promises: Array<Promise<void>> = [] const promises: Array<Promise<void>> = []
for (const [component, item] of Object.entries(paths)) { for (const component in paths) {
const item = paths[component]!
if (!(components!.has(component))) { if (!(components!.has(component))) {
promises.push((async () => { promises.push((async () => {
const chunkSource = join(source, item.chunk) const chunkSource = join(source, item.chunk)
@ -146,10 +147,10 @@ export default defineComponent({
html = html.replace(ISLAND_SCOPE_ID_RE, full => full + ' ' + props.scopeId) html = html.replace(ISLAND_SCOPE_ID_RE, full => full + ' ' + props.scopeId)
} }
if (import.meta.client && !canLoadClientComponent.value) { if (import.meta.client && !canLoadClientComponent.value && payloads.components) {
for (const [key, value] of Object.entries(payloads.components || {})) { for (const key in payloads.components) {
html = html.replace(new RegExp(` data-island-uid="${uid.value}" data-island-component="${key}"[^>]*>`), (full) => { html = html.replace(new RegExp(` data-island-uid="${uid.value}" data-island-component="${key}"[^>]*>`), (full) => {
return full + value.html return full + payloads.components![key]!.html
}) })
} }
} }
@ -289,8 +290,8 @@ export default defineComponent({
if (selectiveClient) { if (selectiveClient) {
if (import.meta.server) { if (import.meta.server) {
if (payloads.components) { if (payloads.components) {
for (const [id, info] of Object.entries(payloads.components)) { for (const id in payloads.components) {
const { html, slots } = info const { html, slots } = payloads.components[id]!
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`) let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
for (const slot in slots) { for (const slot in slots) {
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot]) replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
@ -301,8 +302,8 @@ export default defineComponent({
} }
} }
} else if (canLoadClientComponent.value && payloads.components) { } else if (canLoadClientComponent.value && payloads.components) {
for (const [id, info] of Object.entries(payloads.components)) { for (const id in payloads.components) {
const { props, slots } = info const { props, slots } = payloads.components[id]!
const component = components!.get(id)! const component = components!.get(id)!
// use different selectors for even and odd teleportKey to force trigger the teleport // use different selectors for even and odd teleportKey to force trigger the teleport
const vnode = createVNode(Teleport, { to: `${isKeyOdd ? 'div' : ''}[data-island-uid='${uid.value}'][data-island-component="${id}"]` }, { const vnode = createVNode(Teleport, { to: `${isKeyOdd ? 'div' : ''}[data-island-uid='${uid.value}'][data-island-component="${id}"]` }, {

View File

@ -250,8 +250,8 @@ function generateOptionSegments<_ResT, DataT, DefaultT> (opts: UseFetchOptions<_
if (!obj) { continue } if (!obj) { continue }
const unwrapped: Record<string, string> = {} const unwrapped: Record<string, string> = {}
for (const [key, value] of Object.entries(obj)) { for (const key in obj) {
unwrapped[toValue(key)] = toValue(value) unwrapped[toValue(key)] = toValue(obj[key])
} }
segments.push(unwrapped) segments.push(unwrapped)
} }

View File

@ -144,7 +144,8 @@ export default defineNuxtModule<ComponentsOptions>({
nuxt.hook('build:manifest', (manifest) => { nuxt.hook('build:manifest', (manifest) => {
const sourceFiles = getComponents().filter(c => c.global).map(c => relative(nuxt.options.srcDir, c.filePath)) const sourceFiles = getComponents().filter(c => c.global).map(c => relative(nuxt.options.srcDir, c.filePath))
for (const chunk of Object.values(manifest)) { for (const chunkId in manifest) {
const chunk = manifest[chunkId]!
if (chunk.isEntry) { if (chunk.isEntry) {
chunk.dynamicImports = chunk.dynamicImports =
chunk.dynamicImports?.filter(i => !sourceFiles.includes(i)) chunk.dynamicImports?.filter(i => !sourceFiles.includes(i))

View File

@ -214,7 +214,8 @@ export const ComponentsChunkPlugin = createUnplugin((options: ComponentChunkOpti
async generateBundle (_opts, bundle) { async generateBundle (_opts, bundle) {
const components = options.getComponents().filter(c => c.mode === 'client' || c.mode === 'all') const components = options.getComponents().filter(c => c.mode === 'client' || c.mode === 'all')
const pathAssociation: Record<string, string> = {} const pathAssociation: Record<string, string> = {}
for (const [chunkPath, chunkInfo] of Object.entries(bundle)) { for (const chunkPath in bundle) {
const chunkInfo = bundle[chunkPath]!
if (chunkInfo.type !== 'chunk') { continue } if (chunkInfo.type !== 'chunk') { continue }
for (const component of components) { for (const component of components) {

View File

@ -346,7 +346,8 @@ async function initNuxt (nuxt: Nuxt) {
// TODO: [Experimental] Avoid emitting assets when flag is enabled // TODO: [Experimental] Avoid emitting assets when flag is enabled
if (nuxt.options.features.noScripts && !nuxt.options.dev) { if (nuxt.options.features.noScripts && !nuxt.options.dev) {
nuxt.hook('build:manifest', async (manifest) => { nuxt.hook('build:manifest', async (manifest) => {
for (const chunk of Object.values(manifest)) { for (const chunkId in manifest) {
const chunk = manifest[chunkId]!
if (chunk.resourceType === 'script') { if (chunk.resourceType === 'script') {
await rm(resolve(nuxt.options.buildDir, 'dist/client', withoutLeadingSlash(nuxt.options.app.buildAssetsDir), chunk.file), { force: true }) await rm(resolve(nuxt.options.buildDir, 'dist/client', withoutLeadingSlash(nuxt.options.app.buildAssetsDir), chunk.file), { force: true })
chunk.file = '' chunk.file = ''

View File

@ -396,7 +396,8 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
} }
if (!isRenderingIsland || import.meta.dev) { if (!isRenderingIsland || import.meta.dev) {
const link: Link[] = [] const link: Link[] = []
for (const resource of Object.values(styles)) { for (const resourceId in styles) {
const resource = styles[resourceId]!
// Do not add links to resources that are inlined (vite v5+) // Do not add links to resources that are inlined (vite v5+)
if (import.meta.dev && 'inline' in getURLQuery(resource.file)) { if (import.meta.dev && 'inline' in getURLQuery(resource.file)) {
continue continue
@ -462,7 +463,9 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
if (isRenderingIsland && islandContext) { if (isRenderingIsland && islandContext) {
const islandHead: Head = {} const islandHead: Head = {}
for (const entry of head.headEntries()) { for (const entry of head.headEntries()) {
for (const [key, value] of Object.entries(resolveUnrefHeadInput(entry.input) as Head)) { const currentEntry = resolveUnrefHeadInput(entry.input)
for (const key in currentEntry as Head) {
const value = currentEntry[key]
const currentValue = islandHead[key as keyof Head] const currentValue = islandHead[key as keyof Head]
if (Array.isArray(currentValue)) { if (Array.isArray(currentValue)) {
currentValue.push(...value) currentValue.push(...value)
@ -661,9 +664,9 @@ const SSR_CLIENT_SLOT_MARKER = /^island-slot=[^;]*;(.*)$/
function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['slots'] { function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['slots'] {
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) { return undefined } if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) { return undefined }
const response: NuxtIslandResponse['slots'] = {} const response: NuxtIslandResponse['slots'] = {}
for (const [name, slot] of Object.entries(ssrContext.islandContext.slots)) { for (const name in ssrContext.islandContext.slots) {
response[name] = { response[name] = {
...slot, ...ssrContext.islandContext.slots[name]!,
fallback: ssrContext.teleports?.[`island-fallback=${name}`], fallback: ssrContext.teleports?.[`island-fallback=${name}`],
} }
} }
@ -674,11 +677,11 @@ function getClientIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandRespons
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) { return undefined } if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) { return undefined }
const response: NuxtIslandResponse['components'] = {} const response: NuxtIslandResponse['components'] = {}
for (const [clientUid, component] of Object.entries(ssrContext.islandContext.components)) { for (const clientUid in ssrContext.islandContext.components) {
// remove teleport anchor to avoid hydration issues // remove teleport anchor to avoid hydration issues
const html = ssrContext.teleports?.[clientUid]?.replaceAll('<!--teleport start anchor-->', '') || '' const html = ssrContext.teleports?.[clientUid]?.replaceAll('<!--teleport start anchor-->', '') || ''
response[clientUid] = { response[clientUid] = {
...component, ...ssrContext.islandContext.components[clientUid]!,
html, html,
slots: getComponentSlotTeleport(ssrContext.teleports ?? {}), slots: getComponentSlotTeleport(ssrContext.teleports ?? {}),
} }

View File

@ -436,7 +436,8 @@ export default defineNuxtModule({
nuxt.hook('pages:extend', (routes) => { nuxt.hook('pages:extend', (routes) => {
const nitro = useNitro() const nitro = useNitro()
let resolvedRoutes: string[] let resolvedRoutes: string[]
for (const [path, rule] of Object.entries(nitro.options.routeRules)) { for (const path in nitro.options.routeRules) {
const rule = nitro.options.routeRules[path]!
if (!rule.redirect) { continue } if (!rule.redirect) { continue }
resolvedRoutes ||= routes.flatMap(route => resolveRoutePaths(route)) resolvedRoutes ||= routes.flatMap(route => resolveRoutePaths(route))
// skip if there's already a route matching this path // skip if there's already a route matching this path
@ -480,7 +481,8 @@ export default defineNuxtModule({
if (nuxt.options.dev) { return } if (nuxt.options.dev) { return }
const sourceFiles = nuxt.apps.default?.pages?.length ? getSources(nuxt.apps.default.pages) : [] const sourceFiles = nuxt.apps.default?.pages?.length ? getSources(nuxt.apps.default.pages) : []
for (const [key, chunk] of Object.entries(manifest)) { for (const key in manifest) {
const chunk = manifest[key]!
if (chunk.src && Object.values(nuxt.apps).some(app => app.pages?.some(page => page.mode === 'server' && page.file === join(nuxt.options.srcDir, chunk.src!)))) { if (chunk.src && Object.values(nuxt.apps).some(app => app.pages?.some(page => page.mode === 'server' && page.file === join(nuxt.options.srcDir, chunk.src!)))) {
delete manifest[key] delete manifest[key]
continue continue

View File

@ -18,7 +18,8 @@ export function analyzePlugin (ctx: ViteBuildContext): Plugin[] {
const bundle = outputBundle[_bundleId] const bundle = outputBundle[_bundleId]
if (!bundle || bundle.type !== 'chunk') { continue } if (!bundle || bundle.type !== 'chunk') { continue }
const minifiedModuleEntryPromises: Array<Promise<[string, RenderedModule]>> = [] const minifiedModuleEntryPromises: Array<Promise<[string, RenderedModule]>> = []
for (const [moduleId, module] of Object.entries(bundle.modules)) { for (const moduleId in bundle.modules) {
const module = bundle.modules[moduleId]!
minifiedModuleEntryPromises.push( minifiedModuleEntryPromises.push(
transform(module.code || '', { minify: true }) transform(module.code || '', { minify: true })
.then(result => [moduleId, { ...module, code: result.code }]), .then(result => [moduleId, { ...module, code: result.code }]),

View File

@ -14,7 +14,8 @@ export const createSourcemapPreserver = () => {
outputDir = config.build.outDir outputDir = config.build.outDir
}, },
async writeBundle (_options, bundle) { async writeBundle (_options, bundle) {
for (const chunk of Object.values(bundle)) { for (const chunkId in bundle) {
const chunk = bundle[chunkId]!
if (chunk.type !== 'chunk' || !chunk.map) { continue } if (chunk.type !== 'chunk' || !chunk.map) { continue }
const id = resolve(outputDir, chunk.fileName) const id = resolve(outputDir, chunk.fileName)

View File

@ -87,7 +87,8 @@ export const VitePublicDirsPlugin = createUnplugin((options: VitePublicDirsPlugi
} }
}, },
generateBundle (_outputOptions, bundle) { generateBundle (_outputOptions, bundle) {
for (const [file, chunk] of Object.entries(bundle)) { for (const file in bundle) {
const chunk = bundle[file]!
if (!file.endsWith('.css') || chunk.type !== 'asset') { continue } if (!file.endsWith('.css') || chunk.type !== 'asset') { continue }
let css = chunk.source.toString() let css = chunk.source.toString()

View File

@ -62,7 +62,8 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
if (options.mode === 'client') { return } if (options.mode === 'client') { return }
const emitted: Record<string, string> = {} const emitted: Record<string, string> = {}
for (const [file, { files, inBundle }] of Object.entries(cssMap)) { for (const file in cssMap) {
const { files, inBundle } = cssMap[file]!
// File has been tree-shaken out of build (or there are no styles to inline) // File has been tree-shaken out of build (or there are no styles to inline)
if (!files.length || !inBundle) { continue } if (!files.length || !inBundle) { continue }
const fileName = filename(file) const fileName = filename(file)

View File

@ -201,7 +201,8 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
// Remove CSS entries for files that will have inlined styles // Remove CSS entries for files that will have inlined styles
ctx.nuxt.hook('build:manifest', (manifest) => { ctx.nuxt.hook('build:manifest', (manifest) => {
for (const [key, entry] of Object.entries(manifest)) { for (const key in manifest) {
const entry = manifest[key]!
const shouldRemoveCSS = chunksWithInlinedCSS.has(key) && !entry.isEntry const shouldRemoveCSS = chunksWithInlinedCSS.has(key) && !entry.isEntry
if (entry.isEntry && chunksWithInlinedCSS.has(key)) { if (entry.isEntry && chunksWithInlinedCSS.has(key)) {
// @ts-expect-error internal key // @ts-expect-error internal key

View File

@ -33,7 +33,8 @@ export default class VueSSRClientPlugin {
const stats = compilation.getStats().toJson() const stats = compilation.getStats().toJson()
const initialFiles = new Set<string>() const initialFiles = new Set<string>()
for (const { assets } of Object.values(stats.entrypoints!)) { for (const assetId in stats.entrypoints!) {
const { assets } = stats.entrypoints[assetId]!
if (!assets) { continue } if (!assets) { continue }
for (const asset of assets) { for (const asset of assets) {

View File

@ -114,8 +114,8 @@ importers:
specifier: 3.3.0 specifier: 3.3.0
version: 3.3.0 version: 3.3.0
eslint-plugin-perfectionist: eslint-plugin-perfectionist:
specifier: 4.0.2 specifier: 4.0.3
version: 4.0.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3) version: 4.0.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3)
eslint-typegen: eslint-typegen:
specifier: 0.3.2 specifier: 0.3.2
version: 0.3.2(eslint@9.15.0(jiti@2.4.0)) version: 0.3.2(eslint@9.15.0(jiti@2.4.0))
@ -4373,8 +4373,8 @@ packages:
resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==}
engines: {node: '>=5.0.0'} engines: {node: '>=5.0.0'}
eslint-plugin-perfectionist@4.0.2: eslint-plugin-perfectionist@4.0.3:
resolution: {integrity: sha512-zWdgyg2SdHqhp/P9d9vKwo5qD9is28xMAGzBslHqkZz5mVIikjyz1qvuJ4yS7Wrsf4KlbGorORefb4Kbe7Puzg==} resolution: {integrity: sha512-CyafnreF6boy4lf1XaF72U8NbkwrfjU/mOf1y6doaDMS9zGXhUU1DSk+ZPf/rVwCf1PL1m+rhHqFs+IcB8kDmA==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies: peerDependencies:
eslint: '>=8.0.0' eslint: '>=8.0.0'
@ -11519,7 +11519,7 @@ snapshots:
eslint-plugin-no-only-tests@3.3.0: {} eslint-plugin-no-only-tests@3.3.0: {}
eslint-plugin-perfectionist@4.0.2(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3): eslint-plugin-perfectionist@4.0.3(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3):
dependencies: dependencies:
'@typescript-eslint/types': 8.15.0 '@typescript-eslint/types': 8.15.0
'@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3) '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.6.3)