@@ -107,8 +107,8 @@ module.exports = {
107107 if ( _ . isString ( this . webpackConfig ) ) {
108108 const webpackConfigFilePath = path . join ( this . serverless . config . servicePath , this . webpackConfig ) ;
109109 if ( ! this . serverless . utils . fileExistsSync ( webpackConfigFilePath ) ) {
110- throw new this . serverless . classes
111- . Error ( 'The webpack plugin could not find the configuration file at: ' + webpackConfigFilePath ) ;
110+ return BbPromise . reject ( new this . serverless . classes
111+ . Error ( 'The webpack plugin could not find the configuration file at: ' + webpackConfigFilePath ) ) ;
112112 }
113113 try {
114114 this . webpackConfig = require ( webpackConfigFilePath ) ;
@@ -117,104 +117,115 @@ module.exports = {
117117 return BbPromise . reject ( err ) ;
118118 }
119119 }
120+
121+ // Intermediate function to handle async webpack config
122+ const processConfig = _config => {
123+ this . webpackConfig = _config ;
124+ // Default context
125+ if ( ! this . webpackConfig . context ) {
126+ this . webpackConfig . context = this . serverless . config . servicePath ;
127+ }
120128
121- // Default context
122- if ( ! this . webpackConfig . context ) {
123- this . webpackConfig . context = this . serverless . config . servicePath ;
124- }
125-
126- // Default target
127- if ( ! this . webpackConfig . target ) {
128- this . webpackConfig . target = 'node' ;
129- }
130-
131- // Default output
132- if ( ! this . webpackConfig . output || _ . isEmpty ( this . webpackConfig . output ) ) {
133- const outputPath = path . join ( this . serverless . config . servicePath , '.webpack' ) ;
134- this . webpackConfig . output = {
135- libraryTarget : 'commonjs' ,
136- path : outputPath ,
137- filename : '[name].js' ,
138- } ;
139- }
140-
141- // Custom output path
142- if ( this . options . out ) {
143- this . webpackConfig . output . path = path . join ( this . serverless . config . servicePath , this . options . out ) ;
144- }
129+ // Default target
130+ if ( ! this . webpackConfig . target ) {
131+ this . webpackConfig . target = 'node' ;
132+ }
145133
146- if ( this . skipCompile ) {
147- this . serverless . cli . log ( 'Skipping build and using existing compiled output' ) ;
148- if ( ! fse . pathExistsSync ( this . webpackConfig . output . path ) ) {
149- return BbPromise . reject ( new this . serverless . classes
150- . Error ( 'No compiled output found' ) ) ;
134+ // Default output
135+ if ( ! this . webpackConfig . output || _ . isEmpty ( this . webpackConfig . output ) ) {
136+ const outputPath = path . join ( this . serverless . config . servicePath , '.webpack' ) ;
137+ this . webpackConfig . output = {
138+ libraryTarget : 'commonjs' ,
139+ path : outputPath ,
140+ filename : '[name].js' ,
141+ } ;
151142 }
152- this . keepOutputDirectory = true ;
153- }
154143
155- if ( ! this . keepOutputDirectory ) {
156- this . options . verbose && this . serverless . cli . log ( `Removing ${ this . webpackConfig . output . path } ` ) ;
157- fse . removeSync ( this . webpackConfig . output . path ) ;
158- }
159- this . webpackOutputPath = this . webpackConfig . output . path ;
144+ // Custom output path
145+ if ( this . options . out ) {
146+ this . webpackConfig . output . path = path . join ( this . serverless . config . servicePath , this . options . out ) ;
147+ }
160148
161- // In case of individual packaging we have to create a separate config for each function
162- if ( _ . has ( this . serverless , 'service.package' ) && this . serverless . service . package . individually ) {
163- this . options . verbose && this . serverless . cli . log ( 'Using multi-compile (individual packaging)' ) ;
164- this . multiCompile = true ;
149+ if ( this . skipCompile ) {
150+ this . serverless . cli . log ( 'Skipping build and using existing compiled output' ) ;
151+ if ( ! fse . pathExistsSync ( this . webpackConfig . output . path ) ) {
152+ return BbPromise . reject ( new this . serverless . classes
153+ . Error ( 'No compiled output found' ) ) ;
154+ }
155+ this . keepOutputDirectory = true ;
156+ }
165157
166- if ( this . webpackConfig . entry && ! _ . isEqual ( this . webpackConfig . entry , entries ) ) {
167- return BbPromise . reject ( new this . serverless . classes
168- . Error ( 'Webpack entry must be automatically resolved when package.individually is set to true. ' +
169- 'In webpack.config.js, remove the entry declaration or set entry to slsw.lib.entries.' ) ) ;
158+ if ( ! this . keepOutputDirectory ) {
159+ this . options . verbose && this . serverless . cli . log ( `Removing ${ this . webpackConfig . output . path } ` ) ;
160+ fse . removeSync ( this . webpackConfig . output . path ) ;
170161 }
162+ this . webpackOutputPath = this . webpackConfig . output . path ;
171163
172- // Lookup associated Serverless functions
173- const allEntryFunctions = _ . map (
174- this . serverless . service . getAllFunctions ( ) ,
175- funcName => {
176- const func = this . serverless . service . getFunction ( funcName ) ;
177- const handler = func . handler ;
178- const handlerFile = path . relative ( '.' , getHandlerFile ( handler ) ) ;
179- return {
180- handlerFile,
181- funcName,
182- func
183- } ;
164+ // In case of individual packaging we have to create a separate config for each function
165+ if ( _ . has ( this . serverless , 'service.package' ) && this . serverless . service . package . individually ) {
166+ this . options . verbose && this . serverless . cli . log ( 'Using multi-compile (individual packaging)' ) ;
167+ this . multiCompile = true ;
168+
169+ if ( this . webpackConfig . entry && ! _ . isEqual ( this . webpackConfig . entry , entries ) ) {
170+ return BbPromise . reject ( new this . serverless . classes
171+ . Error ( 'Webpack entry must be automatically resolved when package.individually is set to true. ' +
172+ 'In webpack.config.js, remove the entry declaration or set entry to slsw.lib.entries.' ) ) ;
184173 }
185- ) ;
186174
187- this . entryFunctions = _ . flatMap ( entries , ( value , key ) => {
188- const entry = path . relative ( '.' , value ) ;
189- const entryFile = _ . replace ( entry , new RegExp ( `${ path . extname ( entry ) } $` ) , '' ) ;
175+ // Lookup associated Serverless functions
176+ const allEntryFunctions = _ . map (
177+ this . serverless . service . getAllFunctions ( ) ,
178+ funcName => {
179+ const func = this . serverless . service . getFunction ( funcName ) ;
180+ const handler = func . handler ;
181+ const handlerFile = path . relative ( '.' , getHandlerFile ( handler ) ) ;
182+ return {
183+ handlerFile,
184+ funcName,
185+ func
186+ } ;
187+ }
188+ ) ;
189+
190+ this . entryFunctions = _ . flatMap ( entries , ( value , key ) => {
191+ const entry = path . relative ( '.' , value ) ;
192+ const entryFile = _ . replace ( entry , new RegExp ( `${ path . extname ( entry ) } $` ) , '' ) ;
193+
194+ const entryFuncs = _ . filter ( allEntryFunctions , [ 'handlerFile' , entryFile ] ) ;
195+ if ( _ . isEmpty ( entryFuncs ) ) {
196+ // We have to make sure that for each entry there is an entry function item.
197+ entryFuncs . push ( { } ) ;
198+ }
199+ _ . forEach ( entryFuncs , entryFunc => {
200+ entryFunc . entry = {
201+ key,
202+ value
203+ } ;
204+ } ) ;
205+ return entryFuncs ;
206+ } ) ;
190207
191- const entryFuncs = _ . filter ( allEntryFunctions , [ 'handlerFile' , entryFile ] ) ;
192- if ( _ . isEmpty ( entryFuncs ) ) {
193- // We have to make sure that for each entry there is an entry function item.
194- entryFuncs . push ( { } ) ;
195- }
196- _ . forEach ( entryFuncs , entryFunc => {
197- entryFunc . entry = {
198- key,
199- value
208+ this . webpackConfig = _ . map ( this . entryFunctions , entryFunc => {
209+ const config = _ . cloneDeep ( this . webpackConfig ) ;
210+ config . entry = {
211+ [ entryFunc . entry . key ] : entryFunc . entry . value
200212 } ;
213+ const compileName = entryFunc . funcName || _ . camelCase ( entryFunc . entry . key ) ;
214+ config . output . path = path . join ( config . output . path , compileName ) ;
215+ return config ;
201216 } ) ;
202- return entryFuncs ;
203- } ) ;
217+ } else {
218+ this . webpackConfig . output . path = path . join ( this . webpackConfig . output . path , 'service' ) ;
219+ }
204220
205- this . webpackConfig = _ . map ( this . entryFunctions , entryFunc => {
206- const config = _ . cloneDeep ( this . webpackConfig ) ;
207- config . entry = {
208- [ entryFunc . entry . key ] : entryFunc . entry . value
209- } ;
210- const compileName = entryFunc . funcName || _ . camelCase ( entryFunc . entry . key ) ;
211- config . output . path = path . join ( config . output . path , compileName ) ;
212- return config ;
213- } ) ;
221+ return BbPromise . resolve ( ) ;
222+ } ;
223+
224+ // Webpack config can be a Promise, If it's a Promise wait for resolved config object.
225+ if ( this . webpackConfig && _ . isFunction ( this . webpackConfig . then ) ) {
226+ return BbPromise . resolve ( this . webpackConfig . then ( config => processConfig ( config ) ) ) ;
214227 } else {
215- this . webpackConfig . output . path = path . join ( this . webpackConfig . output . path , 'service' ) ;
228+ return processConfig ( this . webpackConfig ) ;
216229 }
217-
218- return BbPromise . resolve ( ) ;
219230 } ,
220231} ;
0 commit comments