@@ -19,15 +19,18 @@ const PromiseQueue = require('./utils/PromiseQueue');
1919const installPackage = require ( './utils/installPackage' ) ;
2020const bundleReport = require ( './utils/bundleReport' ) ;
2121const prettifyTime = require ( './utils/prettifyTime' ) ;
22+ const getRootDir = require ( './utils/getRootDir' ) ;
23+ const glob = require ( 'glob' ) ;
2224
2325/**
2426 * The Bundler is the main entry point. It resolves and loads assets,
2527 * creates the bundle tree, and manages the worker farm, cache, and file watcher.
2628 */
2729class Bundler extends EventEmitter {
28- constructor ( main , options = { } ) {
30+ constructor ( entryFiles , options = { } ) {
2931 super ( ) ;
30- this . mainFile = Path . resolve ( main || '' ) ;
32+
33+ this . entryFiles = this . normalizeEntries ( entryFiles ) ;
3134 this . options = this . normalizeOptions ( options ) ;
3235
3336 this . resolver = new Resolver ( this . options ) ;
@@ -64,6 +67,23 @@ class Bundler extends EventEmitter {
6467 logger . setOptions ( this . options ) ;
6568 }
6669
70+ normalizeEntries ( entryFiles ) {
71+ // Support passing a single file
72+ if ( entryFiles && ! Array . isArray ( entryFiles ) ) {
73+ entryFiles = [ entryFiles ] ;
74+ }
75+
76+ // If no entry files provided, resolve the entry point from the current directory.
77+ if ( ! entryFiles || entryFiles . length === 0 ) {
78+ entryFiles = [ process . cwd ( ) ] ;
79+ }
80+
81+ // Match files as globs
82+ return entryFiles
83+ . reduce ( ( p , m ) => p . concat ( glob . sync ( m , { nonull : true } ) ) , [ ] )
84+ . map ( f => Path . resolve ( f ) ) ;
85+ }
86+
6787 normalizeOptions ( options ) {
6888 const isProduction =
6989 options . production || process . env . NODE_ENV === 'production' ;
@@ -90,9 +110,9 @@ class Bundler extends EventEmitter {
90110 : typeof options . hmr === 'boolean' ? options . hmr : watch ,
91111 https : options . https || false ,
92112 logLevel : isNaN ( options . logLevel ) ? 3 : options . logLevel ,
93- mainFile : this . mainFile ,
113+ entryFiles : this . entryFiles ,
94114 hmrPort : options . hmrPort || 0 ,
95- rootDir : Path . dirname ( this . mainFile ) ,
115+ rootDir : getRootDir ( this . entryFiles ) ,
96116 sourceMaps :
97117 typeof options . sourceMaps === 'boolean' ? options . sourceMaps : true ,
98118 hmrHostname :
@@ -156,7 +176,8 @@ class Bundler extends EventEmitter {
156176 }
157177
158178 async loadPlugins ( ) {
159- let pkg = await config . load ( this . mainFile , [ 'package.json' ] ) ;
179+ let relative = Path . join ( this . options . rootDir , 'index' ) ;
180+ let pkg = await config . load ( relative , [ 'package.json' ] ) ;
160181 if ( ! pkg ) {
161182 return ;
162183 }
@@ -166,7 +187,7 @@ class Bundler extends EventEmitter {
166187 for ( let dep in deps ) {
167188 const pattern = / ^ ( @ .* \/ ) ? p a r c e l - p l u g i n - .+ / ;
168189 if ( pattern . test ( dep ) ) {
169- let plugin = await localRequire ( dep , this . mainFile ) ;
190+ let plugin = await localRequire ( dep , relative ) ;
170191 await plugin ( this ) ;
171192 }
172193 }
@@ -185,7 +206,7 @@ class Bundler extends EventEmitter {
185206 } ) ;
186207 }
187208
188- let isInitialBundle = ! this . mainAsset ;
209+ let isInitialBundle = ! this . entryAssets ;
189210 let startTime = Date . now ( ) ;
190211 this . pending = true ;
191212 this . errored = false ;
@@ -201,8 +222,12 @@ class Bundler extends EventEmitter {
201222 if ( isInitialBundle ) {
202223 await fs . mkdirp ( this . options . outDir ) ;
203224
204- this . mainAsset = await this . resolveAsset ( this . mainFile ) ;
205- this . buildQueue . add ( this . mainAsset ) ;
225+ this . entryAssets = new Set ( ) ;
226+ for ( let entry of this . entryFiles ) {
227+ let asset = await this . resolveAsset ( entry ) ;
228+ this . buildQueue . add ( asset ) ;
229+ this . entryAssets . add ( asset ) ;
230+ }
206231 }
207232
208233 // Build the queued assets.
@@ -217,8 +242,16 @@ class Bundler extends EventEmitter {
217242 asset . invalidateBundle ( ) ;
218243 }
219244
220- // Create a new bundle tree
221- this . mainBundle = this . createBundleTree ( this . mainAsset ) ;
245+ // Create a root bundle to hold all of the entry assets, and add them to the tree.
246+ this . mainBundle = new Bundle ( ) ;
247+ for ( let asset of this . entryAssets ) {
248+ this . createBundleTree ( asset , this . mainBundle ) ;
249+ }
250+
251+ // If there is only one child bundle, replace the root with that bundle.
252+ if ( this . mainBundle . childBundles . size === 1 ) {
253+ this . mainBundle = Array . from ( this . mainBundle . childBundles ) [ 0 ] ;
254+ }
222255
223256 // Generate the final bundle names, and replace references in the built assets.
224257 this . bundleNameMap = this . mainBundle . getBundleNameMap (
@@ -281,7 +314,7 @@ class Bundler extends EventEmitter {
281314 }
282315
283316 await this . loadPlugins ( ) ;
284- await loadEnv ( this . mainFile ) ;
317+ await loadEnv ( Path . join ( this . options . rootDir , 'index' ) ) ;
285318
286319 this . options . extensions = Object . assign ( { } , this . parser . extensions ) ;
287320 this . options . bundleLoaders = this . bundleLoaders ;
@@ -508,7 +541,7 @@ class Bundler extends EventEmitter {
508541 } ) ;
509542 }
510543
511- createBundleTree ( asset , dep , bundle , parentBundles = new Set ( ) ) {
544+ createBundleTree ( asset , bundle , dep , parentBundles = new Set ( ) ) {
512545 if ( dep ) {
513546 asset . parentDeps . add ( dep ) ;
514547 }
@@ -534,13 +567,23 @@ class Bundler extends EventEmitter {
534567 }
535568 }
536569
537- if ( ! bundle ) {
538- // Create the root bundle if it doesn't exist
539- bundle = Bundle . createWithAsset ( asset ) ;
540- } else if ( dep && dep . dynamic ) {
570+ let isEntryAsset =
571+ asset . parentBundle && asset . parentBundle . entryAsset === asset ;
572+
573+ if ( ( dep && dep . dynamic ) || ! bundle . type ) {
574+ // If the asset is already the entry asset of a bundle, don't create a duplicate.
575+ if ( isEntryAsset ) {
576+ return ;
577+ }
578+
541579 // Create a new bundle for dynamic imports
542580 bundle = bundle . createChildBundle ( asset ) ;
543581 } else if ( asset . type && ! this . packagers . has ( asset . type ) ) {
582+ // If the asset is already the entry asset of a bundle, don't create a duplicate.
583+ if ( isEntryAsset ) {
584+ return ;
585+ }
586+
544587 // No packager is available for this asset type. Create a new bundle with only this asset.
545588 bundle . createSiblingBundle ( asset ) ;
546589 } else {
@@ -566,7 +609,7 @@ class Bundler extends EventEmitter {
566609 parentBundles . add ( bundle ) ;
567610
568611 for ( let [ dep , assetDep ] of asset . depAssets ) {
569- this . createBundleTree ( assetDep , dep , bundle , parentBundles ) ;
612+ this . createBundleTree ( assetDep , bundle , dep , parentBundles ) ;
570613 }
571614
572615 parentBundles . delete ( bundle ) ;
0 commit comments