From 3b8c45b0a07a29917b40d325912fbc55677b014b Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Fri, 4 Sep 2026 17:53:37 +0800 Subject: [PATCH 1/3] chore: enable `minimumReleaseAgeStrict` (#23424) --- pnpm-workspace.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1db6b74b66d990..1947b72987bef1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -46,6 +46,7 @@ allowBuilds: unrs-resolver: true workerd: true +minimumReleaseAgeStrict: true minimumReleaseAgeExcludePrune: true minimumReleaseAgeExclude: - rolldown From 12e709ca4df1059747db1cb7c5d1cd71aba79a24 Mon Sep 17 00:00:00 2001 From: Rusty Raven Date: Fri, 4 Sep 2026 18:12:06 +0800 Subject: [PATCH 2/3] fix(html): don't inline preload link targets (fix #13355) (#23387) Co-authored-by: kakiuwang-ui --- packages/vite/src/node/plugins/html.ts | 32 ++++++++++++++------- playground/assets/__tests__/assets.spec.ts | 30 +++++++++++++++++++ playground/assets/index.html | 18 ++++++++++++ playground/assets/nested/preload-asset.png | Bin 0 -> 3395 bytes playground/assets/preload-module.js | 2 ++ 5 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 playground/assets/nested/preload-asset.png create mode 100644 playground/assets/preload-module.js diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index d3488d5bb092c9..c09d5067086c37 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -168,8 +168,24 @@ const noInlineLinkRels = new Set([ 'apple-touch-icon', 'apple-touch-startup-image', 'manifest', + 'modulepreload', + 'preload', + 'prefetch', ]) +// If the node is a link, check if it can be inlined. If not, return `false` to +// force no inline. `undefined` leaves it to the default heuristics. +function getLinkShouldInline( + node: DefaultTreeAdapterMap['element'], + attributes: Record, +): false | undefined { + const isNoInlineLink = + node.nodeName === 'link' && + attributes.rel && + parseRelAttr(attributes.rel).some((v) => noInlineLinkRels.has(v)) + return isNoInlineLink ? false : undefined +} + export const isAsyncScriptMap: WeakMap< ResolvedConfig, Map @@ -636,7 +652,10 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { decodedUrl !== undefined && !isExcludedUrl(decodedUrl) ) { - const result = await processAssetUrl(url) + const result = await processAssetUrl( + url, + getLinkShouldInline(node, attr.attributes), + ) return result !== decodedUrl ? encodeURIPath(result) : url @@ -675,20 +694,11 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { }) js += importExpression } else { - // If the node is a link, check if it can be inlined. If not, set `shouldInline` - // to `false` to force no inline. If `undefined`, it leaves to the default heuristics. - const isNoInlineLink = - node.nodeName === 'link' && - attr.attributes.rel && - parseRelAttr(attr.attributes.rel).some((v) => - noInlineLinkRels.has(v), - ) - const shouldInline = isNoInlineLink ? false : undefined assetUrlsPromises.push( (async () => { const processedUrl = await processAssetUrl( url, - shouldInline, + getLinkShouldInline(node, attr.attributes), ) if (processedUrl !== url) { overwriteAttrValue( diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts index 222ae0ba88cafe..318d32158b0080 100644 --- a/playground/assets/__tests__/assets.spec.ts +++ b/playground/assets/__tests__/assets.spec.ts @@ -328,6 +328,36 @@ describe('css url() references', () => { expect(await getBg('.css-url-quotes-base64-inline')).toMatch(match) }) + test('no base64 inline for modulepreload links', async () => { + const el = await page.$(`link[rel="modulepreload"]`) + const href = await el.getAttribute('href') + expect(href).toMatch( + isBundled + ? /\/foo\/bar\/assets\/preload-module-[-\w]{8}\.js/ + : 'preload-module.js', + ) + }) + + test('no base64 inline for preload and prefetch links', async () => { + const preloadAssetMatch = isBundled + ? /\/foo\/bar\/assets\/preload-asset-[-\w]{8}\.png/ + : '/foo/bar/nested/preload-asset.png' + + const preloadEl = await page.$('link.preload-href') + expect(await preloadEl.getAttribute('href')).toMatch(preloadAssetMatch) + + const prefetchEl = await page.$('link.prefetch-href') + expect(await prefetchEl.getAttribute('href')).toMatch(preloadAssetMatch) + + // `imagesrcset` goes through the srcset branch, which has to honour the + // same no-inline decision as `href` + const imageSrcSetEl = await page.$('link.preload-imagesrcset') + const imageSrcSet = await imageSrcSetEl.getAttribute('imagesrcset') + imageSrcSet.split(', ').forEach((s) => { + expect(s).toMatch(preloadAssetMatch) + }) + }) + test('no base64 inline for icon and manifest links', async () => { const iconEl = await page.$(`link.ico`) const href = await iconEl.getAttribute('href') diff --git a/playground/assets/index.html b/playground/assets/index.html index d9b395be1c12a1..601863db0dcb34 100644 --- a/playground/assets/index.html +++ b/playground/assets/index.html @@ -4,6 +4,24 @@ + + + + KF&@kJcVR{+lVnpAW=nV5g|H(io-_}8K6*NcqG{pEa>P0gCYr*U~dy=m^0Oe z7!hfoL?e16xp?A}qVY%q7;OczNI;1QNJIt>lt79h(@_bQ;BUMr(S5@W1%tkYFrqEN ze~R*PJ`A#<(1;)t15+!P8!LgB{xFgOZ^M8V*o?+;j% zjYbGVxnu3V=Mq_#;0OkTih@F!Or`4OCV95o&O>x)4w-L)G}xSjtYevz@Q}3MqS^c z=?r(`-!lF&n(moMB|_babV?izFPcY~_7AYAcmJMfBT%FUg{9!*NJKKj0c!~sc?<}V z1e6KP(DZx{!kk~eI~MsL4MCDJ0}i3B?ug#`N698}~# z2*4l^2$-pjof!hNA>QZ!0*1A7WRL!P>~qu#$^9z(m!0H z_1U=owYMVUugxctMe9xz?e+DZ*aiSVrr80D@l4=N_`ae9j3}c&b|M6c^Scw&#v42` zs@=W24^$JB&ZnFHq$6hgI?L<)7qPYdpMFDMm5r*2NZZ#;hNLU%;UMB}lBX&zgLa?a z^q;(Rv!#SE3*p7_>9&tfp}FA;>iv!v_p|!wd;>mn_^936qi>ng*>kFww|a^}qJTRK znA`1@E!Y|;+Yc3d2h!d=ZZPN&V<0ppw;;&qMLk zs8GnX$?aj;YSC%6t7ryd|Y^9Qc9F|ZTi%4o)Pe;3_TsRPSb<*4*B>QW0CG(vI z>y^yW0M4}!mMf3!4z1fO+L~w1pRfz#LUd11)b_hvE5tyLhoKw+{E?+obcpiN*0LU8 z+U$wi{2kPnH5r4PMp&T>SNDmqNn*??;K@i|?J!$E9U15d+24QdeF^V4qsj`m?4KR1 zo+530cOpA+R_oI`YVpGHn|g}#XF^ggiIq#Q$r!(y$dA${=6vmyc6@muL~LaHK9;_U zM6ianv&69LoqCIN7iY5Nk~w}(YQ_@J^_HeBva+0R_9?+f_e~4spT$RYhq*aCNMrO$ zANmbE3u(ID)?XQ7A$ZW2RXgnhnaPNg>o$T&swba`imtoDTfX-ox*^fNY~&|)r*EP9 zDjZoQYgH3!&1P!g6r^)r`PMo_8VTHjZZPV`=6oa69GQI3%5zMi(iWaa;uA~o4%J^) zTvx7E_z4|v`9%k4yvRr!>a=q&CRMXs)EtsGU0BaC=tm1rZCwe$9zABiZcVuVM#f_O zEcY-xE#-a$$qK0SptY*~;s&%&{MxjMyzUJK)Ro2HOShN#i zdmd(sJrh3Lv2smAU0Uf)tzU1B4BTO~oK-hJav|YH;*QbtQMXN4?1g)YYj*9zWn;WS zf1=g6CNYN>p%StDbcLOA=ocrq)8-NU#|p81bRF3}y8w-f<_em-45$3L1@~e-{F^+_ zxkl==Ne8Vus0W)|3%}tC9-OE+5bT+_6f|Q*jZeS-JXh8E3%`TziByq04bJ6a1d7>H z;RYj*F8l4WsVGR4UERkbN(jGxSrPD|EDl*hJV;*`c%6d`F)1W~@pz_2+lh zX8Y6jap-cIJ8qTxvL@N3GJ-7LiuUjog<%wMNATus+JP&V$uD}fv7BWwUYMmGCIMGj z{8~4f?dWx0LX>Y-qi=!s6hE7+ubMW78h!`|R=KV%8FK zd9Sek(lv`S^5+9xYR`{X>yATq2OfeBt(}qyYA3{aLq|2d#^vB$R4#D)8lf9t!Y;+P z_6W7^{$}!gg?;4KjI39niyeEj#~ble%M>uw{nu#b`CHdh{gg9q+d8BrP^@~lDBI@d z7PMHwiV3pH(=wk3x<4;S!E(K=DJ>2!RAm*jrN_O@8jfGh%FKDK2Jufl-PsHs+4lH9 zDVKmh4;9;;mTf^PV;hRc zGZ1`0sMNGF2Q#}5#R#bM)tW_A=dSME$5(a2i}Ihk4u>_zBv%vI*myG)hHABMyPQj@ zM)WDfPOZ2LDPxwQFP3s9qT2x$(n(71$z;Qxd;tB$vX<;ZX<>Nsq(dQ>mhaX*MIFCf zb0p{bXj}2S`bD#rpHdTdNv!#{OR);Jsq8JJ*l1;(96~iudG#aZgj0Qo3WuL}YVZek z(SM)#(x7!4_(saUC6(W&b$isUNe3O4T~w_02Y#{Bs)T0h-r|>RiXN`FZb$o39EXiL z*RJ#X)VH`&nA(%q0JE_w3>ZQUex|DOv-oSu#vm zNS0_maoG$tauoZ;v)jT-lc=;EaufphG>)@S1@N~a5rr)*{bw*r-?o*rX6>8&zHcc*`CR~1#1jSw~d|R zwXi;)w4*Di+agG^bKz87RbPQwK!stmYMB_=wK@dlhtu9wFD@&T*Rq=*u7gj@78PR;rI9VW}r3UUH0!vA30jS z9UC??hXtMukpyu2>X*~v8;@W;`1_RbZHs(`$_8)1P;u9mwi4Rc0`sT=V!Y1o!I{Qq zTuHw3d^RR%uB5r{Ro1<>F8RPbj_b`$75gQNggjNu*H}~8;-HRVpN?w*H+KzOf}(^U z)d8)S!qI%E&Bf@3i1yh^Px1-jguC#MCUGbC&Rv0bg=h2Ms1B6?sLoFXEM>DdK;(^h zBZ=9iZF8CfgvLGLDUDAC>!hByzwDss&zxy_dFFE+ps2snc=RE+p+zrQ*E_9YM0{{Y z!fhZyCOLFWcsB~(RGiu+Zuz#hisxiIQ_CT@V-K)JH skXH~y@{pZ%H2RLzTI|$xG-@5%4N!D?9MV?={PtVpVC#adKM-=_zfn5szW@LL literal 0 HcmV?d00001 diff --git a/playground/assets/preload-module.js b/playground/assets/preload-module.js new file mode 100644 index 00000000000000..5d139fa7c2caeb --- /dev/null +++ b/playground/assets/preload-module.js @@ -0,0 +1,2 @@ +// referenced via , small enough to hit assetsInlineLimit +export const preloadedModule = 'preloaded' From 8492422b8f110625a90c702f42f30784e8cf19dc Mon Sep 17 00:00:00 2001 From: btea <2356281422@qq.com> Date: Fri, 4 Sep 2026 18:13:10 +0800 Subject: [PATCH 3/3] fix: resolve the actual package root in findNearestMainPackageData for nested package.json (#23356) --- .../vite/src/node/__tests__/packages.spec.ts | 112 ++++++++++++++++++ .../__snapshots__/license.spec.ts.snap | 12 ++ .../build/devtools/index.js | 4 + .../build/devtools/package.json | 6 + .../build/esm/index.js | 5 + .../build/esm/package.json | 4 + .../license/dep-license-type-marker/license | 3 + .../dep-license-type-marker/package.json | 9 ++ .../plugins/fixtures/license/index.html | 3 +- .../plugins/fixtures/license/package.json | 1 + packages/vite/src/node/packages.ts | 38 ++++-- pnpm-lock.yaml | 14 +++ 12 files changed, 201 insertions(+), 10 deletions(-) create mode 100644 packages/vite/src/node/__tests__/packages.spec.ts create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/index.js create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/package.json create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/index.js create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/package.json create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/license create mode 100644 packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/package.json diff --git a/packages/vite/src/node/__tests__/packages.spec.ts b/packages/vite/src/node/__tests__/packages.spec.ts new file mode 100644 index 00000000000000..159c7fa4110252 --- /dev/null +++ b/packages/vite/src/node/__tests__/packages.spec.ts @@ -0,0 +1,112 @@ +import fs from 'node:fs' +import os from 'node:os' +import path from 'node:path' +import { afterEach, expect, test } from 'vitest' +import { findNearestMainPackageData } from '../packages' + +let tempDir: string | undefined + +afterEach(() => { + if (tempDir) fs.rmSync(tempDir, { recursive: true, force: true }) + tempDir = undefined +}) + +function createFixtures(files: Record): string { + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vite-packages-')) + for (const [file, content] of Object.entries(files)) { + const target = path.join(tempDir, file) + fs.mkdirSync(path.dirname(target), { recursive: true }) + fs.writeFileSync( + target, + typeof content === 'string' ? content : JSON.stringify(content), + ) + } + return tempDir +} + +const projectManifest = { name: 'project' } + +// paths after realpath resolution under pnpm: +// `/node_modules/.pnpm/dep@1.0.0/node_modules/dep/...` +test('resolves the package root for the pnpm store layout', () => { + const root = createFixtures({ + 'package.json': projectManifest, + 'node_modules/.pnpm/dep@1.0.0/node_modules/dep/package.json': { + name: 'dep', + version: '1.0.0', + license: 'MIT', + }, + // nested type-marker manifest with a `name` but no `version` + 'node_modules/.pnpm/dep@1.0.0/node_modules/dep/build/esm/package.json': { + name: 'dep', + type: 'module', + }, + }) + const pkg = findNearestMainPackageData( + path.join(root, 'node_modules/.pnpm/dep@1.0.0/node_modules/dep/build/esm'), + ) + expect(pkg?.data).toMatchObject({ name: 'dep', version: '1.0.0' }) +}) + +// packages hoisted by pnpm to `node_modules/.pnpm/node_modules/` +test('resolves the package root for packages hoisted by pnpm', () => { + const root = createFixtures({ + 'package.json': projectManifest, + 'node_modules/.pnpm/node_modules/hoisted/package.json': { + name: 'hoisted', + version: '1.0.0', + }, + 'node_modules/.pnpm/node_modules/hoisted/build/esm/package.json': { + name: 'hoisted', + type: 'module', + }, + }) + const pkg = findNearestMainPackageData( + path.join(root, 'node_modules/.pnpm/node_modules/hoisted/build/esm'), + ) + expect(pkg?.data).toMatchObject({ name: 'hoisted', version: '1.0.0' }) +}) + +test('resolves the package root for scoped packages', () => { + const root = createFixtures({ + 'package.json': projectManifest, + 'node_modules/@scope/dep/package.json': { + name: '@scope/dep', + version: '2.0.0', + }, + 'node_modules/@scope/dep/dist/esm/package.json': { + name: '@scope/dep', + type: 'module', + }, + }) + const pkg = findNearestMainPackageData( + path.join(root, 'node_modules/@scope/dep/dist/esm'), + ) + expect(pkg?.data).toMatchObject({ name: '@scope/dep', version: '2.0.0' }) +}) + +// under Yarn PnP, packages are hosted inside zip archives at +// `.../cache/-npm--.zip/node_modules//...` (the cache +// may live outside the project, e.g. in `~/.yarn/berry/cache`). The path +// contains a synthesized `node_modules/` segment, so the layout-based +// resolution covers PnP without any PnP-specific handling +test('resolves the package root for the Yarn PnP zip layout', () => { + const root = createFixtures({ + 'package.json': projectManifest, + 'cache/engine.io-client-npm-6.6.6-fd14f4b531-10c0.zip/node_modules/engine.io-client/package.json': + { name: 'engine.io-client', version: '6.6.6', license: 'MIT' }, + // nested type-marker manifest with a `name` but no `version` + 'cache/engine.io-client-npm-6.6.6-fd14f4b531-10c0.zip/node_modules/engine.io-client/build/esm/package.json': + { name: 'engine.io-client', type: 'module' }, + }) + const pkg = findNearestMainPackageData( + path.join( + root, + 'cache/engine.io-client-npm-6.6.6-fd14f4b531-10c0.zip/node_modules/engine.io-client/build/esm', + ), + ) + expect(pkg?.data).toMatchObject({ + name: 'engine.io-client', + version: '6.6.6', + }) +}) diff --git a/packages/vite/src/node/__tests__/plugins/__snapshots__/license.spec.ts.snap b/packages/vite/src/node/__tests__/plugins/__snapshots__/license.spec.ts.snap index d93b6c9515daa3..1546143e444a75 100644 --- a/packages/vite/src/node/__tests__/plugins/__snapshots__/license.spec.ts.snap +++ b/packages/vite/src/node/__tests__/plugins/__snapshots__/license.spec.ts.snap @@ -14,6 +14,12 @@ exports[`json 1`] = ` "identifier": "MIT", "text": "MIT License\\n\\nCopyright (c) ..." }, + { + "name": "@vitejs/test-dep-license-type-marker", + "version": "1.0.0", + "identifier": "MIT", + "text": "MIT License\\n\\nCopyright (c) ..." + }, { "name": "@vitejs/test-dep-nested-license-isc", "version": "0.0.0", @@ -40,6 +46,12 @@ MIT License Copyright (c) ... +## @vitejs/test-dep-license-type-marker - 1.0.0 (MIT) + +MIT License + +Copyright (c) ... + ## @vitejs/test-dep-nested-license-isc - 0.0.0 (ISC) Copyright (c) ... diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/index.js b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/index.js new file mode 100644 index 00000000000000..e11c75b1f19d50 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/index.js @@ -0,0 +1,4 @@ +// Avoid to be inlined completely: https://github.com/rolldown/rolldown/issues/8100 +console.log() + +export default 'devtools' diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/package.json b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/package.json new file mode 100644 index 00000000000000..2bbae143ba4199 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitejs/test-dep-license-type-marker-devtools", + "version": "1.0.0", + "private": true, + "main": "index.js" +} diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/index.js b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/index.js new file mode 100644 index 00000000000000..053d82cc7498eb --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/index.js @@ -0,0 +1,5 @@ +// Avoid to be inlined completely: https://github.com/rolldown/rolldown/issues/8100 +console.log() + +export { default as devtools } from '../devtools/index.js' +export default 'ok' diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/package.json b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/package.json new file mode 100644 index 00000000000000..8b9091d41e41b5 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm/package.json @@ -0,0 +1,4 @@ +{ + "name": "@vitejs/test-dep-license-type-marker", + "type": "module" +} diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/license b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/license new file mode 100644 index 00000000000000..1732da241e5252 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/license @@ -0,0 +1,3 @@ +MIT License + +Copyright (c) ... diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/package.json b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/package.json new file mode 100644 index 00000000000000..5db5607a1f9c68 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/package.json @@ -0,0 +1,9 @@ +{ + "name": "@vitejs/test-dep-license-type-marker", + "private": true, + "version": "1.0.0", + "license": "MIT", + "exports": { + ".": "./build/esm/index.js" + } +} diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/index.html b/packages/vite/src/node/__tests__/plugins/fixtures/license/index.html index b0825ecb300d5b..cf1dd5f1e85b1e 100644 --- a/packages/vite/src/node/__tests__/plugins/fixtures/license/index.html +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/index.html @@ -1,5 +1,6 @@ diff --git a/packages/vite/src/node/__tests__/plugins/fixtures/license/package.json b/packages/vite/src/node/__tests__/plugins/fixtures/license/package.json index 4e06638e94f0cc..1f2a8eaa73484f 100644 --- a/packages/vite/src/node/__tests__/plugins/fixtures/license/package.json +++ b/packages/vite/src/node/__tests__/plugins/fixtures/license/package.json @@ -5,6 +5,7 @@ "type": "module", "dependencies": { "@vitejs/test-dep-license-mit": "file:./dep-license-mit", + "@vitejs/test-dep-license-type-marker": "file:./dep-license-type-marker", "@vitejs/test-dep-licence-cc0": "file:./dep-licence-cc0" } } diff --git a/packages/vite/src/node/packages.ts b/packages/vite/src/node/packages.ts index 2021af272c77ab..457aea0a07b544 100644 --- a/packages/vite/src/node/packages.ts +++ b/packages/vite/src/node/packages.ts @@ -158,20 +158,40 @@ export function findNearestPackageData( return null } -// Finds the nearest package.json with a `name` field +function isNodeModulesPackageRoot(pkgDir: string): boolean { + const parent = path.dirname(pkgDir) + if (path.basename(parent) === 'node_modules') { + return !path.basename(pkgDir).startsWith('@') + } + // scoped package root: `node_modules/@scope/pkg` + return ( + path.basename(parent).startsWith('@') && + path.basename(path.dirname(parent)) === 'node_modules' + ) +} + +// Finds the nearest package.json with a `name` field. For paths inside +// `node_modules`, the manifest at the package root is returned instead, which +// may be further up than the nearest manifest. export function findNearestMainPackageData( basedir: string, packageCache?: PackageCache, ): PackageData | null { const nearestPackage = findNearestPackageData(basedir, packageCache) - return ( - nearestPackage && - (nearestPackage.data.name - ? nearestPackage - : findNearestMainPackageData( - path.dirname(nearestPackage.dir), - packageCache, - )) + if (!nearestPackage) return null + if ( + isInNodeModules(nearestPackage.dir) && + !isNodeModulesPackageRoot(nearestPackage.dir) + ) { + return findNearestMainPackageData( + path.dirname(nearestPackage.dir), + packageCache, + ) + } + if (nearestPackage.data.name) return nearestPackage + return findNearestMainPackageData( + path.dirname(nearestPackage.dir), + packageCache, ) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d26a1a2ff9329..385614e87d3ad9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -600,6 +600,9 @@ importers: '@vitejs/test-dep-license-mit': specifier: file:./dep-license-mit version: file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit + '@vitejs/test-dep-license-type-marker': + specifier: file:./dep-license-type-marker + version: file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker packages/vite/src/node/__tests__/plugins/fixtures/license/dep-licence-cc0: {} @@ -609,6 +612,12 @@ importers: specifier: file:../dep-nested-license-isc version: file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc + packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker: {} + + packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/devtools: {} + + packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker/build/esm: {} + packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc: {} packages/vite/src/node/server/__tests__/fixtures/deno/nested: {} @@ -4492,6 +4501,9 @@ packages: '@vitejs/test-dep-license-mit@file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit': resolution: {directory: packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit, type: directory} + '@vitejs/test-dep-license-type-marker@file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker': + resolution: {directory: packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker, type: directory} + '@vitejs/test-dep-lodash-es@file:playground/optimize-deps/dep-lodash-es': resolution: {directory: playground/optimize-deps/dep-lodash-es, type: directory} @@ -10553,6 +10565,8 @@ snapshots: dependencies: '@vitejs/test-dep-nested-license-isc': file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc + '@vitejs/test-dep-license-type-marker@file:packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-type-marker': {} + '@vitejs/test-dep-lodash-es@file:playground/optimize-deps/dep-lodash-es': {} '@vitejs/test-dep-lodash.clonedeep@file:playground/optimize-deps/dep-lodash-clonedeep': {}