Serverless-webpack: Errors when using a Webpack config with multiple configurations

Created on 23 Aug 2018  路  7Comments  路  Source: serverless-heaven/serverless-webpack

This is a Bug Report

Description

I'm using multiples entries in my Webpack config (as described here). Everything works fine using serverless offline start to develop locally. However, when I try to package it, it fails with the following error:

TypeError: Cannot read property 'errors' of undefined
at _.forEach.compileStats (/web-ui/node_modules/serverless-webpack/lib/compile.js:33:40)
at arrayEach (/web-ui/node_modules/lodash/lodash.js:516:11)
at Function.forEach (/web-ui/node_modules/lodash/lodash.js:9342:14)
at BbPromise.fromCallback.then.stats (/web-ui/node_modules/serverless-webpack/lib/compile.js:30:11)
at finalCallback (/web-ui/node_modules/webpack/lib/MultiCompiler.js:247:12)
at runWithDependencies.err (/web-ui/node_modules/webpack/lib/MultiCompiler.js:270:6)

According to the code in question in serverless-webpack/lib/compile.js, it seems like the variable on line 30 compileStats is an array when using multiple configs, rather than an object.

The reason I'm using multiples configurations is that I'm using serverless-webpack to build a front-end application written in React that I render server-side using serverless. So one of the configuration is for the client-side, the other configuration is for the server-side. Both are using the same sources, but with different options/loaders, and I want to deploy both of the app together.

I can create a reproduction repo if it can help.

Similar or dependent issue(s):

  • #124
  • #102

Additional Data

  • Serverless-Webpack Version you're using: 5.2.0
  • Webpack version you're using: 4.17.1
  • Serverless Framework Version you're using: 1.30.1
  • Operating System: macOS 10.13.6
  • Stack Trace (if available):

TypeError: Cannot read property 'errors' of undefined
at _.forEach.compileStats (/web-ui/node_modules/serverless-webpack/lib/compile.js:33:40)
at arrayEach (/web-ui/node_modules/lodash/lodash.js:516:11)
at Function.forEach (/web-ui/node_modules/lodash/lodash.js:9342:14)
at BbPromise.fromCallback.then.stats (/web-ui/node_modules/serverless-webpack/lib/compile.js:30:11)
at finalCallback (/web-ui/node_modules/webpack/lib/MultiCompiler.js:247:12)
at runWithDependencies.err (/web-ui/node_modules/webpack/lib/MultiCompiler.js:270:6)
at done (/web-ui/node_modules/neo-async/async.js:2920:13)
at runCompilers (/web-ui/node_modules/webpack/lib/MultiCompiler.js:174:48)
at err (/web-ui/node_modules/webpack/lib/MultiCompiler.js:181:7)
at compiler.run (/web-ui/node_modules/webpack/lib/MultiCompiler.js:263:7)
at finalCallback (/web-ui/node_modules/webpack/lib/Compiler.js:210:39)
at hooks.done.callAsync.err (/web-ui/node_modules/webpack/lib/Compiler.js:259:14)
at AsyncSeriesHook.eval [as callAsync] (eval at create (/web-ui/node_modules/tapable/lib/HookCodeFactory.js:24:12), :15:1)
at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/web-ui/node_modules/tapable/lib/Hook.js:35:21)
at emitRecords.err (/web-ui/node_modules/webpack/lib/Compiler.js:257:22)
at Compiler.emitRecords (/web-ui/node_modules/webpack/lib/Compiler.js:372:39)
at emitAssets.err (/web-ui/node_modules/webpack/lib/Compiler.js:251:10)
at hooks.afterEmit.callAsync.err (/web-ui/node_modules/webpack/lib/Compiler.js:358:14)
at _err0 (eval at create (/web-ui/node_modules/tapable/lib/HookCodeFactory.js:24:12), :11:1)
at callback (/web-ui/node_modules/copy-webpack-plugin/dist/index.js:126:17)
at afterEmit (/web-ui/node_modules/copy-webpack-plugin/dist/index.js:220:13)
at AsyncSeriesHook.eval [as callAsync] (eval at create (/web-ui/node_modules/tapable/lib/HookCodeFactory.js:24:12), :7:1)
at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/web-ui/node_modules/tapable/lib/Hook.js:35:21)
at asyncLib.forEach.err (/web-ui/node_modules/webpack/lib/Compiler.js:355:27)
at done (/web-ui/node_modules/neo-async/async.js:2854:11)
at /web-ui/node_modules/neo-async/async.js:2805:7
at /web-ui/node_modules/graceful-fs/graceful-fs.js:43:10
at FSReqWrap.oncomplete (fs.js:139:20)
From previous event:
at ServerlessWebpack.compile (/web-ui/node_modules/serverless-webpack/lib/compile.js:15:8)
From previous event:
at Object.webpack:compile:compile [as hook] (/web-ui/node_modules/serverless-webpack/index.js:160:10)
at BbPromise.reduce (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:390:55)
From previous event:
at PluginManager.invoke (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:390:22)
at PluginManager.spawn (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:408:17)
at ServerlessWebpack.BbPromise.bind.then.then (/web-ui/node_modules/serverless-webpack/index.js:101:51)
From previous event:
at Object.before:package:createDeploymentArtifacts [as hook] (/web-ui/node_modules/serverless-webpack/index.js:101:10)
at BbPromise.reduce (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:390:55)
From previous event:
at PluginManager.invoke (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:390:22)
at PluginManager.run (/web-ui/node_modules/web-ui/lib/classes/PluginManager.js:421:17)
at variables.populateService.then.then (/web-ui/node_modules/web-ui/lib/Serverless.js:157:33)
at runCallback (timers.js:693:18)
at tryOnImmediate (timers.js:664:5)
at processImmediate (timers.js:646:5)
at process.topLevelDomainCallback (domain.js:121:23)
From previous event:
at Serverless.run (/web-ui/node_modules/web-ui/lib/Serverless.js:144:8)
at serverless.init.then (/web-ui/node_modules/web-ui/bin/serverless:43:50)

