Skip to content

Commit cba13e8

Browse files
smeng9sapphi-red
andauthored
fix(optimizer): browser field bare import (fix #7599) (#10314)
Co-authored-by: sapphi-red <[email protected]>
1 parent 65dd88b commit cba13e8

File tree

9 files changed

+84
-1
lines changed

9 files changed

+84
-1
lines changed

packages/vite/src/node/plugins/resolve.ts

+39-1
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,8 @@ function tryResolveBrowserMapping(
11061106
externalize?: boolean
11071107
) {
11081108
let res: string | undefined
1109-
const pkg = importer && idToPkgMap.get(importer)
1109+
const pkg =
1110+
importer && (idToPkgMap.get(importer) || resolvePkg(importer, options))
11101111
if (pkg && isObject(pkg.data.browser)) {
11111112
const mapId = isFilePath ? './' + slash(path.relative(pkg.dir, id)) : id
11121113
const browserMappedPath = mapWithBrowserField(mapId, pkg.data.browser)
@@ -1165,3 +1166,40 @@ function getRealPath(resolved: string, preserveSymlinks?: boolean): string {
11651166
}
11661167
return normalizePath(resolved)
11671168
}
1169+
1170+
/**
1171+
* if importer was not resolved by vite's resolver previously
1172+
* (when esbuild resolved it)
1173+
* resolve importer's pkg and add to idToPkgMap
1174+
*/
1175+
function resolvePkg(importer: string, options: InternalResolveOptions) {
1176+
const { root, preserveSymlinks, packageCache } = options
1177+
1178+
if (importer.includes('\x00')) {
1179+
return null
1180+
}
1181+
1182+
const possiblePkgIds: string[] = []
1183+
for (let prevSlashIndex = -1; ; ) {
1184+
const slashIndex = importer.indexOf(isWindows ? '\\' : '/', prevSlashIndex)
1185+
if (slashIndex < 0) {
1186+
break
1187+
}
1188+
1189+
prevSlashIndex = slashIndex + 1
1190+
1191+
const possiblePkgId = importer.slice(0, slashIndex)
1192+
possiblePkgIds.push(possiblePkgId)
1193+
}
1194+
1195+
let pkg: PackageData | undefined
1196+
possiblePkgIds.reverse().find((pkgId) => {
1197+
pkg = resolvePackageData(pkgId, root, preserveSymlinks, packageCache)!
1198+
return pkg
1199+
})!
1200+
1201+
if (pkg) {
1202+
idToPkgMap.set(importer, pkg)
1203+
}
1204+
return pkg
1205+
}

playground/optimize-deps/__tests__/optimize-deps.spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ test('cjs browser field (axios)', async () => {
5858
expect(await page.textContent('.cjs-browser-field')).toBe('pong')
5959
})
6060

61+
test('cjs browser field bare', async () => {
62+
expect(await page.textContent('.cjs-browser-field-bare')).toBe('pong')
63+
})
64+
6165
test('dep from linked dep (lodash-es)', async () => {
6266
expect(await page.textContent('.deps-linked')).toBe('fooBarBaz')
6367
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
foo: 'foo'
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict'
2+
3+
const internal = require('./internal')
4+
5+
module.exports = internal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict'
2+
3+
// eslint-disable-next-line import/no-nodejs-modules
4+
const events = require('events')
5+
6+
module.exports = 'foo' in events ? 'pong' : ''
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "dep-cjs-browser-field-bare",
3+
"private": true,
4+
"version": "0.0.0",
5+
"main": "index.js",
6+
"browser": {
7+
"events": "./events-shim.js"
8+
}
9+
}

playground/optimize-deps/index.html

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ <h2>Dedupe (dep in linked & optimized package)</h2>
2929
<h2>CommonJS w/ browser field mapping (axios)</h2>
3030
<div>This should show pong: <span class="cjs-browser-field"></span></div>
3131

32+
<h2>CommonJS w/ bare id browser field mapping</h2>
33+
<div>This should show pong: <span class="cjs-browser-field-bare"></span></div>
34+
3235
<h2>Detecting linked src package and optimizing its deps (lodash-es)</h2>
3336
<div>This should show fooBarBaz: <span class="deps-linked"></span></div>
3437

@@ -100,6 +103,9 @@ <h2>Non Optimized Module isn't duplicated</h2>
100103
// test dep detection in globbed files
101104
const globbed = import.meta.glob('./glob/*.js', { eager: true })
102105

106+
import cjsBrowerFieldBare from 'dep-cjs-browser-field-bare'
107+
text('.cjs-browser-field-bare', cjsBrowerFieldBare)
108+
103109
import { camelCase } from 'dep-linked'
104110
text('.deps-linked', camelCase('foo-bar-baz'))
105111

playground/optimize-deps/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"axios": "^0.27.2",
1313
"clipboard": "^2.0.11",
14+
"dep-cjs-browser-field-bare": "file:./dep-cjs-browser-field-bare",
1415
"dep-cjs-compiled-from-cjs": "file:./dep-cjs-compiled-from-cjs",
1516
"dep-cjs-compiled-from-esm": "file:./dep-cjs-compiled-from-esm",
1617
"dep-cjs-with-assets": "file:./dep-cjs-with-assets",

pnpm-lock.yaml

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)