1
- import { createRequire } from 'node:module'
2
1
import inject from '@rollup/plugin-inject'
2
+ import browserResolve from 'browser-resolve'
3
3
import stdLibBrowser from 'node-stdlib-browser'
4
4
import { handleCircularDependancyWarning } from 'node-stdlib-browser/helpers/rollup/plugin'
5
5
import esbuildPlugin from 'node-stdlib-browser/helpers/esbuild/plugin'
6
6
import type { Plugin } from 'vite'
7
- import { compareModuleNames , isEnabled , isNodeProtocolImport , toRegExp , withoutNodeProtocol } from './utils'
7
+ import { compareModuleNames , isEnabled , isNodeProtocolImport , resolvePolyfill , toEntries , toRegExp , withoutNodeProtocol } from './utils'
8
8
9
- export type BuildTarget = 'build' | 'dev'
9
+ export type BareModuleName < T = ModuleName > = T extends `node:${infer P } ` ? P : never
10
+ export type BareModuleNameWithSubpath < T = ModuleName > = T extends `node:${infer P } ` ? `${P } /${string } ` : never
10
11
export type BooleanOrBuildTarget = boolean | BuildTarget
12
+ export type BuildTarget = 'build' | 'dev'
11
13
export type ModuleName = keyof typeof stdLibBrowser
12
- export type ModuleNameWithoutNodePrefix < T = ModuleName > = T extends `node:${infer P } ` ? P : never
14
+ export type OverrideOptions = {
15
+
16
+ }
13
17
14
18
export type PolyfillOptions = {
15
19
/**
@@ -22,7 +26,7 @@ export type PolyfillOptions = {
22
26
* })
23
27
* ```
24
28
*/
25
- include ?: ModuleNameWithoutNodePrefix [ ] ,
29
+ include ?: BareModuleName [ ] ,
26
30
/**
27
31
* @example
28
32
*
@@ -32,7 +36,7 @@ export type PolyfillOptions = {
32
36
* })
33
37
* ```
34
38
*/
35
- exclude ?: ModuleNameWithoutNodePrefix [ ] ,
39
+ exclude ?: BareModuleName [ ] ,
36
40
/**
37
41
* Specify whether specific globals should be polyfilled.
38
42
*
@@ -66,7 +70,7 @@ export type PolyfillOptions = {
66
70
* })
67
71
* ```
68
72
*/
69
- overrides ?: { [ Key in ModuleNameWithoutNodePrefix ] ?: string } ,
73
+ overrides ?: { [ Key in BareModuleName | BareModuleNameWithSubpath ] ?: string } ,
70
74
/**
71
75
* Specify whether the Node protocol version of an import (e.g. `node:buffer`) should be polyfilled too.
72
76
*
@@ -76,14 +80,14 @@ export type PolyfillOptions = {
76
80
}
77
81
78
82
export type PolyfillOptionsResolved = {
79
- include : ModuleNameWithoutNodePrefix [ ] ,
80
- exclude : ModuleNameWithoutNodePrefix [ ] ,
83
+ include : BareModuleName [ ] ,
84
+ exclude : BareModuleName [ ] ,
81
85
globals : {
82
86
Buffer : BooleanOrBuildTarget ,
83
87
global : BooleanOrBuildTarget ,
84
88
process : BooleanOrBuildTarget ,
85
89
} ,
86
- overrides : { [ Key in ModuleNameWithoutNodePrefix ] ?: string } ,
90
+ overrides : { [ Key in BareModuleName | BareModuleNameWithSubpath ] ?: string } ,
87
91
protocolImports : boolean ,
88
92
}
89
93
@@ -127,11 +131,10 @@ const globalShimsBanner = [
127
131
* ```
128
132
*/
129
133
export const nodePolyfills = ( options : PolyfillOptions = { } ) : Plugin => {
130
- const require = createRequire ( import . meta. url )
131
134
const globalShimPaths = [
132
- require . resolve ( 'vite-plugin-node-polyfills/shims/buffer' ) ,
133
- require . resolve ( 'vite-plugin-node-polyfills/shims/global' ) ,
134
- require . resolve ( 'vite-plugin-node-polyfills/shims/process' ) ,
135
+ 'vite-plugin-node-polyfills/shims/buffer' ,
136
+ 'vite-plugin-node-polyfills/shims/global' ,
137
+ 'vite-plugin-node-polyfills/shims/process' ,
135
138
]
136
139
const optionsResolved : PolyfillOptionsResolved = {
137
140
include : [ ] ,
@@ -155,16 +158,16 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
155
158
return optionsResolved . exclude . some ( ( excludedName ) => compareModuleNames ( moduleName , excludedName ) )
156
159
}
157
160
158
- const toOverride = ( name : ModuleNameWithoutNodePrefix ) : string | void => {
159
- if ( isEnabled ( optionsResolved . globals . Buffer , 'dev' ) && / ^ b u f f e r $ / . test ( name ) ) {
161
+ const toOverride = ( name : BareModuleName ) : string | void => {
162
+ if ( / ^ b u f f e r $ / . test ( name ) ) {
160
163
return 'vite-plugin-node-polyfills/shims/buffer'
161
164
}
162
165
163
- if ( isEnabled ( optionsResolved . globals . global , 'dev' ) && / ^ g l o b a l $ / . test ( name ) ) {
166
+ if ( / ^ g l o b a l $ / . test ( name ) ) {
164
167
return 'vite-plugin-node-polyfills/shims/global'
165
168
}
166
169
167
- if ( isEnabled ( optionsResolved . globals . process , 'dev' ) && / ^ p r o c e s s $ / . test ( name ) ) {
170
+ if ( / ^ p r o c e s s $ / . test ( name ) ) {
168
171
return 'vite-plugin-node-polyfills/shims/process'
169
172
}
170
173
@@ -189,6 +192,7 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
189
192
190
193
return {
191
194
name : 'vite-plugin-node-polyfills' ,
195
+ enforce : 'pre' ,
192
196
config : ( config , env ) => {
193
197
const isDev = env . command === 'serve'
194
198
@@ -236,21 +240,25 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
236
240
...globalShimPaths ,
237
241
] ,
238
242
plugins : [
239
- esbuildPlugin ( polyfills ) ,
243
+ esbuildPlugin ( {
244
+ ...polyfills ,
245
+ } ) ,
240
246
// Supress the 'injected path "..." cannot be marked as external' error in Vite 4 (emitted by esbuild).
241
247
// https://github.com/evanw/esbuild/blob/edede3c49ad6adddc6ea5b3c78c6ea7507e03020/internal/bundler/bundler.go#L1469
242
248
{
243
249
name : 'vite-plugin-node-polyfills-shims-resolver' ,
244
- setup ( build ) {
250
+ setup : ( build ) => {
245
251
for ( const globalShimPath of globalShimPaths ) {
246
252
const globalShimsFilter = toRegExp ( globalShimPath )
247
253
248
254
// https://esbuild.github.io/plugins/#on-resolve
249
255
build . onResolve ( { filter : globalShimsFilter } , ( ) => {
256
+ const resolved = browserResolve . sync ( globalShimPath )
257
+
250
258
return {
251
259
// https://github.com/evanw/esbuild/blob/edede3c49ad6adddc6ea5b3c78c6ea7507e03020/internal/bundler/bundler.go#L1468
252
260
external : false ,
253
- path : globalShimPath ,
261
+ path : resolved ,
254
262
}
255
263
} )
256
264
}
@@ -267,5 +275,28 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
267
275
} ,
268
276
}
269
277
} ,
278
+ async resolveId ( id ) {
279
+ for ( const [ moduleName , modulePath ] of toEntries ( polyfills ) ) {
280
+ if ( id . startsWith ( modulePath ) ) {
281
+ // Grab the subpath without the forward slash. E.g. `path/posix` -> `posix`
282
+ const moduleSubpath = id . slice ( modulePath . length + 1 )
283
+
284
+ if ( moduleSubpath . length > 0 ) {
285
+ const moduleNameWithoutProtocol = withoutNodeProtocol ( moduleName )
286
+ const overrideName = `${ moduleNameWithoutProtocol } /${ moduleSubpath } ` as const
287
+ const override = optionsResolved . overrides [ overrideName ]
288
+
289
+ if ( ! override ) {
290
+ // Todo: Maybe throw error?
291
+ return undefined
292
+ }
293
+
294
+ return await resolvePolyfill ( this , override )
295
+ }
296
+
297
+ return browserResolve . sync ( modulePath )
298
+ }
299
+ }
300
+ } ,
270
301
}
271
302
}
0 commit comments