serverless-webpack
serverless-webpack copied to clipboard
How to use in Monorepo without producing tons of duplicate code.
This is a Question / Clarification
Description
How do you use this within a Monorepo. Ideally you would define a single webpack.config.js and .babelrc file, and no matter the services, it should share that config. It seems when I specify a webpack.config.js in root, it assumes the functions are located there.
What is the best practices? Is this supported?
In order to have multiple functions in different folders you have to add this to your webpack confg:
module.exports = { entry: slsw.lib.entries };
It takes all functions from your serverless config which contains paths to all functions handlers. For example your serverless.yml file can look like this:
functions: trackFulfillment: handler: src/functions/track/fulfillment/handler.trackFulfillment trackValidation: handler: src/functions/track/validation/handler.trackValidation feedbackFulfillment: handler: src/functions/feedback/fulfillment/handler.feedbackFulfillment feedbackValidation: handler: src/functions/feedback/validation/handler.feedbackValidation
When configured like this you don't need to change anything in webpack config whenever new function is added.
@rbobko93 - I did discover this, but this makes sense if I have one serverless.yml file.
I am looking at a structure more like below. Each services has a package.json and a serverless.yml.
I am curious if each serverless.yml should be configured like something below - What is the best practice. Does each package.json need to have webpack and babel plugin inside of each service, or is there a way to contain this at root to reduce code?
In a traditional node monorepo, I would have a separate package.json in each separated concerns. How do you mimic that structure with the least code copy/pasted between them. Does this make more sense?
My Current Folder Structure
package.json
webpack.config.js
.babelrc
jest.config.js
resources/
dynamo-table.yml
s3-bucket.yml
package.json
serverless.yml
services/
users/
create.js
create.test.js
list.js
list.test.js
delete.js
delete.test.js
update.js
update.test.js
get.js
get.test.js
package.json
serverless.yml
projects/
create.js
create.test.js
list.js
list.test.js
delete.js
delete.test.js
update.js
update.test.js
get.js
get.test.js
package.json
serverless.yml
etc/
...
Example Service Yaml File
service: service-name
plugins:
- serverless-webpack
- serverless-dynamodb-local
- serverless-offline
- serverless-domain-manager
- serverless-plugin-stage-variables
custom:
webpack:
webpackConfig: ../../webpack.config.js
includeModules:
forceExclude:
- aws-sdk
stage: ${opt:stage, self:provider.stage}
stageVariables:
env: ${self:custom.stage}
tables:
projects: projects-${self:custom.stage}
domains:
prod: api.example.com
stage: stage-api.example.com
dev: dev-api.example.com
customDomain:
domainName: ${self:custom.domains.${self:custom.stage}}
basePath: 'projects'
stage: ${self:custom.stage}
createRoute53Record: true
dynamodb:
start:
port: 8000
inMemory: true
migrate: true
migration:
dir: migrations
package:
exclude:
- coverage/**
- migrations/**
- .circleci/**
- .git/**
- tests/**
provider:
name: aws
runtime: nodejs8.10
stage: dev
region: us-east-1
iamRoleStatements:
- Effect: "Allow"
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource: "arn:aws:dynamodb:*:*:table/${self:custom.tables.projects}"
functions:
create:
handler: create.default
events:
- http:
path: /
method: post
cors: true
environment:
PROJECTS_TABLE: ${self:custom.tables.projects}
list:
handler: list.default
events:
- http:
path: /
method: get
cors: true
environment:
PROJECTS_TABLE: ${self:custom.tables.projects}
get:
handler: get.default
events:
- http:
path: /{id}
method: get
cors: true
environment:
PROJECTS_TABLE: ${self:custom.tables.projects}
update:
handler: update.default
events:
- http:
path: /{id}
method: put
cors: true
environment:
PROJECTS_TABLE: ${self:custom.tables.projects}
delete:
handler: delete.default
events:
- http:
path: /{id}
method: delete
cors: true
environment:
PROJECTS_TABLE: ${self:custom.tables.projects}
Error when running against root webpack.config.js
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be one of these:
object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function
-> The entry point(s) of the compilation.
Details:
* configuration.entry should not be empty.
-> Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.
* configuration.entry should be a string.
-> An entry point without name. The string is resolved to a module which is loaded upon startup.
* configuration.entry should be an array:
[non-empty string]
* configuration.entry should be an instance of function
-> A Function returning an entry object, an entry string, an entry array or a promise to these things.
Root Webpack Config
const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");
module.exports = {
entry: slsw.lib.entries,
target: "node",
// Generate sourcemaps for proper error messages
devtool: 'source-map',
// Since 'aws-sdk' is not compatible with webpack,
// we exclude all node dependencies
externals: [nodeExternals()],
mode: slsw.lib.webpack.isLocal ? "development" : "production",
optimization: {
// We do not want to minimize our code.
minimize: false
},
performance: {
// Turn off size warnings for entry points
hints: false
},
// Run babel on all .js files and skip those in node_modules
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
include: __dirname,
exclude: /node_modules/
}
]
}
};
@khrome83 did you find a resolution to this problem?
I have a small Serverless project which is about to get considerably more complex and as there are only two people working on it I'm learning towards keeping a mono-repo however I'm seeing lots of people mentioning this issues so I'm unsure.
It's possible to have a single webpack config file in a root, but as a result you must move "serverless-webpack" and "webpack" npm dependencies in a root package.json (and ignore warnings while npm i eg. npm WARN [email protected] requires a peer of webpack@>=2 but none is installed. You must install peer dependencies yourself.) also you should setup correct webpackConfig path in serverless.yml
Hi all, just thought I'd share how we manage similar webpack configurations in a monorepo. We use Yarn Workspaces, but you should be able to do without.
We created a @org/webpack-config package that exports a single .js file with the base Webpack config.
Then in each Serverless project inside the monorepo, you can do something like:
services/users/webpack.config.js:
const slsw = require('serverless-webpack');
const baseConfig = require('@org/webpack-config');
module.exports = {
...baseConfig,
entry: slsw.lib.entries,
}
@hassankhan Could you give an example of what the baseConfig would look? This almost worked for me but I'm not sure if it was some wrong Typescript configuration that is preventing me from actually getting somewhere.