I am using serverless
to package nodejs application. I am using yarn workspace
in my project.
- common
- projectA
- projectB
the projectA
and projectB
are using common
module which is managed by yarn workspace
. It creates a link inside node_modules/common -> ../common
. But when I package the application with sls deploy
, it doesn't inlude the link node_modules/common
. How can I make it package symbolic link?
What code bundler does:
As you can see, it's a perfect match for AWS Lambda and your use case.
All of the dependencies from common
package will be included in the output file.
Also code bundlers have other cool features, like removing all of the unneeded files, that are defined in libraries that you use, but you are not using them directly. Due to this output package size of your Lambda will be a lot smaller, which will decrease cold starts.
The easiest way is to start with serverless-webpack plugin, which includes Webpack (one of the most popular code bundlers) and some most common configurations for it.
After adding this plugin, simply configure it in serverless.yml
:
custom:
webpack:
webpackConfig: 'webpack.config.js' # you can remove it, it's the same as default
packager: 'yarn'
Now you need to configure Webpack using webpack.config.js
file. There are a lot of possibilities to configure it and the example below is the most basic one:
const path = require('path');
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
stats: 'minimal',
devtool: 'nosources-source-map',
externals: [{'aws-sdk': 'commonjs aws-sdk'}],
resolve: {
extensions: ['.js', '.json'],
},
output: {
libraryTarget: 'commonjs2',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
sourceMapFilename: '[file].map',
},
};
Now when you call sls package
in projectA
or projectB
, then after unzipping ./.serverless/functionName.zip
, you will find just single "fat" file, that will include all of the required dependencies.
During sls deploy
phase, this file will be deployed as Lambda handler.
Make sure, that common
package is listed as dependency of projectA
and projectB
:
// common/package.json
{
"name": "@your-project/common",
"version": "1.0.0",
"license": "ISC",
}
// projectA/package.json
{
"name": "@your-project/packageA",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@your-project/common": "1.0.0"
}
}
Thanks to this, you will be able to reference commons in pakcageA imports via:
import exampleHelper from '@your-project/common/src/exampleHelper';
Project using this approach can be found on my Github here: