# serverless-webpack **Repository Path**: mirrors_stevemao/serverless-webpack ## Basic Information - **Project Name**: serverless-webpack - **Description**: Serverless plugin to bundle your lambdas with Webpack - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-26 - **Last Updated**: 2025-09-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Serverless Webpack [![Serverless][ico-serverless]][link-serverless] [![License][ico-license]][link-license] [![NPM][ico-npm]][link-npm] [![Build Status][ico-build]][link-build] [![Coverage Status][ico-coverage]][link-coverage] [![Contributors][ico-contributors]][link-contributors] A Serverless v1.x plugin to build your lambda functions with [Webpack][link-webpack]. This plugin is for you if you want to use the latest Javascript version with [Babel][link-babel]; use custom [resource loaders][link-webpack-loaders], optimize your packaged functions individually and much more! ## Highlights * Configuration possibilities range from zero-config to fully customizable * Support of `serverless package`, `serverless deploy` and `serverless deploy function` * Support of `serverless invoke local` and `serverless invoke local --watch` * Support of `serverless run` and `serverless run --watch` * Integrates with [`serverless-offline`][link-serverless-offline] to simulate local API Gateway endpoints * When enabled in your service configuration, functions are packaged and compiled individually, resulting in smaller Lambda packages that contain only the code and dependencies needed to run the function. This allows the plugin to fully utilize WebPack's [Tree-Shaking][link-webpack-tree] optimization. * Webpack version 3 and 4 support * Support NPM and Yarn for packaging * Support asynchronous webpack configuration ## Recent improvements and important changes for 5.x * Support Yarn * Support Webpack 4 * Cleaned up configuration. You should now use a `custom.webpack` object to configure everything relevant for the plugin. The old configuration still works but will be removed in the next major release. For details see below. * Added support for asynchronous webpack configuration For the complete release notes see the end of this document. ## Install ```bash $ npm install serverless-webpack --save-dev ``` Add the plugin to your `serverless.yml` file: ```yaml plugins: - serverless-webpack ``` ## Configure The configuration of the plugin is done by defining a `custom: webpack` object in your `serverless.yml` with your specific configuration. All settings are optional and will be set to reasonable defaults if missing. See the sections below for detailed descriptions of the settings. The defaults are: ```yaml custom: webpack: webpackConfig: 'webpack.config.js' # Name of webpack configuration file includeModules: false # Node modules configuration for packaging packager: 'npm' # Packager that will be used to package your external modules ``` ### Webpack configuration file By default the plugin will look for a `webpack.config.js` in the service directory. Alternatively, you can specify a different file or configuration in `serverless.yml`. ```yaml custom: webpack: webpackConfig: ./folder/my-webpack.config.js ``` A base Webpack configuration might look like this: ```js // webpack.config.js module.exports = { entry: './handler.js', target: 'node', module: { loaders: [ ... ] } }; ``` Alternatively the Webpack configuration can export an asynchronous object (e.g. a promise or async function) which will be awaited by the plugin and resolves to the final configuration object. This is useful if the confguration depends on asynchronous functions, for example, defining the AccountId of the current aws user inside AWS lambda@edge which does not support defining normal process environment variables. A basic Webpack promise configuration might look like this: ```js // Version if the local Node.js version supports async/await // webpack.config.js const webpack = require('webpack') const slsw = require('serverless-webpack'); module.exports = async () => { const accountId = await slsw.lib.serverless.providers.aws.getAccountId(); return { entry: './handler.js', target: 'node', plugins: [ new webpack.DefinePlugin({ AWS_ACCOUNT_ID: `${accountId}`, }), ], module: { loaders: [ ... ] } }; }(); ``` ```js // Version with promises // webpack.config.js const webpack = require('webpack') const slsw = require('serverless-webpack'); const BbPromise = require('bluebird'); module.exports = BbPromise.try(() => { return slsw.lib.serverless.providers.aws.getAccountId() .then(accountId => ({ entry: './handler.js', target: 'node', plugins: [ new webpack.DefinePlugin({ AWS_ACCOUNT_ID: `${accountId}`, }), ], module: { loaders: [ ... ] } })); }; ``` ### serverless-webpack lib export helper serverless-webpack exposes a lib object, that can be used in your webpack.config.js to make the configuration easier and to build fully dynamic configurations. This is the preferred way to configure webpack - the plugin will take care of as much of the configuration (and subsequent changes in your services) as it can. #### Automatic entry resolution You can let the plugin determine the correct handler entry points at build time. Then you do not have to care anymore when you add or remove functions from your service: ```js // webpack.config.js const slsw = require('serverless-webpack'); module.exports = { ... entry: slsw.lib.entries, ... }; ``` Custom entries that are not part of the SLS build process can be added too: ```js // webpack.config.js const _ = require('lodash'); const slsw = require('serverless-webpack'); module.exports = { ... entry: _.assign({ myCustomEntry1: './custom/path/something.js' }, slsw.lib.entries), ... }; ``` #### Full customization (for experts) The lib export also provides the `serverless` and `options` properties, through which you can access the Serverless instance and the options given on the command-line. This enables you to have a fully customized dynamic configuration, that can evaluate anything available in the Serverless framework. There are really no limits. Samples are: The current stage and the complete service definition. You thereby have access to anything that a Serverless plugin would have access to. Both properties should be handled with care and should never be written to, as that will modify the running framework and leads to unpredictable behavior! If you have cool use cases with the full customization, we might add your solution to the plugin examples as showcase. #### Invocation state `lib.webpack` contains state variables that can be used to configure the build dynamically on a specific plugin state. ##### isLocal `lib.webpack.isLocal` is a boolean property that is set to true, if any known mechanism is used in the current Serverless invocation that runs code locally. This allows to set properties in the webpack configuration differently depending if the lambda code is run on the local machine or deployed. A sample is to set the compile mode with Webpack 4: ``` mode: slsw.lib.webpack.isLocal ? "development" : "production" ``` ### Output Note that, if the `output` configuration is not set, it will automatically be generated to write bundles in the `.webpack` directory. If you set your own `output` configuration make sure to add a [`libraryTarget`][link-webpack-libtarget] for best compatibility with external dependencies: ```js // webpack.config.js const path = require('path'); module.exports = { // ... output: { libraryTarget: 'commonjs', path: path.resolve(__dirname, '.webpack'), filename: '[name].js', }, // ... }; ``` ### Stats By default, the plugin will print a quite verbose bundle information to your console. However, if you are not satisfied with the current output info, you can overwrite it in your `webpack.config.js` ```js // webpack.config.js module.export = { // ... stats: 'minimal' // ... } ``` All the stats config can be found in [webpack's documentation][link-webpack-stats] ### Node modules / externals By default, the plugin will try to bundle all dependencies. However, you don't want to include all modules in some cases such as selectively import, excluding builtin package (ie: `aws-sdk`) and handling webpack-incompatible modules. In this case you might add external modules in [Webpack's `externals` configuration][link-webpack-externals]. Those modules can be included in the Serverless bundle with the `custom: webpack: includeModules` option in `serverless.yml`: ```js // webpack.config.js var nodeExternals = require('webpack-node-externals') module.exports = { // we use webpack-node-externals to excludes all node deps. // You can manually set the externals too. externals: [nodeExternals()], } ``` ```yaml # serverless.yml custom: webpack: includeModules: true # enable auto-packing of external modules ``` All modules stated in `externals` will be excluded from bundled files. If an excluded module is stated as `dependencies` in `package.json` and it is used by the webpack chunk, it will be packed into the Serverless artifact under the `node_modules` directory. By default, the plugin will use the `package.json` file in working directory, If you want to use a different package file, set `packagePath` to your custom `package.json`: ```yaml # serverless.yml custom: webpack: includeModules: packagePath: '../package.json' # relative path to custom package.json file. ``` > Note that only relative path is supported at the moment. #### Runtime dependencies If a runtime dependency is detected that is found in the `devDependencies` section and so would not be packaged, the plugin will error until you explicitly exclude it (see `forceExclude` below) or move it to the `dependencies` section. #### AWS-SDK An exception for the runtime dependency error is the AWS-SDK. All projects using the AWS-SDK normally have it listed in `devDependencies` because AWS provides it already in their Lambda environment. In this case the aws-sdk is automatically excluded and only an informational message is printed (in `--verbose` mode). The main reason for the warning is, that silently ignoring anything contradicts the declarative nature of Serverless' service definition. So the correct way to define the handling for the aws-sdk is, as you would do for all other excluded modules (see `forceExclude` below). ```yaml # serverless.yml custom: webpack: includeModules: forceExclude: - aws-sdk ``` #### Packagers You can select the packager that will be used to package your external modules. The packager can be set with the packager configuration. Currently it can be 'npm' or 'yarn' and defaults to using npm when not set. ```yaml # serverless.yml custom: webpack: packager: 'yarn' # Defaults to npm packagerOptions: {} # Optional, depending on the selected packager ``` You should select the packager, that you use to develop your projects, because only then locked versions will be handled correctly, i.e. the plugin uses the generated (and usually committed) package lock file that is created by your favorite packager. Each packager might support specific options that can be set in the `packagerOptions` configuration setting. For details see below. ##### NPM By default, the plugin uses NPM to package the external modules. However, if you use npm, you should use any version `<5.5 >=5.7.1` as the versions in-between have some nasty bugs. Right now there are no `packagerOptions` that can be set with NPM. ##### Yarn Using yarn will switch the whole packaging pipeline to use yarn, so does it use a `yarn.lock` file. The yarn packager supports the following `packagerOptions`: | Option | Type | Default | Description | |---------------|------|---------|-------------| | ignoreScripts | bool | true | Do not execute package.json hook scripts on install | ##### Common packager options There are some settings that are common to all packagers and affect the packaging itself. ###### Custom scripts You can specify custom scripts that are executed after the installation of the function/service packages has been finished. These are standard packager scripts as they can be used in any `package.json`. Warning: The use cases for them are very rare and specific and you should investigate first, if your use case can be covered with webpack plugins first. They should never access files outside of their current working directory which is the compiled function folder, if any. A valid use case would be to start anything available as binary from `node_modules`. ```yaml custom: webpack: packagerOptions: scripts: - npm rebuild grpc --target=6.1.0 --target_arch=x64 --target_platform=linux --target_libc=glibc ``` #### Forced inclusion Sometimes it might happen that you use dynamic requires in your code, i.e. you require modules that are only known at runtime. Webpack is not able to detect such externals and the compiled package will miss the needed dependencies. In such cases you can force the plugin to include certain modules by setting them in the `forceInclude` array property. However the module must appear in your service's production dependencies in `package.json`. ```yaml # serverless.yml custom: webpack: includeModules: forceInclude: - module1 - module2 ``` #### Forced exclusion You can forcefully exclude detected external modules, e.g. if you have a module in your dependencies that is already installed at your provider's environment. Just add them to the `forceExclude` array property and they will not be packaged. ```yaml # serverless.yml custom: webpack: includeModules: forceExclude: - module1 - module2 ``` If you specify a module in both arrays, `forceInclude` and `forceExclude`, the exclude wins and the module will not be packaged. #### Local modules You can use `file:` version references in your `package.json` to use a node module from a local folder (e.g. `"mymodule": "file:../../myOtherProject/mymodule"`). With that you can do test deployments from the local machine with different module versions or modules before they are published officially. #### Examples You can find an example setups in the [`examples`][link-examples] folder. #### Service level packaging If you do not enable individual packaging in your service (serverless.yml), the plugin creates one ZIP file for all functions (the service package) that includes all node modules used in the service. This is the fastest packaging, but not the optimal one, as node modules are always packaged, that are not needed by some functions. #### Optimization / Individual packaging per function A better way to do the packaging, is to enable individual packaging in your service: ```yaml # serverless.yml ... package: individually: true ... ``` This will switch the plugin to per function packaging which makes use of the multi-compiler feature of Webpack. That means, that Webpack compiles **and optimizes** each function individually, removing unnecessary imports and reducing code sizes significantly. Tree-Shaking only makes sense with this approach. Now the needed external node modules are also detected by Webpack per function and the plugin only packages the needed ones into the function artifacts. As a result, the deployed artifacts are smaller, depending on the functions and cold-start times (to install the functions into the cloud at runtime) are reduced too. The individual packaging will automatically apply the _automatic entry resolution_ (see above) and you will not be able to configure the entry config in webpack. An error will be thrown if you are trying to override the entry in webpack.config.js with other unsupported values. The individual packaging needs more time at the packaging phase, but you'll get that paid back twice at runtime. ## Usage ### Automatic bundling The normal Serverless deploy procedure will automatically bundle with Webpack: - Create the Serverless project with `serverless create -t aws-nodejs` - Install Serverless Webpack as above - Deploy with `serverless deploy` ### Run a function locally The plugin fully integrates with `serverless invoke local`. To run your bundled functions locally you can: ```bash $ serverless invoke local --function ``` All options that are supported by invoke local can be used as usual: - `--function` or `-f` (required) is the name of the function to run - `--path` or `-p` (optional) is a JSON file path used as the function input event - `--data` or `-d` (optional) inline JSON data used as the function input event > :exclamation: The old `webpack invoke` command has been disabled. #### Run a function with an existing compiled output (--no-build) On CI systems it is likely that you'll run multiple integration tests with `invoke local` sequentially. To improve this, you can do one compile and run multiple invokes on the compiled output - it is not necessary to compile again before each and every invoke. ```bash $ serverless webpack $ serverless invoke local --function --no-build $ serverless invoke local --function --no-build ... ``` ### Run a function locally on source changes Or to run a function every time the source files change use the `--watch` option together with `serverless invoke local`: ```bash $ serverless invoke local --function --path event.json --watch ``` Everytime the sources are changed, the function will be executed again with the changed sources. The command will watch until the process is terminated. If you have your sources located on a file system that does not offer events, you can enable polling with the `--webpack-use-polling=