Skip to content

Commit 6e7f652

Browse files
committed
feat: esbuild based dep pre-bundling
1 parent fa37456 commit 6e7f652

File tree

13 files changed

+352
-327
lines changed

13 files changed

+352
-327
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ test('forced include', async () => {
3030
expect(await page.textContent('.force-include')).toMatch(`[success]`)
3131
})
3232

33+
test('import * from optimized dep', async () => {
34+
expect(await page.textContent('.import-star')).toMatch(`[success]`)
35+
})
36+
3337
test('dep with css import', async () => {
3438
expect(await getColor('h1')).toBe('red')
3539
})

packages/playground/optimize-deps/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ <h2>Detecting linked src package and optimizing its deps (lodash-es)</h2>
2121
<h2>Optimizing force included dep even when it's linked</h2>
2222
<div class="force-include"></div>
2323

24+
<h2>import * as ...</h2>
25+
<div class="import-star"></div>
26+
2427
<h2>Dep w/ special file format supported via plugins</h2>
2528
<div class="plugin"></div>
2629

@@ -37,4 +40,12 @@ <h2>Dep w/ special file format supported via plugins</h2>
3740
import { msg, VueSFC } from 'optimize-deps-linked-include'
3841
document.querySelector('.force-include').textContent = msg
3942
document.querySelector('.plugin').textContent = VueSFC.render()
43+
44+
import * as linked from 'optimize-deps-linked-include'
45+
const keys = Object.keys(linked)
46+
if (keys.length) {
47+
document.querySelector('.import-star').textContent = `[success] ${keys.join(
48+
', '
49+
)}`
50+
}
4051
</script>

packages/vite/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
},
4545
"//": "READ .github/contributing.md to understand what to put under deps vs. devDeps!",
4646
"dependencies": {
47-
"esbuild": "^0.8.26",
47+
"esbuild": "^0.8.34",
4848
"postcss": "^8.2.1",
4949
"resolve": "^1.19.0",
5050
"rollup": "^2.35.1"
@@ -76,6 +76,7 @@
7676
"acorn-numeric-separator": "^0.3.6",
7777
"acorn-static-class-features": "^0.2.4",
7878
"brotli-size": "^4.0.0",
79+
"builtin-modules": "^3.2.0",
7980
"cac": "^6.6.1",
8081
"chalk": "^4.1.0",
8182
"chokidar": "^3.4.3",
@@ -94,7 +95,6 @@
9495
"execa": "^5.0.0",
9596
"fast-glob": "^3.2.4",
9697
"http-proxy": "^1.18.1",
97-
"isbuiltin": "^1.0.0",
9898
"launch-editor-middleware": "^2.2.1",
9999
"magic-string": "^0.25.7",
100100
"merge-source-map": "^1.1.0",

packages/vite/src/node/constants.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export const FS_PREFIX = `/@fs/`
1313
* Prefix for resolved Ids that are not valid browser import specifiers
1414
*/
1515
export const VALID_ID_PREFIX = `/@id/`
16+
17+
export const OPTIMIZED_PREFIX = `/@optimized/`
18+
1619
/**
1720
* Some Rollup plugins use ids that starts with the null byte \0 to avoid
1821
* collisions, but it is not permitted in import URLs so we have to replace
@@ -25,7 +28,7 @@ export const CLIENT_PUBLIC_PATH = `/@vite/client`
2528
export const CLIENT_ENTRY = require.resolve('vite/dist/client/client.js')
2629
export const CLIENT_DIR = path.dirname(CLIENT_ENTRY)
2730

28-
const knownAssetTypes = [
31+
export const knownAssetTypes = [
2932
// images
3033
'png',
3134
'jpe?g',

packages/vite/src/node/optimizer/depAssetPlugin.ts

Lines changed: 0 additions & 86 deletions
This file was deleted.

packages/vite/src/node/optimizer/depMetadataPlugin.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import path from 'path'
2+
import { Plugin } from 'esbuild'
3+
import { knownAssetTypes } from '../constants'
4+
import builtins from 'builtin-modules'
5+
import { ResolvedConfig } from '..'
6+
import chalk from 'chalk'
7+
import { deepImportRE } from '../utils'
8+
9+
const externalTypes = ['css', 'vue', 'svelte', ...knownAssetTypes]
10+
11+
export function esbuildDepPlugin(
12+
qualified: Record<string, string>,
13+
config: ResolvedConfig,
14+
transitiveOptimized: Record<string, true>
15+
): Plugin {
16+
return {
17+
name: 'vite:dep-pre-bundle',
18+
setup(build) {
19+
// externalize assets and commonly known non-js file types
20+
build.onResolve(
21+
{
22+
filter: new RegExp(`\\.(` + externalTypes.join('|') + `)(\\?.*)?$`)
23+
},
24+
({ path: _path, importer }) => {
25+
if (_path.startsWith('.')) {
26+
const dir = path.dirname(importer)
27+
return {
28+
path: path.resolve(dir, _path),
29+
external: true
30+
}
31+
}
32+
}
33+
)
34+
35+
// record transitive deps
36+
build.onResolve({ filter: /^[\w@]/ }, ({ path: id }) => {
37+
if (!(id in qualified) && !/:\/\//.test(id)) {
38+
const deepMatch = id.match(deepImportRE)
39+
const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : id
40+
transitiveOptimized[pkgId] = true
41+
}
42+
return null
43+
})
44+
45+
// redirect node-builtins to empty module for browser
46+
build.onResolve(
47+
{
48+
filter: new RegExp(`^(${builtins.join('|')})$`)
49+
},
50+
({ path: id, importer }) => {
51+
config.logger.warn(
52+
chalk.yellow(
53+
`externalized node built-in "${id}" to empty module. ` +
54+
`(imported by: ${chalk.white.dim(importer)})`
55+
)
56+
)
57+
return {
58+
path: id,
59+
namespace: 'browser-external'
60+
}
61+
}
62+
)
63+
64+
build.onLoad(
65+
{ filter: /.*/, namespace: 'browser-external' },
66+
({ path: id }) => {
67+
return {
68+
contents:
69+
`export default new Proxy({}, {
70+
get() {
71+
throw new Error('Module "${id}" has been externalized for ` +
72+
`browser compatibility and cannot be accessed in client code.')
73+
}
74+
})`
75+
}
76+
}
77+
)
78+
79+
if (config.dedupe) {
80+
build.onResolve(
81+
{
82+
filter: new RegExp(`^(${config.dedupe.join('|')})$`)
83+
},
84+
({ path: id }) => {
85+
if (id in qualified) {
86+
return {
87+
path: path.resolve(qualified[id])
88+
}
89+
}
90+
}
91+
)
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)