@@ -153,20 +153,25 @@ function findExternalOrigin(issuer) {
153153}
154154
155155function getExternalModules ( stats ) {
156+ if ( ! stats . compilation . chunks ) {
157+ return [ ] ;
158+ }
156159 const externals = new Set ( ) ;
160+ for ( const chunk of stats . compilation . chunks ) {
161+ if ( ! chunk . modulesIterable ) {
162+ continue ;
163+ }
157164
158- _ . forEach ( stats . compilation . chunks , chunk => {
159165 // Explore each module within the chunk (built inputs):
160- chunk . forEachModule ( module => {
166+ for ( const module of chunk . modulesIterable ) {
161167 if ( isExternalModule ( module ) ) {
162168 externals . add ( {
163169 origin : _ . get ( findExternalOrigin ( module . issuer ) , 'rawRequest' ) ,
164170 external : getExternalModuleName ( module )
165171 } ) ;
166172 }
167- } ) ;
168- } ) ;
169-
173+ }
174+ }
170175 return Array . from ( externals ) ;
171176}
172177
@@ -206,146 +211,146 @@ module.exports = {
206211
207212 // Determine and create packager
208213 return BbPromise . try ( ( ) => Packagers . get . call ( this , this . configuration . packager ) )
209- . then ( packager => {
210- // Fetch needed original package.json sections
211- const sectionNames = packager . copyPackageSectionNames ;
212- const packageJson = this . serverless . utils . readFileSync ( packageJsonPath ) ;
213- const packageSections = _ . pick ( packageJson , sectionNames ) ;
214- if ( ! _ . isEmpty ( packageSections ) ) {
215- this . options . verbose && this . serverless . cli . log ( `Using package.json sections ${ _ . join ( _ . keys ( packageSections ) , ', ' ) } ` ) ;
216- }
214+ . then ( packager => {
215+ // Fetch needed original package.json sections
216+ const sectionNames = packager . copyPackageSectionNames ;
217+ const packageJson = this . serverless . utils . readFileSync ( packageJsonPath ) ;
218+ const packageSections = _ . pick ( packageJson , sectionNames ) ;
219+ if ( ! _ . isEmpty ( packageSections ) ) {
220+ this . options . verbose && this . serverless . cli . log ( `Using package.json sections ${ _ . join ( _ . keys ( packageSections ) , ', ' ) } ` ) ;
221+ }
217222
218- // Get first level dependency graph
219- this . options . verbose && this . serverless . cli . log ( `Fetch dependency graph from ${ packageJsonPath } ` ) ;
223+ // Get first level dependency graph
224+ this . options . verbose && this . serverless . cli . log ( `Fetch dependency graph from ${ packageJsonPath } ` ) ;
220225
221- return packager . getProdDependencies ( path . dirname ( packageJsonPath ) , 1 )
222- . then ( dependencyGraph => {
223- const problems = _ . get ( dependencyGraph , 'problems' , [ ] ) ;
224- if ( this . options . verbose && ! _ . isEmpty ( problems ) ) {
225- this . serverless . cli . log ( `Ignoring ${ _ . size ( problems ) } NPM errors:` ) ;
226- _ . forEach ( problems , problem => {
227- this . serverless . cli . log ( `=> ${ problem } ` ) ;
228- } ) ;
229- }
230-
231- // (1) Generate dependency composition
232- const compositeModules = _ . uniq ( _ . flatMap ( stats . stats , compileStats => {
233- const externalModules = _ . concat (
234- getExternalModules . call ( this , compileStats ) ,
235- _ . map ( packageForceIncludes , whitelistedPackage => ( { external : whitelistedPackage } ) )
236- ) ;
237- return getProdModules . call ( this , externalModules , packagePath , dependencyGraph , packageForceExcludes ) ;
238- } ) ) ;
239- removeExcludedModules . call ( this , compositeModules , packageForceExcludes , true ) ;
240-
241- if ( _ . isEmpty ( compositeModules ) ) {
242- // The compiled code does not reference any external modules at all
243- this . serverless . cli . log ( 'No external modules needed' ) ;
244- return BbPromise . resolve ( ) ;
245- }
246-
247- // (1.a) Install all needed modules
248- const compositeModulePath = path . join ( this . webpackOutputPath , 'dependencies' ) ;
249- const compositePackageJson = path . join ( compositeModulePath , 'package.json' ) ;
250-
251- // (1.a.1) Create a package.json
252- const compositePackage = _ . defaults ( {
253- name : this . serverless . service . service ,
254- version : '1.0.0' ,
255- description : `Packaged externals for ${ this . serverless . service . service } ` ,
256- private : true ,
257- scripts : packageScripts
258- } , packageSections ) ;
259- const relPath = path . relative ( compositeModulePath , path . dirname ( packageJsonPath ) ) ;
260- addModulesToPackageJson ( compositeModules , compositePackage , relPath ) ;
261- this . serverless . utils . writeFileSync ( compositePackageJson , JSON . stringify ( compositePackage , null , 2 ) ) ;
262-
263- // (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
264- const packageLockPath = path . join ( path . dirname ( packageJsonPath ) , packager . lockfileName ) ;
265- let hasPackageLock = false ;
266- return BbPromise . fromCallback ( cb => fse . pathExists ( packageLockPath , cb ) )
267- . then ( exists => {
268- if ( exists ) {
269- this . serverless . cli . log ( 'Package lock found - Using locked versions' ) ;
270- try {
271- let packageLockFile = this . serverless . utils . readFileSync ( packageLockPath ) ;
272- packageLockFile = packager . rebaseLockfile ( relPath , packageLockFile ) ;
273- if ( _ . isObject ( packageLockFile ) ) {
274- packageLockFile = JSON . stringify ( packageLockFile , null , 2 ) ;
275- }
276-
277- this . serverless . utils . writeFileSync ( path . join ( compositeModulePath , packager . lockfileName ) , packageLockFile ) ;
278- hasPackageLock = true ;
279- } catch ( err ) {
280- this . serverless . cli . log ( `Warning: Could not read lock file: ${ err . message } ` ) ;
226+ return packager . getProdDependencies ( path . dirname ( packageJsonPath ) , 1 )
227+ . then ( dependencyGraph => {
228+ const problems = _ . get ( dependencyGraph , 'problems' , [ ] ) ;
229+ if ( this . options . verbose && ! _ . isEmpty ( problems ) ) {
230+ this . serverless . cli . log ( `Ignoring ${ _ . size ( problems ) } NPM errors:` ) ;
231+ _ . forEach ( problems , problem => {
232+ this . serverless . cli . log ( `=> ${ problem } ` ) ;
233+ } ) ;
281234 }
282- }
283- return BbPromise . resolve ( ) ;
284- } )
285- . then ( ( ) => {
286- const start = _ . now ( ) ;
287- this . serverless . cli . log ( 'Packing external modules: ' + compositeModules . join ( ', ' ) ) ;
288- return packager . install ( compositeModulePath , this . configuration . packagerOptions )
289- . then ( ( ) => this . options . verbose && this . serverless . cli . log ( `Package took [${ _ . now ( ) - start } ms]` ) )
290- . return ( stats . stats ) ;
291- } )
292- . mapSeries ( compileStats => {
293- const modulePath = compileStats . compilation . compiler . outputPath ;
294-
295- // Create package.json
296- const modulePackageJson = path . join ( modulePath , 'package.json' ) ;
297- const modulePackage = _ . defaults ( {
298- name : this . serverless . service . service ,
299- version : '1.0.0' ,
300- description : `Packaged externals for ${ this . serverless . service . service } ` ,
301- private : true ,
302- scripts : packageScripts ,
303- dependencies : { }
304- } , packageSections ) ;
305- const prodModules = getProdModules . call ( this ,
306- _ . concat (
307- getExternalModules . call ( this , compileStats ) ,
308- _ . map ( packageForceIncludes , whitelistedPackage => ( { external : whitelistedPackage } ) )
309- ) , packagePath , dependencyGraph , packageForceExcludes ) ;
310- removeExcludedModules . call ( this , prodModules , packageForceExcludes ) ;
311- const relPath = path . relative ( modulePath , path . dirname ( packageJsonPath ) ) ;
312- addModulesToPackageJson ( prodModules , modulePackage , relPath ) ;
313- this . serverless . utils . writeFileSync ( modulePackageJson , JSON . stringify ( modulePackage , null , 2 ) ) ;
314-
315- // GOOGLE: Copy modules only if not google-cloud-functions
316- // GCF Auto installs the package json
317- if ( _ . get ( this . serverless , 'service.provider.name' ) === 'google' ) {
318- return BbPromise . resolve ( ) ;
319- }
320-
321- const startCopy = _ . now ( ) ;
322- return BbPromise . try ( ( ) => {
323- // Only copy dependency modules if demanded by packager
324- if ( packager . mustCopyModules ) {
325- return BbPromise . fromCallback ( callback => fse . copy ( path . join ( compositeModulePath , 'node_modules' ) , path . join ( modulePath , 'node_modules' ) , callback ) ) ;
235+
236+ // (1) Generate dependency composition
237+ const compositeModules = _ . uniq ( _ . flatMap ( stats . stats , compileStats => {
238+ const externalModules = _ . concat (
239+ getExternalModules . call ( this , compileStats ) ,
240+ _ . map ( packageForceIncludes , whitelistedPackage => ( { external : whitelistedPackage } ) )
241+ ) ;
242+ return getProdModules . call ( this , externalModules , packagePath , dependencyGraph , packageForceExcludes ) ;
243+ } ) ) ;
244+ removeExcludedModules . call ( this , compositeModules , packageForceExcludes , true ) ;
245+
246+ if ( _ . isEmpty ( compositeModules ) ) {
247+ // The compiled code does not reference any external modules at all
248+ this . serverless . cli . log ( 'No external modules needed' ) ;
249+ return BbPromise . resolve ( ) ;
326250 }
327- return BbPromise . resolve ( ) ;
328- } )
329- . then ( ( ) => hasPackageLock ?
330- BbPromise . fromCallback ( callback => fse . copy ( path . join ( compositeModulePath , packager . lockfileName ) , path . join ( modulePath , packager . lockfileName ) , callback ) ) :
331- BbPromise . resolve ( )
332- )
333- . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Copy modules: ${ modulePath } [${ _ . now ( ) - startCopy } ms]` ) )
334- . then ( ( ) => {
335- // Prune extraneous packages - removes not needed ones
336- const startPrune = _ . now ( ) ;
337- return packager . prune ( modulePath , this . configuration . packagerOptions )
338- . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Prune: ${ modulePath } [${ _ . now ( ) - startPrune } ms]` ) ) ;
339- } )
340- . then ( ( ) => {
341- // Prune extraneous packages - removes not needed ones
342- const startRunScripts = _ . now ( ) ;
343- return packager . runScripts ( modulePath , _ . keys ( packageScripts ) )
344- . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Run scripts: ${ modulePath } [${ _ . now ( ) - startRunScripts } ms]` ) ) ;
251+
252+ // (1.a) Install all needed modules
253+ const compositeModulePath = path . join ( this . webpackOutputPath , 'dependencies' ) ;
254+ const compositePackageJson = path . join ( compositeModulePath , 'package.json' ) ;
255+
256+ // (1.a.1) Create a package.json
257+ const compositePackage = _ . defaults ( {
258+ name : this . serverless . service . service ,
259+ version : '1.0.0' ,
260+ description : `Packaged externals for ${ this . serverless . service . service } ` ,
261+ private : true ,
262+ scripts : packageScripts
263+ } , packageSections ) ;
264+ const relPath = path . relative ( compositeModulePath , path . dirname ( packageJsonPath ) ) ;
265+ addModulesToPackageJson ( compositeModules , compositePackage , relPath ) ;
266+ this . serverless . utils . writeFileSync ( compositePackageJson , JSON . stringify ( compositePackage , null , 2 ) ) ;
267+
268+ // (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
269+ const packageLockPath = path . join ( path . dirname ( packageJsonPath ) , packager . lockfileName ) ;
270+ let hasPackageLock = false ;
271+ return BbPromise . fromCallback ( cb => fse . pathExists ( packageLockPath , cb ) )
272+ . then ( exists => {
273+ if ( exists ) {
274+ this . serverless . cli . log ( 'Package lock found - Using locked versions' ) ;
275+ try {
276+ let packageLockFile = this . serverless . utils . readFileSync ( packageLockPath ) ;
277+ packageLockFile = packager . rebaseLockfile ( relPath , packageLockFile ) ;
278+ if ( _ . isObject ( packageLockFile ) ) {
279+ packageLockFile = JSON . stringify ( packageLockFile , null , 2 ) ;
280+ }
281+
282+ this . serverless . utils . writeFileSync ( path . join ( compositeModulePath , packager . lockfileName ) , packageLockFile ) ;
283+ hasPackageLock = true ;
284+ } catch ( err ) {
285+ this . serverless . cli . log ( `Warning: Could not read lock file: ${ err . message } ` ) ;
286+ }
287+ }
288+ return BbPromise . resolve ( ) ;
289+ } )
290+ . then ( ( ) => {
291+ const start = _ . now ( ) ;
292+ this . serverless . cli . log ( 'Packing external modules: ' + compositeModules . join ( ', ' ) ) ;
293+ return packager . install ( compositeModulePath , this . configuration . packagerOptions )
294+ . then ( ( ) => this . options . verbose && this . serverless . cli . log ( `Package took [${ _ . now ( ) - start } ms]` ) )
295+ . return ( stats . stats ) ;
296+ } )
297+ . mapSeries ( compileStats => {
298+ const modulePath = compileStats . compilation . compiler . outputPath ;
299+
300+ // Create package.json
301+ const modulePackageJson = path . join ( modulePath , 'package.json' ) ;
302+ const modulePackage = _ . defaults ( {
303+ name : this . serverless . service . service ,
304+ version : '1.0.0' ,
305+ description : `Packaged externals for ${ this . serverless . service . service } ` ,
306+ private : true ,
307+ scripts : packageScripts ,
308+ dependencies : { }
309+ } , packageSections ) ;
310+ const prodModules = getProdModules . call ( this ,
311+ _ . concat (
312+ getExternalModules . call ( this , compileStats ) ,
313+ _ . map ( packageForceIncludes , whitelistedPackage => ( { external : whitelistedPackage } ) )
314+ ) , packagePath , dependencyGraph , packageForceExcludes ) ;
315+ removeExcludedModules . call ( this , prodModules , packageForceExcludes ) ;
316+ const relPath = path . relative ( modulePath , path . dirname ( packageJsonPath ) ) ;
317+ addModulesToPackageJson ( prodModules , modulePackage , relPath ) ;
318+ this . serverless . utils . writeFileSync ( modulePackageJson , JSON . stringify ( modulePackage , null , 2 ) ) ;
319+
320+ // GOOGLE: Copy modules only if not google-cloud-functions
321+ // GCF Auto installs the package json
322+ if ( _ . get ( this . serverless , 'service.provider.name' ) === 'google' ) {
323+ return BbPromise . resolve ( ) ;
324+ }
325+
326+ const startCopy = _ . now ( ) ;
327+ return BbPromise . try ( ( ) => {
328+ // Only copy dependency modules if demanded by packager
329+ if ( packager . mustCopyModules ) {
330+ return BbPromise . fromCallback ( callback => fse . copy ( path . join ( compositeModulePath , 'node_modules' ) , path . join ( modulePath , 'node_modules' ) , callback ) ) ;
331+ }
332+ return BbPromise . resolve ( ) ;
333+ } )
334+ . then ( ( ) => hasPackageLock ?
335+ BbPromise . fromCallback ( callback => fse . copy ( path . join ( compositeModulePath , packager . lockfileName ) , path . join ( modulePath , packager . lockfileName ) , callback ) ) :
336+ BbPromise . resolve ( )
337+ )
338+ . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Copy modules: ${ modulePath } [${ _ . now ( ) - startCopy } ms]` ) )
339+ . then ( ( ) => {
340+ // Prune extraneous packages - removes not needed ones
341+ const startPrune = _ . now ( ) ;
342+ return packager . prune ( modulePath , this . configuration . packagerOptions )
343+ . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Prune: ${ modulePath } [${ _ . now ( ) - startPrune } ms]` ) ) ;
344+ } )
345+ . then ( ( ) => {
346+ // Prune extraneous packages - removes not needed ones
347+ const startRunScripts = _ . now ( ) ;
348+ return packager . runScripts ( modulePath , _ . keys ( packageScripts ) )
349+ . tap ( ( ) => this . options . verbose && this . serverless . cli . log ( `Run scripts: ${ modulePath } [${ _ . now ( ) - startRunScripts } ms]` ) ) ;
350+ } ) ;
351+ } )
352+ . return ( ) ;
345353 } ) ;
346- } )
347- . return ( ) ;
348354 } ) ;
349- } ) ;
350355 }
351356} ;
0 commit comments