Skip to content

Commit

Permalink
feat: esbuild based dep pre-bundling
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 22, 2021
1 parent fa37456 commit 6e7f652
Show file tree
Hide file tree
Showing 13 changed files with 352 additions and 327 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ test('forced include', async () => {
expect(await page.textContent('.force-include')).toMatch(`[success]`)
})

test('import * from optimized dep', async () => {
expect(await page.textContent('.import-star')).toMatch(`[success]`)
})

test('dep with css import', async () => {
expect(await getColor('h1')).toBe('red')
})
Expand Down
11 changes: 11 additions & 0 deletions packages/playground/optimize-deps/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ <h2>Detecting linked src package and optimizing its deps (lodash-es)</h2>
<h2>Optimizing force included dep even when it's linked</h2>
<div class="force-include"></div>

<h2>import * as ...</h2>
<div class="import-star"></div>

<h2>Dep w/ special file format supported via plugins</h2>
<div class="plugin"></div>

Expand All @@ -37,4 +40,12 @@ <h2>Dep w/ special file format supported via plugins</h2>
import { msg, VueSFC } from 'optimize-deps-linked-include'
document.querySelector('.force-include').textContent = msg
document.querySelector('.plugin').textContent = VueSFC.render()

import * as linked from 'optimize-deps-linked-include'
const keys = Object.keys(linked)
if (keys.length) {
document.querySelector('.import-star').textContent = `[success] ${keys.join(
', '
)}`
}
</script>
4 changes: 2 additions & 2 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
"//": "READ .github/contributing.md to understand what to put under deps vs. devDeps!",
"dependencies": {
"esbuild": "^0.8.26",
"esbuild": "^0.8.34",
"postcss": "^8.2.1",
"resolve": "^1.19.0",
"rollup": "^2.35.1"
Expand Down Expand Up @@ -76,6 +76,7 @@
"acorn-numeric-separator": "^0.3.6",
"acorn-static-class-features": "^0.2.4",
"brotli-size": "^4.0.0",
"builtin-modules": "^3.2.0",
"cac": "^6.6.1",
"chalk": "^4.1.0",
"chokidar": "^3.4.3",
Expand All @@ -94,7 +95,6 @@
"execa": "^5.0.0",
"fast-glob": "^3.2.4",
"http-proxy": "^1.18.1",
"isbuiltin": "^1.0.0",
"launch-editor-middleware": "^2.2.1",
"magic-string": "^0.25.7",
"merge-source-map": "^1.1.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/vite/src/node/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export const FS_PREFIX = `/@fs/`
* Prefix for resolved Ids that are not valid browser import specifiers
*/
export const VALID_ID_PREFIX = `/@id/`

export const OPTIMIZED_PREFIX = `/@optimized/`

/**
* Some Rollup plugins use ids that starts with the null byte \0 to avoid
* collisions, but it is not permitted in import URLs so we have to replace
Expand All @@ -25,7 +28,7 @@ export const CLIENT_PUBLIC_PATH = `/@vite/client`
export const CLIENT_ENTRY = require.resolve('vite/dist/client/client.js')
export const CLIENT_DIR = path.dirname(CLIENT_ENTRY)

const knownAssetTypes = [
export const knownAssetTypes = [
// images
'png',
'jpe?g',
Expand Down
86 changes: 0 additions & 86 deletions packages/vite/src/node/optimizer/depAssetPlugin.ts

This file was deleted.

38 changes: 0 additions & 38 deletions packages/vite/src/node/optimizer/depMetadataPlugin.ts

This file was deleted.

95 changes: 95 additions & 0 deletions packages/vite/src/node/optimizer/esbuildDepPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import path from 'path'
import { Plugin } from 'esbuild'
import { knownAssetTypes } from '../constants'
import builtins from 'builtin-modules'
import { ResolvedConfig } from '..'
import chalk from 'chalk'
import { deepImportRE } from '../utils'

const externalTypes = ['css', 'vue', 'svelte', ...knownAssetTypes]

export function esbuildDepPlugin(
qualified: Record<string, string>,
config: ResolvedConfig,
transitiveOptimized: Record<string, true>
): Plugin {
return {
name: 'vite:dep-pre-bundle',
setup(build) {
// externalize assets and commonly known non-js file types
build.onResolve(
{
filter: new RegExp(`\\.(` + externalTypes.join('|') + `)(\\?.*)?$`)
},
({ path: _path, importer }) => {
if (_path.startsWith('.')) {
const dir = path.dirname(importer)
return {
path: path.resolve(dir, _path),
external: true
}
}
}
)

// record transitive deps
build.onResolve({ filter: /^[\w@]/ }, ({ path: id }) => {
if (!(id in qualified) && !/:\/\//.test(id)) {
const deepMatch = id.match(deepImportRE)
const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : id
transitiveOptimized[pkgId] = true
}
return null
})

// redirect node-builtins to empty module for browser
build.onResolve(
{
filter: new RegExp(`^(${builtins.join('|')})$`)
},
({ path: id, importer }) => {
config.logger.warn(
chalk.yellow(
`externalized node built-in "${id}" to empty module. ` +
`(imported by: ${chalk.white.dim(importer)})`
)
)
return {
path: id,
namespace: 'browser-external'
}
}
)

build.onLoad(
{ filter: /.*/, namespace: 'browser-external' },
({ path: id }) => {
return {
contents:
`export default new Proxy({}, {
get() {
throw new Error('Module "${id}" has been externalized for ` +
`browser compatibility and cannot be accessed in client code.')
}
})`
}
}
)

if (config.dedupe) {
build.onResolve(
{
filter: new RegExp(`^(${config.dedupe.join('|')})$`)
},
({ path: id }) => {
if (id in qualified) {
return {
path: path.resolve(qualified[id])
}
}
}
)
}
}
}
}
Loading

0 comments on commit 6e7f652

Please sign in to comment.