diff --git a/packages/vite/src/node/__tests__/utils.spec.ts b/packages/vite/src/node/__tests__/utils.spec.ts index 4b80e20814b82f..18d55b9f18b6fc 100644 --- a/packages/vite/src/node/__tests__/utils.spec.ts +++ b/packages/vite/src/node/__tests__/utils.spec.ts @@ -4,6 +4,7 @@ import { describe, expect, test } from 'vitest' import { asyncFlatten, bareImportRE, + flattenId, getHash, getLocalhostAddressIfDiffersFromDNS, injectQuery, @@ -260,3 +261,22 @@ describe('processSrcSetSync', () => { ).toBe('/base/nested/asset.png 1x, /base/nested/asset.png 2x') }) }) + +describe('flattenId', () => { + test('should limit id to 170 characters', () => { + const tenChars = '1234567890' + let id = '' + + for (let i = 0; i < 17; i++) { + id += tenChars + } + expect(id).toHaveLength(170) + + const result = flattenId(id) + expect(result).toHaveLength(170) + + id += tenChars + const result2 = flattenId(id) + expect(result2).toHaveLength(170) + }) +}) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 76ab58ba92f9f9..65f230f8e10db6 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -78,12 +78,29 @@ const replaceSlashOrColonRE = /[/:]/g const replaceDotRE = /\./g const replaceNestedIdRE = /(\s*>\s*)/g const replaceHashRE = /#/g -export const flattenId = (id: string): string => - id - .replace(replaceSlashOrColonRE, '_') - .replace(replaceDotRE, '__') - .replace(replaceNestedIdRE, '___') - .replace(replaceHashRE, '____') +export const flattenId = (id: string): string => { + const flatId = limitFlattenIdLength( + id + .replace(replaceSlashOrColonRE, '_') + .replace(replaceDotRE, '__') + .replace(replaceNestedIdRE, '___') + .replace(replaceHashRE, '____'), + ) + return flatId +} + +const FLATTEN_ID_HASH_LENGTH = 8 +const FLATTEN_ID_MAX_FILE_LENGTH = 170 + +const limitFlattenIdLength = ( + id: string, + limit: number = FLATTEN_ID_MAX_FILE_LENGTH, +): string => { + if (id.length <= limit) { + return id + } + return id.slice(0, limit - (FLATTEN_ID_HASH_LENGTH + 1)) + '_' + getHash(id) +} export const normalizeId = (id: string): string => id.replace(replaceNestedIdRE, ' > ') diff --git a/playground/optimize-deps/__tests__/optimize-deps.spec.ts b/playground/optimize-deps/__tests__/optimize-deps.spec.ts index a42e8838288e9e..a3b3df6e5edfc0 100644 --- a/playground/optimize-deps/__tests__/optimize-deps.spec.ts +++ b/playground/optimize-deps/__tests__/optimize-deps.spec.ts @@ -238,6 +238,24 @@ test.runIf(isBuild)('no missing deps during build', async () => { }) }) +test('name file limit is 170 characters', async () => { + if (isServe) { + const response = page.waitForResponse( + /@vitejs_longfilename_\w+_[a-zA-Z\d]+\.js\?v=[a-zA-Z\d]+/, + ) + await page.goto(viteTestUrl) + const content = await response + + const fromUrl = content.url() + const stripFolderPart = fromUrl.split('/').at(-1) + const onlyTheFilePart = stripFolderPart.split('.')[0] + expect(onlyTheFilePart).toHaveLength(170) + + const text = await content.text() + expect(text).toMatch(/import\s+("[^"]+")/) + } +}) + describe.runIf(isServe)('optimizeDeps config', () => { test('supports include glob syntax', () => { const metadata = readDepOptimizationMetadata() @@ -256,3 +274,7 @@ describe.runIf(isServe)('optimizeDeps config', () => { ]) }) }) + +test('long file name should work', async () => { + expect(await page.textContent('.long-file-name')).toMatch(`hello world`) +}) diff --git a/playground/optimize-deps/index.html b/playground/optimize-deps/index.html index af31bcff8a4d29..3839a4aa9951d0 100644 --- a/playground/optimize-deps/index.html +++ b/playground/optimize-deps/index.html @@ -105,6 +105,11 @@