Most helpful comment

Hi @hamstercat , serverless-webpack is specialized to deploy Lambda code using webpacked sources. It is not intended to use the same configuration for client (bundle) compiles and server compiles. It is optimized to e.g. autotdetect the entries via slsw.lib.entries.

We had the same with a server based rendering solution and solved it by using 2 separate webpack configs and adding the client compile and s3 upload of the client bundle in a script hook using serverless-plugin-scripts.
That works perfectly and makes sure that when you deploy your lambda, a fresh, matching client bundle is deployed too.

All 7 comments

Hi @hamstercat , serverless-webpack is specialized to deploy Lambda code using webpacked sources. It is not intended to use the same configuration for client (bundle) compiles and server compiles. It is optimized to e.g. autotdetect the entries via slsw.lib.entries.

We had the same with a server based rendering solution and solved it by using 2 separate webpack configs and adding the client compile and s3 upload of the client bundle in a script hook using serverless-plugin-scripts.
That works perfectly and makes sure that when you deploy your lambda, a fresh, matching client bundle is deployed too.

Thanks for the quick follow-up, I went ahead and tried your suggestion and it's working well! Had to change a couple of things on how I handled things (since assets are no longer locally available to the server), and it's mostly working. There's juste one thing left, not sure if you have had the same problem before.

I'm generating a JSON file based on the webpack stats so that, coupled with code-splitting and async components, I can include the minimum required code whenever a page is rendered. All of this is done using React Universal Component. The jist of it is that the client webpack build generates the file, and the server code uses it at runtime to find which client assets to include in a specific page.

For the time being I've changed my handler to request that JSON file over HTTP instead of through the filesystem, but since that file can become huge in size I was wondering if anyone had solved that particular issue before without going through HTTP?

After using it, turns out doing the HTTP call is working well. I only had to optimize the webpack stats file by including less stuff in it, but it got to a point where the file is less than 100k. Thanks again for the suggestion!

I'd like to incite some discussion to reconsider this decision.

Part of the appeal of webpack is being able to customize complicated build processes. I feel as if serverless-webpack should allow integrating serverless and webpack without limiting how you use and configure either tool.

Creating two separate webpack configuration files seems like it should be functionally equivalent to creating two configurations in a single file. If serverless-webpack needs to be able to know which bundles are intended for it, that feels like it should be configurable within the serverless.yml's custom.webpack settings. Which bundles I need to produce for my project and how they get built should be my decision.

I think we could easily keep the happy path of one webpack config file + one configuration within + plain reference to that single file in custom.webpack = assume all bundles are functions without prohibiting full usage of webpack features.

To add a usecase I've not seen mentioned here, I'm trying to use webpack to compile my TypeScript project uniformly, and want to build lambda functions written in TS as well as database migration scripts written in TS without duplicating the TS compilation configuration between two different files. Both the lambdas and scripts are logically separate entrypoints with separate output directories, that otherwise need to go through the same build process. There are many other ways to approach this but I'd rather just use webpack.

Hi @HyperBrain, I have a use-case where I would like to use serverless-webpack to compile both AWS Lambda and Lambda@Edge functions (those meant to be triggered by a CloudFront distribution).

They work in a similar fashion, expect that Lambda@Edge functions are extremely restricted in size, memory and timeout duration.

Therefore, I have a need for different webpack configurations (plugins, optimisation etc.) for the Lambda@Edge functions.

I ended up using 2 services so far (2 serverless configuration files and 2 webpack config files), but I would find it quite nicer to merge those into one service, but that would require the possibility to export an array of configs from one webpack file (filtering slsw.lib.entries to separate the config applied to each entry)

@flosch-hb , Can you please try #537? Let me know if you face any issues.

Thanks for the effort @RishikeshDarandale, will try that as soon as I get the chance :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

serverlesspolska picture serverlesspolska  路  4Comments

hassankhan picture hassankhan  路  3Comments

heri16 picture heri16  路  4Comments

deftomat picture deftomat  路  5Comments

tommedema picture tommedema  路  4Comments