vite 2.6.0-beta.0 → 2.6.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vite might be problematic. Click here for more details.
- package/CHANGELOG.md +66 -0
- package/LICENSE.md +161 -3011
- package/bin/vite.js +2 -1
- package/dist/node/chunks/{dep-91aa74e8.js → dep-1e0a75a8.js} +58 -32
- package/dist/node/chunks/dep-1e0a75a8.js.map +1 -0
- package/dist/node/chunks/{dep-e36486f6.js → dep-ac1b4bf9.js} +1 -1
- package/dist/node/chunks/dep-ac1b4bf9.js.map +1 -0
- package/dist/node/chunks/{dep-c7e510f9.js → dep-ba6b30a0.js} +27538 -4953
- package/dist/node/chunks/dep-ba6b30a0.js.map +1 -0
- package/dist/node/chunks/{dep-11213a75.js → dep-c4cf6e92.js} +19 -6
- package/dist/node/chunks/dep-c4cf6e92.js.map +1 -0
- package/dist/node/chunks/{dep-eb6ef720.js → dep-d574094c.js} +18 -5
- package/dist/node/chunks/dep-d574094c.js.map +1 -0
- package/dist/node/chunks/{dep-0d2f9464.js → dep-e39b05d6.js} +18 -5
- package/dist/node/chunks/dep-e39b05d6.js.map +1 -0
- package/dist/node/cli.js +60 -23992
- package/dist/node/cli.js.map +1 -1
- package/dist/node/index.d.ts +26 -8
- package/dist/node/index.js +18 -15
- package/dist/node/index.js.map +1 -1
- package/dist/node/terser.js +102 -55
- package/package.json +28 -13
- package/types/package.json +3 -0
- package/api-extractor.json +0 -54
- package/dist/node/chunks/dep-0d2f9464.js.map +0 -1
- package/dist/node/chunks/dep-11213a75.js.map +0 -1
- package/dist/node/chunks/dep-91aa74e8.js.map +0 -1
- package/dist/node/chunks/dep-c7e510f9.js.map +0 -1
- package/dist/node/chunks/dep-e36486f6.js.map +0 -1
- package/dist/node/chunks/dep-eb6ef720.js.map +0 -1
- package/dist/node/terser.js.map +0 -1
- package/rollup.config.js +0 -389
- package/scripts/patchTypes.js +0 -70
- package/src/node/__tests__/asset.spec.ts +0 -156
- package/src/node/__tests__/build.spec.ts +0 -67
- package/src/node/__tests__/config.spec.ts +0 -166
- package/src/node/__tests__/packages/name/package.json +0 -3
- package/src/node/__tests__/packages/noname/package.json +0 -1
- package/src/node/__tests__/plugins/css.spec.ts +0 -116
- package/src/node/__tests__/scan.spec.ts +0 -118
- package/src/node/__tests__/utils.spec.ts +0 -40
- package/src/node/build.ts +0 -783
- package/src/node/cli.ts +0 -239
- package/src/node/config.ts +0 -1033
- package/src/node/constants.ts +0 -87
- package/src/node/importGlob.ts +0 -173
- package/src/node/index.ts +0 -88
- package/src/node/logger.ts +0 -167
- package/src/node/optimizer/esbuildDepPlugin.ts +0 -216
- package/src/node/optimizer/index.ts +0 -410
- package/src/node/optimizer/registerMissing.ts +0 -102
- package/src/node/optimizer/scan.ts +0 -457
- package/src/node/plugin.ts +0 -138
- package/src/node/plugins/asset.ts +0 -365
- package/src/node/plugins/assetImportMetaUrl.ts +0 -99
- package/src/node/plugins/clientInjections.ts +0 -72
- package/src/node/plugins/css.ts +0 -1279
- package/src/node/plugins/dataUri.ts +0 -64
- package/src/node/plugins/define.ts +0 -107
- package/src/node/plugins/esbuild.ts +0 -280
- package/src/node/plugins/html.ts +0 -673
- package/src/node/plugins/importAnalysis.ts +0 -614
- package/src/node/plugins/importAnalysisBuild.ts +0 -334
- package/src/node/plugins/index.ts +0 -69
- package/src/node/plugins/json.ts +0 -75
- package/src/node/plugins/loadFallback.ts +0 -19
- package/src/node/plugins/manifest.ts +0 -123
- package/src/node/plugins/modulePreloadPolyfill.ts +0 -100
- package/src/node/plugins/preAlias.ts +0 -22
- package/src/node/plugins/reporter.ts +0 -244
- package/src/node/plugins/resolve.ts +0 -925
- package/src/node/plugins/terser.ts +0 -40
- package/src/node/plugins/wasm.ts +0 -72
- package/src/node/plugins/worker.ts +0 -117
- package/src/node/preview.ts +0 -82
- package/src/node/server/__tests__/fixtures/none/nested/package.json +0 -3
- package/src/node/server/__tests__/fixtures/pnpm/nested/package.json +0 -3
- package/src/node/server/__tests__/fixtures/pnpm/package.json +0 -3
- package/src/node/server/__tests__/fixtures/pnpm/pnpm-workspace.yaml +0 -0
- package/src/node/server/__tests__/fixtures/yarn/nested/package.json +0 -3
- package/src/node/server/__tests__/fixtures/yarn/package.json +0 -6
- package/src/node/server/__tests__/search-root.spec.ts +0 -31
- package/src/node/server/hmr.ts +0 -489
- package/src/node/server/http.ts +0 -198
- package/src/node/server/index.ts +0 -705
- package/src/node/server/middlewares/base.ts +0 -52
- package/src/node/server/middlewares/error.ts +0 -98
- package/src/node/server/middlewares/indexHtml.ts +0 -170
- package/src/node/server/middlewares/proxy.ts +0 -124
- package/src/node/server/middlewares/spaFallback.ts +0 -32
- package/src/node/server/middlewares/static.ts +0 -153
- package/src/node/server/middlewares/time.ts +0 -18
- package/src/node/server/middlewares/transform.ts +0 -196
- package/src/node/server/moduleGraph.ts +0 -200
- package/src/node/server/openBrowser.ts +0 -101
- package/src/node/server/pluginContainer.ts +0 -546
- package/src/node/server/searchRoot.ts +0 -70
- package/src/node/server/send.ts +0 -54
- package/src/node/server/sourcemap.ts +0 -54
- package/src/node/server/transformRequest.ts +0 -168
- package/src/node/server/ws.ts +0 -131
- package/src/node/ssr/__tests__/ssrTransform.spec.ts +0 -309
- package/src/node/ssr/ssrExternal.ts +0 -161
- package/src/node/ssr/ssrManifestPlugin.ts +0 -53
- package/src/node/ssr/ssrModuleLoader.ts +0 -214
- package/src/node/ssr/ssrStacktrace.ts +0 -75
- package/src/node/ssr/ssrTransform.ts +0 -452
- package/src/node/tsconfig.json +0 -14
- package/src/node/utils.ts +0 -565
- package/tsconfig.base.json +0 -11
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { Loader, Plugin, ImportKind } from 'esbuild'
|
|
3
|
-
import { KNOWN_ASSET_TYPES } from '../constants'
|
|
4
|
-
import { ResolvedConfig } from '..'
|
|
5
|
-
import {
|
|
6
|
-
isRunningWithYarnPnp,
|
|
7
|
-
flattenId,
|
|
8
|
-
normalizePath,
|
|
9
|
-
isExternalUrl,
|
|
10
|
-
isBuiltin
|
|
11
|
-
} from '../utils'
|
|
12
|
-
import { browserExternalId } from '../plugins/resolve'
|
|
13
|
-
import { ExportsData } from '.'
|
|
14
|
-
|
|
15
|
-
const externalTypes = [
|
|
16
|
-
'css',
|
|
17
|
-
// supported pre-processor types
|
|
18
|
-
'less',
|
|
19
|
-
'sass',
|
|
20
|
-
'scss',
|
|
21
|
-
'styl',
|
|
22
|
-
'stylus',
|
|
23
|
-
'pcss',
|
|
24
|
-
'postcss',
|
|
25
|
-
// known SFC types
|
|
26
|
-
'vue',
|
|
27
|
-
'svelte',
|
|
28
|
-
'marko',
|
|
29
|
-
// JSX/TSX may be configured to be compiled differently from how esbuild
|
|
30
|
-
// handles it by default, so exclude them as well
|
|
31
|
-
'jsx',
|
|
32
|
-
'tsx',
|
|
33
|
-
...KNOWN_ASSET_TYPES
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
export function esbuildDepPlugin(
|
|
37
|
-
qualified: Record<string, string>,
|
|
38
|
-
exportsData: Record<string, ExportsData>,
|
|
39
|
-
config: ResolvedConfig,
|
|
40
|
-
ssr?: boolean
|
|
41
|
-
): Plugin {
|
|
42
|
-
// default resolver which prefers ESM
|
|
43
|
-
const _resolve = config.createResolver({ asSrc: false })
|
|
44
|
-
|
|
45
|
-
// cjs resolver that prefers Node
|
|
46
|
-
const _resolveRequire = config.createResolver({
|
|
47
|
-
asSrc: false,
|
|
48
|
-
isRequire: true
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const resolve = (
|
|
52
|
-
id: string,
|
|
53
|
-
importer: string,
|
|
54
|
-
kind: ImportKind,
|
|
55
|
-
resolveDir?: string
|
|
56
|
-
): Promise<string | undefined> => {
|
|
57
|
-
let _importer: string
|
|
58
|
-
// explicit resolveDir - this is passed only during yarn pnp resolve for
|
|
59
|
-
// entries
|
|
60
|
-
if (resolveDir) {
|
|
61
|
-
_importer = normalizePath(path.join(resolveDir, '*'))
|
|
62
|
-
} else {
|
|
63
|
-
// map importer ids to file paths for correct resolution
|
|
64
|
-
_importer = importer in qualified ? qualified[importer] : importer
|
|
65
|
-
}
|
|
66
|
-
const resolver = kind.startsWith('require') ? _resolveRequire : _resolve
|
|
67
|
-
return resolver(id, _importer, undefined, ssr)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
name: 'vite:dep-pre-bundle',
|
|
72
|
-
setup(build) {
|
|
73
|
-
// externalize assets and commonly known non-js file types
|
|
74
|
-
build.onResolve(
|
|
75
|
-
{
|
|
76
|
-
filter: new RegExp(`\\.(` + externalTypes.join('|') + `)(\\?.*)?$`)
|
|
77
|
-
},
|
|
78
|
-
async ({ path: id, importer, kind }) => {
|
|
79
|
-
const resolved = await resolve(id, importer, kind)
|
|
80
|
-
if (resolved) {
|
|
81
|
-
return {
|
|
82
|
-
path: resolved,
|
|
83
|
-
external: true
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
function resolveEntry(id: string) {
|
|
90
|
-
const flatId = flattenId(id)
|
|
91
|
-
if (flatId in qualified) {
|
|
92
|
-
return {
|
|
93
|
-
path: flatId,
|
|
94
|
-
namespace: 'dep'
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
build.onResolve(
|
|
100
|
-
{ filter: /^[\w@][^:]/ },
|
|
101
|
-
async ({ path: id, importer, kind }) => {
|
|
102
|
-
// ensure esbuild uses our resolved entries
|
|
103
|
-
let entry: { path: string; namespace: string } | undefined
|
|
104
|
-
// if this is an entry, return entry namespace resolve result
|
|
105
|
-
if (!importer) {
|
|
106
|
-
if ((entry = resolveEntry(id))) return entry
|
|
107
|
-
// check if this is aliased to an entry - also return entry namespace
|
|
108
|
-
const aliased = await _resolve(id, undefined, true)
|
|
109
|
-
if (aliased && (entry = resolveEntry(aliased))) {
|
|
110
|
-
return entry
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// use vite's own resolver
|
|
115
|
-
const resolved = await resolve(id, importer, kind)
|
|
116
|
-
if (resolved) {
|
|
117
|
-
if (resolved.startsWith(browserExternalId)) {
|
|
118
|
-
return {
|
|
119
|
-
path: id,
|
|
120
|
-
namespace: 'browser-external'
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (isExternalUrl(resolved) || (ssr && isBuiltin(id))) {
|
|
124
|
-
return {
|
|
125
|
-
path: resolved,
|
|
126
|
-
external: true
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return {
|
|
130
|
-
path: path.resolve(resolved)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
// For entry files, we'll read it ourselves and construct a proxy module
|
|
137
|
-
// to retain the entry's raw id instead of file path so that esbuild
|
|
138
|
-
// outputs desired output file structure.
|
|
139
|
-
// It is necessary to do the re-exporting to separate the virtual proxy
|
|
140
|
-
// module from the actual module since the actual module may get
|
|
141
|
-
// referenced via relative imports - if we don't separate the proxy and
|
|
142
|
-
// the actual module, esbuild will create duplicated copies of the same
|
|
143
|
-
// module!
|
|
144
|
-
const root = path.resolve(config.root)
|
|
145
|
-
build.onLoad({ filter: /.*/, namespace: 'dep' }, ({ path: id }) => {
|
|
146
|
-
const entryFile = qualified[id]
|
|
147
|
-
|
|
148
|
-
let relativePath = normalizePath(path.relative(root, entryFile))
|
|
149
|
-
if (
|
|
150
|
-
!relativePath.startsWith('./') &&
|
|
151
|
-
!relativePath.startsWith('../') &&
|
|
152
|
-
relativePath !== '.'
|
|
153
|
-
) {
|
|
154
|
-
relativePath = `./${relativePath}`
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
let contents = ''
|
|
158
|
-
const data = exportsData[id]
|
|
159
|
-
const [imports, exports] = data
|
|
160
|
-
if (!imports.length && !exports.length) {
|
|
161
|
-
// cjs
|
|
162
|
-
contents += `export default require("${relativePath}");`
|
|
163
|
-
} else {
|
|
164
|
-
if (exports.includes('default')) {
|
|
165
|
-
contents += `import d from "${relativePath}";export default d;`
|
|
166
|
-
}
|
|
167
|
-
if (
|
|
168
|
-
data.hasReExports ||
|
|
169
|
-
exports.length > 1 ||
|
|
170
|
-
exports[0] !== 'default'
|
|
171
|
-
) {
|
|
172
|
-
contents += `\nexport * from "${relativePath}"`
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
let ext = path.extname(entryFile).slice(1)
|
|
177
|
-
if (ext === 'mjs') ext = 'js'
|
|
178
|
-
return {
|
|
179
|
-
loader: ext as Loader,
|
|
180
|
-
contents,
|
|
181
|
-
resolveDir: root
|
|
182
|
-
}
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
build.onLoad(
|
|
186
|
-
{ filter: /.*/, namespace: 'browser-external' },
|
|
187
|
-
({ path: id }) => {
|
|
188
|
-
return {
|
|
189
|
-
contents:
|
|
190
|
-
`export default new Proxy({}, {
|
|
191
|
-
get() {
|
|
192
|
-
throw new Error('Module "${id}" has been externalized for ` +
|
|
193
|
-
`browser compatibility and cannot be accessed in client code.')
|
|
194
|
-
}
|
|
195
|
-
})`
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
// yarn 2 pnp compat
|
|
201
|
-
if (isRunningWithYarnPnp) {
|
|
202
|
-
build.onResolve(
|
|
203
|
-
{ filter: /.*/ },
|
|
204
|
-
async ({ path, importer, kind, resolveDir }) => ({
|
|
205
|
-
// pass along resolveDir for entries
|
|
206
|
-
path: await resolve(path, importer, kind, resolveDir)
|
|
207
|
-
})
|
|
208
|
-
)
|
|
209
|
-
build.onLoad({ filter: /.*/ }, async (args) => ({
|
|
210
|
-
contents: await require('fs').promises.readFile(args.path),
|
|
211
|
-
loader: 'default'
|
|
212
|
-
}))
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import { createHash } from 'crypto'
|
|
5
|
-
import { build, BuildOptions as EsbuildBuildOptions } from 'esbuild'
|
|
6
|
-
import { ResolvedConfig } from '../config'
|
|
7
|
-
import {
|
|
8
|
-
createDebugger,
|
|
9
|
-
emptyDir,
|
|
10
|
-
lookupFile,
|
|
11
|
-
normalizePath,
|
|
12
|
-
writeFile,
|
|
13
|
-
flattenId,
|
|
14
|
-
normalizeId
|
|
15
|
-
} from '../utils'
|
|
16
|
-
import { esbuildDepPlugin } from './esbuildDepPlugin'
|
|
17
|
-
import { ImportSpecifier, init, parse } from 'es-module-lexer'
|
|
18
|
-
import { scanImports } from './scan'
|
|
19
|
-
import { transformWithEsbuild } from '../plugins/esbuild'
|
|
20
|
-
|
|
21
|
-
const debug = createDebugger('vite:deps')
|
|
22
|
-
|
|
23
|
-
export type ExportsData = [ImportSpecifier[], string[]] & {
|
|
24
|
-
// es-module-lexer has a facade detection but isn't always accurate for our
|
|
25
|
-
// use case when the module has default export
|
|
26
|
-
hasReExports?: true
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface DepOptimizationOptions {
|
|
30
|
-
/**
|
|
31
|
-
* By default, Vite will crawl your index.html to detect dependencies that
|
|
32
|
-
* need to be pre-bundled. If build.rollupOptions.input is specified, Vite
|
|
33
|
-
* will crawl those entry points instead.
|
|
34
|
-
*
|
|
35
|
-
* If neither of these fit your needs, you can specify custom entries using
|
|
36
|
-
* this option - the value should be a fast-glob pattern or array of patterns
|
|
37
|
-
* (https://github.com/mrmlnc/fast-glob#basic-syntax) that are relative from
|
|
38
|
-
* vite project root. This will overwrite default entries inference.
|
|
39
|
-
*/
|
|
40
|
-
entries?: string | string[]
|
|
41
|
-
/**
|
|
42
|
-
* Force optimize listed dependencies (must be resolvable import paths,
|
|
43
|
-
* cannot be globs).
|
|
44
|
-
*/
|
|
45
|
-
include?: string[]
|
|
46
|
-
/**
|
|
47
|
-
* Do not optimize these dependencies (must be resolvable import paths,
|
|
48
|
-
* cannot be globs).
|
|
49
|
-
*/
|
|
50
|
-
exclude?: string[]
|
|
51
|
-
/**
|
|
52
|
-
* Options to pass to esbuild during the dep scanning and optimization
|
|
53
|
-
*
|
|
54
|
-
* Certain options are omitted since changing them would not be compatible
|
|
55
|
-
* with Vite's dep optimization.
|
|
56
|
-
*
|
|
57
|
-
* - `external` is also omitted, use Vite's `optimizeDeps.exclude` option
|
|
58
|
-
* - `plugins` are merged with Vite's dep plugin
|
|
59
|
-
* - `keepNames` takes precedence over the deprecated `optimizeDeps.keepNames`
|
|
60
|
-
*
|
|
61
|
-
* https://esbuild.github.io/api
|
|
62
|
-
*/
|
|
63
|
-
esbuildOptions?: Omit<
|
|
64
|
-
EsbuildBuildOptions,
|
|
65
|
-
| 'bundle'
|
|
66
|
-
| 'entryPoints'
|
|
67
|
-
| 'external'
|
|
68
|
-
| 'write'
|
|
69
|
-
| 'watch'
|
|
70
|
-
| 'outdir'
|
|
71
|
-
| 'outfile'
|
|
72
|
-
| 'outbase'
|
|
73
|
-
| 'outExtension'
|
|
74
|
-
| 'metafile'
|
|
75
|
-
>
|
|
76
|
-
/**
|
|
77
|
-
* @deprecated use `esbuildOptions.keepNames`
|
|
78
|
-
*/
|
|
79
|
-
keepNames?: boolean
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface DepOptimizationMetadata {
|
|
83
|
-
/**
|
|
84
|
-
* The main hash is determined by user config and dependency lockfiles.
|
|
85
|
-
* This is checked on server startup to avoid unnecessary re-bundles.
|
|
86
|
-
*/
|
|
87
|
-
hash: string
|
|
88
|
-
/**
|
|
89
|
-
* The browser hash is determined by the main hash plus additional dependencies
|
|
90
|
-
* discovered at runtime. This is used to invalidate browser requests to
|
|
91
|
-
* optimized deps.
|
|
92
|
-
*/
|
|
93
|
-
browserHash: string
|
|
94
|
-
optimized: Record<
|
|
95
|
-
string,
|
|
96
|
-
{
|
|
97
|
-
file: string
|
|
98
|
-
src: string
|
|
99
|
-
needsInterop: boolean
|
|
100
|
-
}
|
|
101
|
-
>
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function optimizeDeps(
|
|
105
|
-
config: ResolvedConfig,
|
|
106
|
-
force = config.server.force,
|
|
107
|
-
asCommand = false,
|
|
108
|
-
newDeps?: Record<string, string>, // missing imports encountered after server has started
|
|
109
|
-
ssr?: boolean
|
|
110
|
-
): Promise<DepOptimizationMetadata | null> {
|
|
111
|
-
config = {
|
|
112
|
-
...config,
|
|
113
|
-
command: 'build'
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const { root, logger, cacheDir } = config
|
|
117
|
-
const log = asCommand ? logger.info : debug
|
|
118
|
-
|
|
119
|
-
if (!cacheDir) {
|
|
120
|
-
log(`No cache directory. Skipping.`)
|
|
121
|
-
return null
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const dataPath = path.join(cacheDir, '_metadata.json')
|
|
125
|
-
const mainHash = getDepHash(root, config)
|
|
126
|
-
const data: DepOptimizationMetadata = {
|
|
127
|
-
hash: mainHash,
|
|
128
|
-
browserHash: mainHash,
|
|
129
|
-
optimized: {}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!force) {
|
|
133
|
-
let prevData: DepOptimizationMetadata | undefined
|
|
134
|
-
try {
|
|
135
|
-
prevData = JSON.parse(fs.readFileSync(dataPath, 'utf-8'))
|
|
136
|
-
} catch (e) {}
|
|
137
|
-
// hash is consistent, no need to re-bundle
|
|
138
|
-
if (prevData && prevData.hash === data.hash) {
|
|
139
|
-
log('Hash is consistent. Skipping. Use --force to override.')
|
|
140
|
-
return prevData
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (fs.existsSync(cacheDir)) {
|
|
145
|
-
emptyDir(cacheDir)
|
|
146
|
-
} else {
|
|
147
|
-
fs.mkdirSync(cacheDir, { recursive: true })
|
|
148
|
-
}
|
|
149
|
-
// a hint for Node.js
|
|
150
|
-
// all files in the cache directory should be recognized as ES modules
|
|
151
|
-
writeFile(
|
|
152
|
-
path.resolve(cacheDir, 'package.json'),
|
|
153
|
-
JSON.stringify({ type: 'module' })
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
let deps: Record<string, string>, missing: Record<string, string>
|
|
157
|
-
if (!newDeps) {
|
|
158
|
-
;({ deps, missing } = await scanImports(config))
|
|
159
|
-
} else {
|
|
160
|
-
deps = newDeps
|
|
161
|
-
missing = {}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// update browser hash
|
|
165
|
-
data.browserHash = createHash('sha256')
|
|
166
|
-
.update(data.hash + JSON.stringify(deps))
|
|
167
|
-
.digest('hex')
|
|
168
|
-
.substr(0, 8)
|
|
169
|
-
|
|
170
|
-
const missingIds = Object.keys(missing)
|
|
171
|
-
if (missingIds.length) {
|
|
172
|
-
throw new Error(
|
|
173
|
-
`The following dependencies are imported but could not be resolved:\n\n ${missingIds
|
|
174
|
-
.map(
|
|
175
|
-
(id) =>
|
|
176
|
-
`${chalk.cyan(id)} ${chalk.white.dim(
|
|
177
|
-
`(imported by ${missing[id]})`
|
|
178
|
-
)}`
|
|
179
|
-
)
|
|
180
|
-
.join(`\n `)}\n\nAre they installed?`
|
|
181
|
-
)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const include = config.optimizeDeps?.include
|
|
185
|
-
if (include) {
|
|
186
|
-
const resolve = config.createResolver({ asSrc: false })
|
|
187
|
-
for (const id of include) {
|
|
188
|
-
// normalize 'foo >bar` as 'foo > bar' to prevent same id being added
|
|
189
|
-
// and for pretty printing
|
|
190
|
-
const normalizedId = normalizeId(id)
|
|
191
|
-
if (!deps[normalizedId]) {
|
|
192
|
-
const entry = await resolve(id)
|
|
193
|
-
if (entry) {
|
|
194
|
-
deps[normalizedId] = entry
|
|
195
|
-
} else {
|
|
196
|
-
throw new Error(
|
|
197
|
-
`Failed to resolve force included dependency: ${chalk.cyan(id)}`
|
|
198
|
-
)
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const qualifiedIds = Object.keys(deps)
|
|
205
|
-
|
|
206
|
-
if (!qualifiedIds.length) {
|
|
207
|
-
writeFile(dataPath, JSON.stringify(data, null, 2))
|
|
208
|
-
log(`No dependencies to bundle. Skipping.\n\n\n`)
|
|
209
|
-
return data
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const total = qualifiedIds.length
|
|
213
|
-
const maxListed = 5
|
|
214
|
-
const listed = Math.min(total, maxListed)
|
|
215
|
-
const extra = Math.max(0, total - maxListed)
|
|
216
|
-
const depsString = chalk.yellow(
|
|
217
|
-
qualifiedIds.slice(0, listed).join(`\n `) +
|
|
218
|
-
(extra > 0 ? `\n (...and ${extra} more)` : ``)
|
|
219
|
-
)
|
|
220
|
-
if (!asCommand) {
|
|
221
|
-
if (!newDeps) {
|
|
222
|
-
// This is auto run on server start - let the user know that we are
|
|
223
|
-
// pre-optimizing deps
|
|
224
|
-
logger.info(
|
|
225
|
-
chalk.greenBright(`Pre-bundling dependencies:\n ${depsString}`)
|
|
226
|
-
)
|
|
227
|
-
logger.info(
|
|
228
|
-
`(this will be run only when your dependencies or config have changed)`
|
|
229
|
-
)
|
|
230
|
-
}
|
|
231
|
-
} else {
|
|
232
|
-
logger.info(chalk.greenBright(`Optimizing dependencies:\n ${depsString}`))
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// esbuild generates nested directory output with lowest common ancestor base
|
|
236
|
-
// this is unpredictable and makes it difficult to analyze entry / output
|
|
237
|
-
// mapping. So what we do here is:
|
|
238
|
-
// 1. flatten all ids to eliminate slash
|
|
239
|
-
// 2. in the plugin, read the entry ourselves as virtual files to retain the
|
|
240
|
-
// path.
|
|
241
|
-
const flatIdDeps: Record<string, string> = {}
|
|
242
|
-
const idToExports: Record<string, ExportsData> = {}
|
|
243
|
-
const flatIdToExports: Record<string, ExportsData> = {}
|
|
244
|
-
|
|
245
|
-
const { plugins = [], ...esbuildOptions } =
|
|
246
|
-
config.optimizeDeps?.esbuildOptions ?? {}
|
|
247
|
-
|
|
248
|
-
await init
|
|
249
|
-
for (const id in deps) {
|
|
250
|
-
const flatId = flattenId(id)
|
|
251
|
-
const filePath = (flatIdDeps[flatId] = deps[id])
|
|
252
|
-
const entryContent = fs.readFileSync(filePath, 'utf-8')
|
|
253
|
-
let exportsData: ExportsData
|
|
254
|
-
try {
|
|
255
|
-
exportsData = parse(entryContent) as ExportsData
|
|
256
|
-
} catch {
|
|
257
|
-
debug(
|
|
258
|
-
`Unable to parse dependency: ${id}. Trying again with a JSX transform.`
|
|
259
|
-
)
|
|
260
|
-
const transformed = await transformWithEsbuild(entryContent, filePath, {
|
|
261
|
-
loader: 'jsx'
|
|
262
|
-
})
|
|
263
|
-
// Ensure that optimization won't fail by defaulting '.js' to the JSX parser.
|
|
264
|
-
// This is useful for packages such as Gatsby.
|
|
265
|
-
esbuildOptions.loader = {
|
|
266
|
-
'.js': 'jsx',
|
|
267
|
-
...esbuildOptions.loader
|
|
268
|
-
}
|
|
269
|
-
exportsData = parse(transformed.code) as ExportsData
|
|
270
|
-
}
|
|
271
|
-
for (const { ss, se } of exportsData[0]) {
|
|
272
|
-
const exp = entryContent.slice(ss, se)
|
|
273
|
-
if (/export\s+\*\s+from/.test(exp)) {
|
|
274
|
-
exportsData.hasReExports = true
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
idToExports[id] = exportsData
|
|
278
|
-
flatIdToExports[flatId] = exportsData
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const define: Record<string, string> = {
|
|
282
|
-
'process.env.NODE_ENV': JSON.stringify(config.mode)
|
|
283
|
-
}
|
|
284
|
-
for (const key in config.define) {
|
|
285
|
-
const value = config.define[key]
|
|
286
|
-
define[key] = typeof value === 'string' ? value : JSON.stringify(value)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const start = Date.now()
|
|
290
|
-
|
|
291
|
-
const result = await build({
|
|
292
|
-
absWorkingDir: process.cwd(),
|
|
293
|
-
entryPoints: Object.keys(flatIdDeps),
|
|
294
|
-
bundle: true,
|
|
295
|
-
format: 'esm',
|
|
296
|
-
external: config.optimizeDeps?.exclude,
|
|
297
|
-
logLevel: 'error',
|
|
298
|
-
splitting: true,
|
|
299
|
-
sourcemap: true,
|
|
300
|
-
outdir: cacheDir,
|
|
301
|
-
treeShaking: 'ignore-annotations',
|
|
302
|
-
metafile: true,
|
|
303
|
-
define,
|
|
304
|
-
plugins: [
|
|
305
|
-
...plugins,
|
|
306
|
-
esbuildDepPlugin(flatIdDeps, flatIdToExports, config, ssr)
|
|
307
|
-
],
|
|
308
|
-
...esbuildOptions
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
const meta = result.metafile!
|
|
312
|
-
|
|
313
|
-
// the paths in `meta.outputs` are relative to `process.cwd()`
|
|
314
|
-
const cacheDirOutputPath = path.relative(process.cwd(), cacheDir)
|
|
315
|
-
|
|
316
|
-
for (const id in deps) {
|
|
317
|
-
const entry = deps[id]
|
|
318
|
-
data.optimized[id] = {
|
|
319
|
-
file: normalizePath(path.resolve(cacheDir, flattenId(id) + '.js')),
|
|
320
|
-
src: entry,
|
|
321
|
-
needsInterop: needsInterop(
|
|
322
|
-
id,
|
|
323
|
-
idToExports[id],
|
|
324
|
-
meta.outputs,
|
|
325
|
-
cacheDirOutputPath
|
|
326
|
-
)
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
writeFile(dataPath, JSON.stringify(data, null, 2))
|
|
331
|
-
|
|
332
|
-
debug(`deps bundled in ${Date.now() - start}ms`)
|
|
333
|
-
return data
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// https://github.com/vitejs/vite/issues/1724#issuecomment-767619642
|
|
337
|
-
// a list of modules that pretends to be ESM but still uses `require`.
|
|
338
|
-
// this causes esbuild to wrap them as CJS even when its entry appears to be ESM.
|
|
339
|
-
const KNOWN_INTEROP_IDS = new Set(['moment'])
|
|
340
|
-
|
|
341
|
-
function needsInterop(
|
|
342
|
-
id: string,
|
|
343
|
-
exportsData: ExportsData,
|
|
344
|
-
outputs: Record<string, any>,
|
|
345
|
-
cacheDirOutputPath: string
|
|
346
|
-
): boolean {
|
|
347
|
-
if (KNOWN_INTEROP_IDS.has(id)) {
|
|
348
|
-
return true
|
|
349
|
-
}
|
|
350
|
-
const [imports, exports] = exportsData
|
|
351
|
-
// entry has no ESM syntax - likely CJS or UMD
|
|
352
|
-
if (!exports.length && !imports.length) {
|
|
353
|
-
return true
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// if a peer dependency used require() on a ESM dependency, esbuild turns the
|
|
357
|
-
// ESM dependency's entry chunk into a single default export... detect
|
|
358
|
-
// such cases by checking exports mismatch, and force interop.
|
|
359
|
-
const flatId = flattenId(id) + '.js'
|
|
360
|
-
let generatedExports: string[] | undefined
|
|
361
|
-
for (const output in outputs) {
|
|
362
|
-
if (
|
|
363
|
-
normalizePath(output) ===
|
|
364
|
-
normalizePath(path.join(cacheDirOutputPath, flatId))
|
|
365
|
-
) {
|
|
366
|
-
generatedExports = outputs[output].exports
|
|
367
|
-
break
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (
|
|
372
|
-
!generatedExports ||
|
|
373
|
-
(isSingleDefaultExport(generatedExports) && !isSingleDefaultExport(exports))
|
|
374
|
-
) {
|
|
375
|
-
return true
|
|
376
|
-
}
|
|
377
|
-
return false
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function isSingleDefaultExport(exports: string[]) {
|
|
381
|
-
return exports.length === 1 && exports[0] === 'default'
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const lockfileFormats = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
|
|
385
|
-
|
|
386
|
-
function getDepHash(root: string, config: ResolvedConfig): string {
|
|
387
|
-
let content = lookupFile(root, lockfileFormats) || ''
|
|
388
|
-
// also take config into account
|
|
389
|
-
// only a subset of config options that can affect dep optimization
|
|
390
|
-
content += JSON.stringify(
|
|
391
|
-
{
|
|
392
|
-
mode: config.mode,
|
|
393
|
-
root: config.root,
|
|
394
|
-
resolve: config.resolve,
|
|
395
|
-
assetsInclude: config.assetsInclude,
|
|
396
|
-
plugins: config.plugins.map((p) => p.name),
|
|
397
|
-
optimizeDeps: {
|
|
398
|
-
include: config.optimizeDeps?.include,
|
|
399
|
-
exclude: config.optimizeDeps?.exclude
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
(_, value) => {
|
|
403
|
-
if (typeof value === 'function' || value instanceof RegExp) {
|
|
404
|
-
return value.toString()
|
|
405
|
-
}
|
|
406
|
-
return value
|
|
407
|
-
}
|
|
408
|
-
)
|
|
409
|
-
return createHash('sha256').update(content).digest('hex').substr(0, 8)
|
|
410
|
-
}
|