-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
/
preAlias.ts
127 lines (122 loc) · 3.93 KB
/
preAlias.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import fs from 'node:fs'
import path from 'node:path'
import type {
Alias,
AliasOptions,
DepOptimizationOptions,
ResolvedConfig,
} from '..'
import type { Plugin } from '../plugin'
import { createIsConfiguredAsSsrExternal } from '../ssr/ssrExternal'
import {
bareImportRE,
cleanUrl,
isInNodeModules,
isOptimizable,
moduleListContains,
} from '../utils'
import { getDepsOptimizer } from '../optimizer'
import { tryOptimizedResolve } from './resolve'
/**
* A plugin to avoid an aliased AND optimized dep from being aliased in src
*/
export function preAliasPlugin(config: ResolvedConfig): Plugin {
const findPatterns = getAliasPatterns(config.resolve.alias)
const isConfiguredAsExternal = createIsConfiguredAsSsrExternal(config)
const isBuild = config.command === 'build'
return {
name: 'vite:pre-alias',
async resolveId(id, importer, options) {
const ssr = options?.ssr === true
const depsOptimizer = getDepsOptimizer(config, ssr)
if (
importer &&
depsOptimizer &&
bareImportRE.test(id) &&
!options?.scan &&
id !== '@vite/client' &&
id !== '@vite/env'
) {
if (findPatterns.find((pattern) => matches(pattern, id))) {
const optimizedId = await tryOptimizedResolve(
depsOptimizer,
id,
importer,
config.resolve.preserveSymlinks,
config.packageCache,
)
if (optimizedId) {
return optimizedId // aliased dep already optimized
}
const resolved = await this.resolve(id, importer, {
skipSelf: true,
...options,
})
if (resolved && !depsOptimizer.isOptimizedDepFile(resolved.id)) {
const optimizeDeps = depsOptimizer.options
const resolvedId = cleanUrl(resolved.id)
const isVirtual = resolvedId === id || resolvedId.includes('\0')
if (
!isVirtual &&
fs.existsSync(resolvedId) &&
!moduleListContains(optimizeDeps.exclude, id) &&
path.isAbsolute(resolvedId) &&
(isInNodeModules(resolvedId) ||
optimizeDeps.include?.includes(id)) &&
isOptimizable(resolvedId, optimizeDeps) &&
!(isBuild && ssr && isConfiguredAsExternal(id)) &&
(!ssr || optimizeAliasReplacementForSSR(resolvedId, optimizeDeps))
) {
// aliased dep has not yet been optimized
const optimizedInfo = depsOptimizer!.registerMissingImport(
id,
resolvedId,
)
return { id: depsOptimizer!.getOptimizedDepId(optimizedInfo) }
}
}
return resolved
}
}
},
}
}
function optimizeAliasReplacementForSSR(
id: string,
optimizeDeps: DepOptimizationOptions,
) {
if (optimizeDeps.include?.includes(id)) {
return true
}
// In the regular resolution, the default for non-external modules is to
// be optimized if they are CJS. Here, we don't have the package id but
// only the replacement file path. We could find the package.json from
// the id and respect the same default in the future.
// Default to not optimize an aliased replacement for now, forcing the
// user to explicitly add it to the ssr.optimizeDeps.include list.
return false
}
// In sync with rollup plugin alias logic
function matches(pattern: string | RegExp, importee: string) {
if (pattern instanceof RegExp) {
return pattern.test(importee)
}
if (importee.length < pattern.length) {
return false
}
if (importee === pattern) {
return true
}
return importee.startsWith(pattern + '/')
}
function getAliasPatterns(
entries: (AliasOptions | undefined) & Alias[],
): (string | RegExp)[] {
if (!entries) {
return []
}
if (Array.isArray(entries)) {
return entries.map((entry) => entry.find)
}
return Object.entries(entries).map(([find]) => find)
}