I’m getting a bit frustrated with serverless deployment, everything I do seems to run into a new deployment error. I don’t want to seem unappreciative of the platform, it seems like a great tool but I just haven’t had any working deployments yet with a couple weeks now of troubleshooting. I really hope I can get some kind of guidance, my other posts are unanswered for now. I’m using nodejs 12 with express and typescript. Local testing with serverless offline works, but any deployment does not! I am trying to use the serverless-webpack
plugin because a normal deployment gives a error in maximum zip
file size.
Here is my folder structure:
Here is the main points of my handler function file at: server/server.ts
import serverless from 'serverless-http';
app.listen();
// Adding serverless express app from my app class.
module.exports.handler = serverless(app.app);
This is my serverless.yml
:
service: editly-api
app: initiate-web # app and org for use with dashboard.serverless.com
org: arielf
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
frameworkVersion: '2'
useDotenv: true
plugins:
- '@kingdarboja/serverless-plugin-typescript'
# - serverless-plugin-typescript
- serverless-webpack
- serverless-offline
package:
individually: true
exclude:
- 'node_modules/.cache/**'
- 'tests/**'
- 'tests-integration/**'
- '.idea/**'
- 'serverless-configs/**'
- 'envs/**'
- 'support/**'
- 'scripts/**'
custom:
typeScript:
tsconfigFilePath: tsconfig.backend.json
webpack: # https://github.com/serverless-heaven/serverless-webpack
webpackConfig: 'serverless.config.js' # Name of webpack configuration file
packager: 'yarn' # Packager that will be used to package your external modules
packagerOptions: {} # Optional, depending on the selected packager
provider:
name: aws
runtime: nodejs12.x
lambdaHashingVersion: 20201221
stage: dev
region: us-west-1
apiGateway:
minimumCompressionSize: 1024
environment:
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1
functions:
app:
handler: server/server.handler
events:
- http: ANY /
- http: 'ANY /{proxy+}'
My serverless.config.js
file looks like this:
'use strict';
// This file is used for serverless deployment, use webpack.config.js for normal builds.
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const NodemonPlugin = require('nodemon-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const { CheckerPlugin } = require('awesome-typescript-loader');
// @ts-ignore
const slsw = require('serverless-webpack');
var nodeExternals = require('webpack-node-externals');
const config = (async function () {
const serverPath = path.resolve('./server');
const tempPath = path.join(__dirname, 'tmp');
const buildPath = path.resolve(__dirname, '.build');
const distPath = path.resolve(__dirname, '/dist');
console.log('buildPath', buildPath);
return {
cache: true,
entry: slsw.lib.entries,
stats: {
warnings: false,
},
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
output: {
publicPath: distPath,
path: buildPath,
filename: 'server.js',
},
devServer: {
publicPath: distPath,
path: buildPath,
filename: 'server.js',
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
},
],
},
target: 'node',
externals: [nodeExternals()],
optimization: {
minimize: false,
concatenateModules: false,
},
watchOptions: {
ignored: ['node_modules/**', tempPath],
},
plugins: [
// @ts-ignore
new NodemonPlugin({
watch: serverPath,
ignore: ['*.js.map', '*.mp4', '*.png', '*.mov', '*.mp3', './server/tmp/*', './build', '**/tmp/**'],
ext: 'ts,tsx',
verbose: true,
}),
new webpack.DefinePlugin({
'process.env.FLUENTFFMPEG_COV': false,
}),
new webpack.DefinePlugin({
'process.browser': 'true',
}),
],
};
})();
module.exports = config;
Here is my package.json
:
"dependencies": {
"serverless": "^2.25.2",
"serverless-http": "^2.7.0",
},
"devDependencies": {
"@kingdarboja/serverless-plugin-typescript": "^1.4.1",
"serverless-offline": "^6.8.0",
"serverless-plugin-typescript": "^1.1.7",
"serverless-webpack": "5.1.0",
"tsconfig-paths-webpack-plugin": "^3.3.0",
"typescript": "^4.1.3",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.1",
"webpack-node-externals": "^2.5.2"
}
I am running the command: rimraf .build .serverless && serverless deploy
because if I don’t delete the .build
folder I run into EPERM errors.
Serverless Error ---------------------------------------
The webpack plugin could not find the configuration file at: C:\Users\Ariel\initiate-video\backend\.build\serverless.config.js
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: win32
Node Version: 12.19.0
Framework Version: 2.25.2 (local)
Plugin Version: 4.4.3
SDK Version: 2.3.2
Components Version: 3.7.0
I noticed with TS plugin it searches for the webpack config file in the .build
directory which is strange and does not happen without the TS plugin. So no problem I will change the webpackConfig
path:
webpackConfig: '../serverless.config.js'
Here is the resulting path error:
Serverless: Deprecation warning: Starting with next major version, API Gateway naming will be changed from "{stage}-{service}" to "{service}-{stage}".
Set "provider.apiGateway.shouldStartNameWithService" to "true" to adapt to the new behavior now.
More Info: https://www.serverless.com/framework/docs/deprecations/#AWS_API_GATEWAY_NAME_STARTING_WITH_SERVICE
Serverless: Compiling with Typescript...
Serverless: Using local tsconfig.json at "C:\Users\Ariel\initiate-video\backend\tsconfig.backend.json"
Serverless: TypeScript compiled.
Serverless: Copying Extras...
Serverless: Finished Copying Extras
Serverless: Copying Dependencies ...
Serverless: Finished Copying Dependencies ...
Serverless: WARNING: More than one matching handlers found for 'server/server'. Using 'server/server.js'.
buildPath C:\Users\Ariel\initiate-video\backend\.build
config :>> {}
compileName app
config.output undefined
Type Error ---------------------------------------------
TypeError: Cannot read property 'path' of undefined
at C:\Users\Ariel\initiate-video\backend\node_modules\serverless-webpack\lib\validate.js:209:54
at arrayMap (C:\Users\Ariel\initiate-video\backend\node_modules\lodash\lodash.js:653:23)
at Function.map (C:\Users\Ariel\initiate-video\backend\node_modules\lodash\lodash.js:9622:14)
at ServerlessWebpack.validate (C:\Users\Ariel\initiate-video\backend\node_modules\serverless-webpack\lib\validate.js:200:30)
at ServerlessWebpack.tryCatcher (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\promise.js:547:31)
at Promise._settlePromise (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\promise.js:604:18)
at Promise._settlePromiseCtx (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\promise.js:641:10)
at _drainQueueStep (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\async.js:97:12)
at _drainQueue (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\async.js:86:9)
at Async._drainQueues (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (C:\Users\Ariel\initiate-video\backend\node_modules\bluebird\js\release\async.js:15:14)
at processImmediate (internal/timers.js:461:21)
For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
I added some console logging in the serverless-webpack module’s validate.js
and you can see in the above error the config is empty!
this.webpackConfig = _.map(this.entryFunctions, entryFunc => {
const config = _.cloneDeep(this.webpackConfig);
console.log('config :>> ', config);
config.entry = {
[entryFunc.entry.key]: entryFunc.entry.value,
};
const compileName = entryFunc.funcName || _.camelCase(entryFunc.entry.key);
console.log('compileName', compileName);
console.log('config.output', config.output);
config.output.path = path.join(config.output.path, compileName);
return config;
});
It seems something is going wrong with parsing the correct webpack config file. If I change the TS plugin to serverless-plugin-typescript
with serverless-webpack
I do get the same webpack path undefined
error with the config being empty. I’m using the @kingdarboja/serverless-plugin-typescript
plugin because trying the other main TS plugin: serverless-plugin-typescript
was giving a different error on a different occasion which I honestly don’t remember. Here is the unzipped size error I get if I don’t use serverless-webpack
...
Serverless: Uploading service app.zip file to S3 (484.41 MB)...
...
Serverless: Publishing service to the Serverless Dashboard...
Serverless: Successfully published your service to the Serverless Dashboard:
Serverless Error ---------------------------------------
An error occurred: AppLambdaFunction - Unzipped size must be smaller than 262144000 bytes (Service: AWSLambdaInternal; Status Code: 400; Error Code: InvalidParameterValueException; Request ID: 13171d34-9eda-40d7-81be-1e
9dc58e8e96; Proxy: null).
I hope this post gives all the necessary information for debugging/troubleshooting I wanted to be thorough. I’ve tried many different configurations and plugins I just want something to work!! Thank you all in advance.