@@ -6,22 +6,23 @@ import {
66 type Plugin as EsbuildPlugin ,
77} from 'esbuild'
88import libEsm from 'lib-esm'
9- import { COLOURS , node_modules as find_node_modules } from 'vite-plugin-utils/function'
9+ import { node_modules as find_node_modules } from 'vite-plugin-utils/function'
1010import { electronBuiltins , ensureDir } from './utils'
1111
1212const cjs_require = createRequire ( import . meta. url )
13- const preBundleCjs = 'pre-bundle -cjs'
14- const preBundleEsm = 'pre-bundle-esm'
13+ const electronNpmCjsNamespace = 'electron:npm -cjs'
14+ const bareImport = / ^ [ \w @ ] . * /
1515const CACHE_DIR = '.vite-electron-renderer'
1616let node_modules_path : string
1717let cache_dir : string
1818
1919export interface optimizerOptions {
20- buildOptions ?: import ( 'esbuild' ) . BuildOptions
2120 /**
22- * Explicitly tell the Pre-Bundling how to work, when value is `false` Vite's default Pre-Bundling will be used.
21+ * Explicitly tell the Pre-Bundling how to work.
22+ *
23+ * - `false` Vite's default Pre-Bundling will be used.
2324 */
24- modules ?: { [ module : string ] : 'commonjs' | 'module' | false }
25+ resolve ?: ( args : import ( 'esbuild' ) . OnResolveArgs ) => 'commonjs' | ' module' | false | null | undefined | Promise < 'commonjs' | 'module' | false | null | undefined >
2526}
2627
2728export default function optimizer ( options : optimizerOptions , nodeIntegration : boolean ) : VitePlugin {
@@ -33,6 +34,7 @@ export default function optimizer(options: optimizerOptions, nodeIntegration: bo
3334
3435 config . optimizeDeps ??= { }
3536 config . optimizeDeps . esbuildOptions ??= { }
37+ config . optimizeDeps . esbuildOptions . platform ??= 'node'
3638 config . optimizeDeps . esbuildOptions . plugins ??= [ ]
3739 config . optimizeDeps . esbuildOptions . plugins . push ( esbuildPlugin ( options ) )
3840
@@ -66,74 +68,78 @@ export default function optimizer(options: optimizerOptions, nodeIntegration: bo
6668}
6769
6870export function esbuildPlugin ( options : optimizerOptions ) : EsbuildPlugin {
69- const { buildOptions , modules = { } } = options
71+ const { resolve } = options
7072
7173 return {
7274 name : 'vite-plugin-target:optimizer:esbuild' ,
7375 setup ( build ) {
74- build . onResolve ( {
75- filter : / ^ [ \w @ ] / , // bare import
76- } , async ( { path : id } ) => {
76+ // https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L277-L279
77+ const escape = ( text : string ) =>
78+ `^${ text . replace ( / [ - / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' ) } $`
79+ const filter = new RegExp ( electronBuiltins . map ( escape ) . join ( '|' ) )
80+
81+ // Electron builtin modules
82+ build . onResolve ( { filter } , args => {
83+ return {
84+ path : args . path ,
85+ external : true ,
86+ }
87+ } )
88+
89+ // Third party npm-pkg
90+ build . onResolve ( { filter : bareImport } , async args => {
91+ const {
92+ path : id ,
93+ namespace,
94+ importer,
95+ } = args
7796 if ( electronBuiltins . includes ( id ) ) {
78- // Builtin modules handled in 'build-config'
97+ // Builtin modules handled in './ build-config.ts '
7998 return
8099 }
81-
82- const userType = modules [ id ]
83- if ( userType === false ) {
84- // Use Vite's default Pre-Bundling
100+ if ( importer . includes ( 'node_modules' ) ) {
101+ return
102+ }
103+ if ( id . startsWith ( 'vite-' ) || namespace . startsWith ( 'vite:' ) ) {
104+ // https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L15-L20
85105 return
86- } else if ( userType === 'commonjs' ) {
87- return {
88- path : id ,
89- namespace : preBundleCjs ,
90- }
91- } else if ( userType === 'module' ) {
92- return {
93- path : id ,
94- namespace : preBundleEsm ,
95- }
96106 }
97107
98108 // ---- Try to detect what type a module is ----
99-
100- let isCjsModule ! : boolean
101- // Assume a bare module
109+ let moduleType : 'commonjs' | 'module' | undefined
102110 const packageJson = path . join ( node_modules_path , id , 'package.json' )
103- // Assume a dirname or filename -> e.g. `foo/bar` or `foo/bar/index.js` 🤔
104- const modulePath = path . join ( node_modules_path , id )
105-
106111 if ( fs . existsSync ( packageJson ) ) {
107- const pkg = cjs_require ( packageJson )
108- if ( pkg . type !== 'module' ) {
109- isCjsModule = true
110- }
111- } else {
112- try {
113- const filename = cjs_require . resolve ( modulePath )
114- if ( path . extname ( filename ) !== '.mjs' ) {
115- isCjsModule = true
116- }
117- } catch ( error ) {
118- console . log ( COLOURS . red ( 'Can not resolve path:' ) , modulePath )
119- }
112+ moduleType = cjs_require ( packageJson ) . type === 'module' ? 'module' : 'commonjs'
120113 }
121114
122- return {
123- path : id ,
124- namespace : isCjsModule ? preBundleCjs : preBundleEsm ,
115+ const userType = await resolve ?.( args )
116+ if ( userType === false ) {
117+ // Use Vite's default Pre-Bundling
118+ return
119+ }
120+ if ( userType === 'commonjs' || userType === 'module' ) {
121+ moduleType = userType
122+ }
123+
124+ // Only `cjs` modules, especially C/C++ npm-pkg, `es` modules will be use Vite's default Pre-Bundling
125+ if ( moduleType === 'commonjs' ) {
126+ return {
127+ path : id ,
128+ namespace : electronNpmCjsNamespace ,
129+ }
125130 }
126131 } )
127132
128133 build . onLoad ( {
129134 filter : / .* / ,
130- namespace : preBundleCjs ,
135+ namespace : electronNpmCjsNamespace ,
131136 } , async ( { path : id } ) => {
132137 const { exports } = libEsm ( { exports : Object . getOwnPropertyNames ( cjs_require ( id ) ) } )
133138
134139 return {
135140 contents : `
136141// Use "__cjs_require" avoid esbuild parse "require"
142+ // TODO: better implements
137143const __cjs_require = require;
138144
139145// If a module is a CommonJs, use the "require" loading it can bring better performance.
@@ -143,27 +149,6 @@ ${exports}
143149 ` . trim ( ) ,
144150 }
145151 } )
146-
147- build . onLoad ( {
148- filter : / .* / ,
149- namespace : preBundleEsm ,
150- } , async ( { path : id } ) => {
151- const outfile = path . join ( cache_dir , id , 'index.js' )
152- ensureDir ( path . dirname ( outfile ) )
153-
154- await build . esbuild . build ( {
155- entryPoints : [ id ] ,
156- outfile,
157- format : 'esm' ,
158- target : 'node14' ,
159- bundle : true ,
160- metafile : true ,
161- external : electronBuiltins ,
162- ...buildOptions ,
163- } )
164-
165- return { contents : fs . readFileSync ( outfile , 'utf8' ) }
166- } )
167152 } ,
168153 }
169154}
0 commit comments