New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

serverless-webpack

Package Overview
Dependencies
Maintainers
2
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

serverless-webpack - npm Package Compare versions

Comparing version 2.2.0 to 3.0.0-rc.1

.eslintrc

85

index.js
'use strict';
const BbPromise = require('bluebird');
const _ = require('lodash');
const validate = require('./lib/validate');
const compile = require('./lib/compile');
const copyFunctionArtifact = require('./lib/copyFunctionArtifact');
const wpwatch = require('./lib/wpwatch');
const cleanup = require('./lib/cleanup');
const run = require('./lib/run');
const serve = require('./lib/serve');
const prepareLocalInvoke = require('./lib/prepareLocalInvoke');
const packExternalModules = require('./lib/packExternalModules');
const packageModules = require('./lib/packageModules');
const lib = require('./lib');

@@ -26,6 +27,4 @@

if (
this.serverless.service
&& this.serverless.service.custom
&& this.serverless.service.custom.webpack
&& this.serverless.service.custom.webpack.endsWith('.ts')
_.has(this.serverless, 'service.custom.webpack') &&
_.endsWith(this.serverless.service.custom.webpack, '.ts')
) {

@@ -35,12 +34,12 @@ require('ts-node/register');

Object.assign(
_.assign(
this,
validate,
compile,
copyFunctionArtifact,
wpwatch,
cleanup,
run,
serve,
packExternalModules
packExternalModules,
packageModules,
prepareLocalInvoke
);

@@ -67,13 +66,2 @@

],
options: {
function: {
usage: 'Name of the function',
shortcut: 'f',
required: true,
},
path: {
usage: 'Path to JSON file holding input data',
shortcut: 'p',
},
},
},

@@ -85,13 +73,2 @@ watch: {

],
options: {
function: {
usage: 'Name of the function',
shortcut: 'f',
required: true,
},
path: {
usage: 'Path to JSON file holding input data',
shortcut: 'p',
},
},
},

@@ -103,8 +80,2 @@ serve: {

],
options: {
port: {
usage: 'The local server port',
shortcut: 'p',
},
},
},

@@ -119,3 +90,4 @@ },

.then(this.compile)
.then(this.packExternalModules),
.then(this.packExternalModules)
.then(this.packageModules),

@@ -128,7 +100,18 @@ 'after:deploy:createDeploymentArtifacts': () => BbPromise.bind(this)

.then(this.compile)
.then(this.packExternalModules),
.then(this.packExternalModules)
.then(this.packageModules),
'after:deploy:function:packageFunction': () => BbPromise.bind(this)
.then(this.copyFunctionArtifact),
'before:invoke:local:invoke': () => BbPromise.bind(this)
.then(this.validate)
.then(this.compile)
.then(this.prepareLocalInvoke),
'after:invoke:local:invoke': () => BbPromise.bind(this)
.then(() => {
if (this.options.watch && !this.isWatching) {
return this.watch();
}
return BbPromise.resolve();
}),
'webpack:validate': () => BbPromise.bind(this)

@@ -139,17 +122,13 @@ .then(this.validate),

.then(this.compile)
.then(this.packExternalModules),
.then(this.packExternalModules)
.then(this.packageModules),
'webpack:invoke:invoke': () => BbPromise.bind(this)
.then(this.validate)
.then(this.compile)
.then(this.run)
.then(out => this.serverless.cli.consoleLog(out)),
.then(() => BbPromise.reject(new this.serverless.classes.Error('Use "serverless invoke local" instead.'))),
'webpack:watch:watch': () => BbPromise.bind(this)
.then(this.validate)
.then(this.watch),
.then(() => BbPromise.reject(new this.serverless.classes.Error('Use "serverless invoke local --watch" instead.'))),
'webpack:serve:serve': () => BbPromise.bind(this)
.then(this.validate)
.then(this.serve),
.then(() => BbPromise.reject(new this.serverless.classes.Error('serve has been removed. Use serverless-offline instead.'))),

@@ -160,3 +139,3 @@ 'before:offline:start': () => BbPromise.bind(this)

.then(this.wpwatch),
'before:offline:start:init': () => BbPromise.bind(this)

@@ -166,3 +145,3 @@ .then(this.validate)

.then(this.wpwatch),
};

@@ -169,0 +148,0 @@ }

'use strict';
const BbPromise = require('bluebird');
const path = require('path');
const fse = require('fs-extra');
const _ = require('lodash');

@@ -12,54 +10,10 @@ module.exports = {

const moveArtifact = new BbPromise((resolve, reject) => {
if (this.originalServicePath) {
this.serverless.config.servicePath = this.originalServicePath;
fse.copy(
path.join(webpackOutputPath, '.serverless'),
path.join(this.serverless.config.servicePath, '.serverless'),
(err) => {
if (err) {
reject(err);
} else {
if (this.serverless.service.package.individually) {
const functionNames = this.serverless.service.getAllFunctions();
this.options.verbose && this.serverless.cli.log(`Remove ${webpackOutputPath}`);
_.forEach(functionNames, name => {
const func = this.serverless.service.getFunction(name);
// The location of the artifact property changed from Serverless
// 1.17 to 1.18 (damn, the guys should use SemVer!). We have to
// use the new one if available here.
const artifactParent = func.artifact ? func : func.package;
if (this.serverless.utils.dirExistsSync(webpackOutputPath)) {
fse.removeSync(webpackOutputPath);
}
artifactParent.artifact = path.join(
this.serverless.config.servicePath,
'.serverless',
path.basename(artifactParent.artifact)
);
});
resolve();
return;
}
this.serverless.service.package.artifact = path.join(
this.serverless.config.servicePath,
'.serverless',
path.basename(this.serverless.service.package.artifact)
);
resolve();
}
}
);
} else {
resolve();
}
});
return moveArtifact
.then(() => {
if (this.serverless.utils.dirExistsSync(webpackOutputPath)) {
fse.removeSync(webpackOutputPath);
}
})
.then(() => BbPromise.resolve());
return BbPromise.resolve();
},
};
'use strict';
const _ = require('lodash');
const BbPromise = require('bluebird');

@@ -16,16 +17,26 @@ const webpack = require('webpack');

this.serverless.cli.consoleLog(stats.toString({
colors: true,
hash: false,
version: false,
chunks: false,
children: false
}));
if (stats.compilation.errors.length) {
throw new Error('Webpack compilation error, see above');
if (!this.multiCompile) {
stats = { stats: [stats] };
}
const outputPath = stats.compilation.compiler.outputPath;
this.webpackOutputPath = outputPath;
this.originalServicePath = this.serverless.config.servicePath;
this.serverless.config.servicePath = outputPath;
const compileOutputPaths = [];
_.forEach(stats.stats, compileStats => {
this.serverless.cli.consoleLog(compileStats.toString({
colors: true,
hash: false,
version: false,
chunks: false,
children: false
}));
if (compileStats.compilation.errors.length) {
throw new Error('Webpack compilation error, see above');
}
compileOutputPaths.push(compileStats.compilation.compiler.outputPath);
});
this.compileOutputPaths = compileOutputPaths;
return stats;

@@ -32,0 +43,0 @@ });

@@ -5,2 +5,2 @@ 'use strict';

entries: {}
}
};
'use strict';
const BbPromise = require('bluebird');
const fs = require('fs');
const _ = require('lodash');
const path = require('path');
const childProcess = require('child_process');
const fse = require('fs-extra');
const npm = require('npm-programmatic');
const isBuiltinModule = require('is-builtin-module');
function getProdModules(externalModules, packagePath) {
const packageJson = require(path.join(process.cwd(), packagePath));
function getProdModules(externalModules, packagePath, dependencyGraph) {
const packageJsonPath = path.join(process.cwd(), packagePath);
const packageJson = require(packageJsonPath);
const prodModules = [];

@@ -16,11 +18,19 @@

if (!packageJson.dependencies) {
return []
return [];
}
externalModules.forEach(module => {
// Get versions of all transient modules
_.forEach(externalModules, module => {
let moduleVersion = packageJson.dependencies[module.external];
const moduleVersion = packageJson.dependencies[module];
if (moduleVersion) {
prodModules.push(`${module}@${moduleVersion}`);
prodModules.push(`${module.external}@${moduleVersion}`);
} else if (!_.has(packageJson, `devDependencies.${module.external}`)) {
// Add transient dependencies if they appear not in the service's dev dependencies
const originInfo = _.get(dependencyGraph, `dependencies.${module.origin}`, {});
moduleVersion = _.get(originInfo, `dependencies.${module.external}.version`);
if (!moduleVersion) {
this.serverless.cli.log(`WARNING: Could not determine version of module ${module.external}`);
}
prodModules.push(moduleVersion ? `${module.external}@${moduleVersion}` : module.external);
}

@@ -33,8 +43,4 @@ });

function getExternalModuleName(module) {
const path = /^external "(.*)"$/.exec(module.identifier())[1];
const pathComponents = path.split('/');
const main = pathComponents[0];

@@ -44,22 +50,35 @@

if (main.charAt(0) == '@') {
return `${main}/${pathComponents[1]}`
return `${main}/${pathComponents[1]}`;
}
return main
return main;
}
function isExternalModule(module) {
return module.identifier().indexOf('external ') === 0;
return _.startsWith(module.identifier(), 'external ') && !isBuiltinModule(getExternalModuleName(module));
}
/**
* Find the original module that required the transient dependency. Returns
* undefined if the module is a first level dependency.
* @param {Object} issuer - Module issuer
*/
function findExternalOrigin(issuer) {
if (!_.isNil(issuer) && _.startsWith(issuer.rawRequest, './')) {
return findExternalOrigin(issuer.issuer);
}
return issuer;
}
function getExternalModules(stats) {
const externals = new Set();
stats.compilation.chunks.forEach(function(chunk) {
_.forEach(stats.compilation.chunks, chunk => {
// Explore each module within the chunk (built inputs):
chunk.modules.forEach(function(module) {
// Explore each source file path that was included into the module:
_.forEach(chunk.modules, module => {
if (isExternalModule(module)) {
externals.add(getExternalModuleName(module));
externals.add({
origin: _.get(findExternalOrigin(module.issuer), 'rawRequest'),
external: getExternalModuleName(module)
});
}

@@ -73,2 +92,15 @@ });

module.exports = {
/**
* We need a performant algorithm to install the packages for each single
* function (in case we package individually).
* (1) We fetch ALL packages needed by ALL functions in a first step
* and use this as a base npm checkout. The checkout will be done to a
* separate temporary directory with a package.json that contains everything.
* (2) For each single compile we copy the whole node_modules to the compile
* directory and create a (function) compile specific package.json and store
* it in the compile directory. Now we start npm again there, and npm will just
* remove the superfluous packages and optimize the remaining dependencies.
* This will utilize the npm cache at its best and give us the needed results
* and performance.
*/
packExternalModules(stats) {

@@ -81,40 +113,89 @@

return BbPromise.resolve().then(() => {
if (!includes) {
return BbPromise.resolve(stats);
}
if (!includes) {
return;
}
const packagePath = includes.packagePath || './package.json';
const packageJsonPath = path.join(process.cwd(), packagePath);
const packagePath = includes.packagePath || './package.json';
this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJsonPath}`);
// Get first level dependency graph
const command = 'npm ls -prod -json -depth=1'; // Only prod dependencies
let dependencyGraph = {};
try {
const depJson = childProcess.execSync(command, {
cwd: path.dirname(packageJsonPath),
maxBuffer: this.serverless.service.custom.packExternalModulesMaxBuffer || 200 * 1024,
encoding: 'utf8'
});
dependencyGraph = JSON.parse(depJson);
} catch (e) {
// We rethrow here. It's not recoverable.
throw e;
}
const externalModules = getExternalModules(stats);
// (1) Generate dependency composition
const compositeModules = _.uniq(_.flatMap(stats.stats, compileStats => {
const externalModules = getExternalModules.call(this, compileStats);
return getProdModules.call(this, externalModules, packagePath, dependencyGraph);
}));
// this plugin will only install modules stated in dependencies section of package.json
const prodModules = getProdModules(externalModules, packagePath);
// (1.a) Install all needed modules
const compositeModulePath = path.join(this.webpackOutputPath, 'dependencies');
const compositePackageJson = path.join(compositeModulePath, 'package.json');
this.serverless.utils.writeFileSync(compositePackageJson, '{}');
if (prodModules.length === 0) {
return;
}
this.serverless.cli.log('Packing external modules: ' + compositeModules.join(', '));
this.serverless.cli.log('Packing external modules: ' + prodModules.join(", "));
return new BbPromise((resolve, reject) => {
const start = _.now();
npm.install(compositeModules, {
cwd: compositeModulePath,
maxBuffer: this.serverless.service.custom.packExternalModulesMaxBuffer || 200 * 1024,
save: true
}).then(() => {
this.options.verbose && this.serverless.cli.log(`Package took [${_.now() - start} ms]`); // eslint-disable-line promise/always-return
resolve(stats.stats);
}).catch(e => {
reject(e);
});
})
.mapSeries(compileStats => {
const modulePath = compileStats.compilation.compiler.outputPath;
const tmpPackageJson = path.join(this.serverless.config.servicePath, 'package.json');
// create a temp package.json in dist directory so that we can install the dependencies later.
fs.writeFileSync(tmpPackageJson, "{}");
// Create package.json
const modulePackageJson = path.join(modulePath, 'package.json');
const modulePackage = {
dependencies: {}
};
const prodModules = getProdModules.call(this, getExternalModules.call(this, compileStats), packagePath, dependencyGraph);
_.forEach(prodModules, prodModule => {
const splitModule = _.split(prodModule, '@');
// If we have a scoped module we have to re-add the @
if (_.startsWith(prodModule, '@')) {
splitModule.splice(0, 1);
splitModule[0] = '@' + splitModule[0];
}
const moduleVersion = _.join(_.tail(splitModule), '@');
modulePackage.dependencies[_.first(splitModule)] = moduleVersion;
});
this.serverless.utils.writeFileSync(modulePackageJson, JSON.stringify(modulePackage, null, 2));
return new BbPromise((resolve, reject) => {
npm.install(prodModules, {
cwd: this.serverless.config.servicePath,
save: true
}).then(() => {
// fs.unlink(tmpPackageJson);
resolve()
}).catch(e => {
// fs.unlink(tmpPackageJson);
reject(e);
// Copy modules
const startCopy = _.now();
return BbPromise.fromCallback(callback => fse.copy(path.join(compositeModulePath, 'node_modules'), path.join(modulePath, 'node_modules'), callback))
.tap(() => this.options.verbose && this.serverless.cli.log(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`))
.then(() => {
// Prune extraneous packages - removes not needed ones
const startPrune = _.now();
return BbPromise.fromCallback(callback => {
childProcess.exec('npm prune', {
cwd: modulePath
}, callback);
})
})
});
.tap(() => this.options.verbose && this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`));
});
})
.return(stats);
}
};

@@ -9,71 +9,2 @@ 'use strict';

module.exports = {
loadHandler(stats, functionId, purge) {
const handler = this.serverless.service.functions[functionId].handler.split('.');
const moduleFileName = `${handler[0]}.js`;
const handlerFilePath = path.join(
path.resolve(stats.compilation.options.output.path),
moduleFileName
);
if (purge) {
utils.purgeCache(handlerFilePath);
}
//set environment before requiring, as imported modules will be immediately
this.setEnvironmentVars(functionId);
const module = require(handlerFilePath);
const functionObjectPath = handler.slice(1);
let func = module;
for (let p of functionObjectPath) {
func = func[p];
}
return func;
},
getEvent() {
return this.options.path
? this.serverless.utils.readFileSync(this.options.path)
: null; // TODO use get-stdin instead
},
getContext(functionName) {
return {
awsRequestId: utils.guid(),
invokeid: utils.guid(),
logGroupName: `/aws/lambda/${functionName}`,
logStreamName: '2016/02/14/[HEAD]13370a84ca4ed8b77c427af260',
functionVersion: '$LATEST',
isDefaultFunctionVersion: true,
functionName: functionName,
memoryLimitInMB: '1024',
};
},
setEnvironmentVars(functionName) {
const providerEnvVars = this.serverless.service.provider.environment || {};
const functionEnvVars = this.serverless.service.functions[functionName].environment || {};
Object.assign(process.env, providerEnvVars, functionEnvVars);
},
run(stats) {
const functionName = this.options.function;
this.serverless.cli.log(`Run function ${functionName}...`);
const handler = this.loadHandler(stats, functionName);
const event = this.getEvent();
const context = this.getContext(functionName);
return new BbPromise((resolve, reject) => handler(
event,
context,
(err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
}
}
));
},
watch() {

@@ -89,22 +20,20 @@ const functionName = this.options.function;

}
this.serverless.cli.log(`Run function ${functionName}...`);
const handler = this.loadHandler(stats, functionName, true);
const event = this.getEvent();
const context = this.getContext(functionName);
handler(
event,
context,
(err, res) => {
if (err) {
throw err;
} else {
this.serverless.cli.consoleLog(res);
}
BbPromise.try(() => {
if (this.originalServicePath) {
process.chdir(this.originalServicePath);
this.serverless.config.servicePath = this.originalServicePath;
}
)
if (!this.isWatching) {
this.isWatching = true;
return BbPromise.resolve();
}
this.serverless.cli.log('Sources changed.');
return this.serverless.pluginManager.spawn('invoke:local');
})
.then(() => this.serverless.cli.log('Waiting for changes ...'));
});
return BbPromise.resolve();
},
};

@@ -49,3 +49,3 @@ 'use strict';

return path.extname(_.first(sortedFiles));
}
};

@@ -70,7 +70,8 @@ const getEntryForFunction = serverlessFunction => {

// Expose entries - must be done before requiring the webpack configuration
// Expose entries - must be done before requiring the webpack configuration
const entries = {};
const functions = this.serverless.service.getAllFunctions();
if (this.options.function) {
const serverlessFunction = this.serverless.service.getFunction(this.options.function);
const serverlessFunction = this.serverless.service.getFunction(this.options.function);
const entry = getEntryForFunction(serverlessFunction);

@@ -84,3 +85,2 @@ _.merge(entries, entry);

}
lib.entries = entries;

@@ -90,2 +90,3 @@ // Expose service file and options

lib.options = this.options;
lib.entries = entries;

@@ -107,14 +108,8 @@ if (_.isString(this.webpackConfig)) {

// Default output
if (!this.webpackConfig.output) {
if (!this.webpackConfig.output || _.isEmpty(this.webpackConfig.output)) {
const outputPath = path.join(this.serverless.config.servicePath, '.webpack');
const outputFilename = path.basename(
_.isArray(this.webpackConfig.entry)
&& this.webpackConfig.entry[this.webpackConfig.entry.length - 1]
|| this.webpackConfig.entry
|| 'handler.js'
);
this.webpackConfig.output = {
libraryTarget: 'commonjs',
path: outputPath,
filename: outputFilename,
filename: '[name].js',
};

@@ -129,5 +124,51 @@ }

fse.removeSync(this.webpackConfig.output.path);
this.webpackOutputPath = this.webpackConfig.output.path;
// In case of individual packaging we have to create a separate config for each function
if (_.has(this.serverless, 'service.package') && this.serverless.service.package.individually) {
this.options.verbose && this.serverless.cli.log('Using multi-compile (individual packaging)');
this.multiCompile = true;
// Lookup associated Serverless functions
const allEntryFunctions = _.map(
this.serverless.service.getAllFunctions(),
funcName => {
const func = this.serverless.service.getFunction(funcName);
const handler = func.handler;
const handlerFile = path.relative('.', /(.*)\..*?$/.exec(handler)[1]);
return {
handlerFile,
funcName,
func
};
}
);
this.entryFunctions = _.map(this.webpackConfig.entry, (value, key) => {
const entry = path.relative('.', value);
const entryFile = _.replace(entry, new RegExp(`${path.extname(entry)}$`), '');
const entryFunc = _.find(allEntryFunctions, [ 'handlerFile', entryFile ]) || {};
entryFunc.entry = {
key,
value
};
return entryFunc;
});
this.webpackConfig = _.map(this.entryFunctions, entryFunc => {
const config = _.cloneDeep(this.webpackConfig);
config.entry = {
[entryFunc.entry.key]: entryFunc.entry.value
};
const compileName = entryFunc.funcName || _.camelCase(entryFunc.entry.key);
config.output.path = path.join(config.output.path, compileName);
return config;
});
} else {
this.webpackConfig.output.path = path.join(this.webpackConfig.output.path, 'service');
}
return BbPromise.resolve();
},
};
{
"name": "serverless-webpack",
"version": "2.2.0",
"version": "3.0.0-rc.1",
"description": "Serverless plugin to bundle your javascript with Webpack",

@@ -30,14 +30,20 @@ "main": "index.js",

"dependencies": {
"archiver": "^2.0.0",
"bluebird": "^3.4.0",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"fs-extra": "^0.26.7",
"glob": "^7.1.2",
"is-builtin-module": "^1.0.0",
"lodash": "^4.17.4",
"npm-programmatic": "0.0.5",
"npm-programmatic": "^0.0.7",
"semver": "^5.4.1",
"ts-node": "^3.2.0"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"chai": "^4.1.0",
"chai-as-promised": "^7.1.1",
"eslint": "^4.3.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-lodash": "^2.4.4",
"eslint-plugin-promise": "^3.5.0",
"istanbul": "^0.4.5",

@@ -44,0 +50,0 @@ "mocha": "^3.4.2",

@@ -12,7 +12,26 @@ # Serverless 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];
try your lambda functions locally and much more!
use custom [resource loaders][link-webpack-loaders], optimize your packaged functions individually
and much more!
> **BREAKING CHANGE IN v2**: `webpack` must now be installed alongside `serverless-webpack` as a peer dependency. This allows more control over which version of Webpack to run.
## 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`
* 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.
## New in V3
* Support for individual packaging and optimization
* Integrate with `serverless invoke local` (including watch mode)
* Stabilized package handling
* Improved compatibility with other plugins
* Updated examples
For the complete release notes see the end of this document.
## Install

@@ -59,2 +78,4 @@

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.

@@ -159,2 +180,3 @@ #### Automatic entry resolution

All modules stated in `externals` will be excluded from bundled files. If an excluded module

@@ -177,2 +199,39 @@ is stated as `dependencies` in `package.json`, it will be packed into the Serverless

#### 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 should be combined with the _automatic entry resolution_ (see above).
The individual packaging needs more time at the packaging phase, but you'll
get that paid back twice at runtime.
## Usage

@@ -188,2 +247,39 @@

### 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 <function-name>
```
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 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 <function-name> --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.
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 watch` command has been disabled.
### Usage with serverless-offline

@@ -234,28 +330,2 @@

### Run a function locally
To run your bundled functions locally you can:
```bash
$ serverless webpack invoke --function <function-name>
```
Options are:
- `--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
### Run a function locally on source changes
Or to run a function every time the source files change use `watch`:
```bash
$ serverless webpack watch --function <function-name> --path event.json
```
Options are:
- `--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
### Bundle with webpack

@@ -275,32 +345,5 @@

_The integrated simulation functionality will be removed in version 3 in favor of
using `serverless-offline` (see [#135][link-135]) which already does the job
perfectly and fully integrates with `serverless-webpack`.
Please switch to `serverless-offline` if you do not use it already._
:exclamation: The serve command has been removed. See above how to achieve the
same functionality with the [`serverless-offline`][link-serverless-offline] plugin.
To start a local server that will act like API Gateway, use the following command.
Your code will be reloaded upon change so that every request to your local server
will serve the latest code.
```bash
$ serverless webpack serve
```
Options are:
- `--port` or `-p` (optional) The local server port. Defaults to `8000`
The `serve` command will automatically look for the local `serverless.yml` and serve
all the `http` events. For example this configuration will generate a GET endpoint:
```yaml
functions:
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
```
## Example with Babel

@@ -312,3 +355,3 @@

- `npm install` to install dependencies
- `serverless webpack run -f hello` to run the example function
- `serverless invoke local -f hello` to run the example function

@@ -319,11 +362,22 @@ ## Provider Support

| | AWS Lambda | Apache OpenWhisk | Azure Functions | Google Cloud Functions |
|----------------|------------|------------------|-----------------|------------------------|
| webpack | ✔︎ | ✔︎ | ⁇ | ⁇ |
| webpack invoke | ✔︎ | ✘ | ⁇ | ⁇ |
| webpack watch | ✔︎ | ✔︎ | ⁇ | ⁇ |
| webpack serve | ✔︎ | ✘ | ⁇ | ⁇ |
| | AWS Lambda | Apache OpenWhisk | Azure Functions | Google Cloud Functions |
|-----------------------|------------|------------------|-----------------|------------------------|
| webpack | ✔︎ | ✔︎ | ⁇ | ⁇ |
| invoke local | ✔︎ | ⁇ | ⁇ | ⁇ |
| invoke local --watch | ✔︎ | ⁇ | ⁇ | ⁇ |
## Release Notes
* 3.0.0
* Integrate with `serverless invoke local` [#151][link-151]
* Support watch mode with `serverless invoke local --watch`
* Stabilized and improved the bundling of node modules [#116][link-116], [#117][link-117]
* Improved interoperability with Serverless and 3rd party plugins [#173][link-173]
* Support individual packaging of the functions in a service [#120][link-120]
* Allow setting stdio max buffers for NPM operations [#185][link-185]
* Support bundling of node modules via node-externals whitelist [#186][link-186]
* Removed the `webpack serve` command in favor of [`serverless-offline`][link-serverless-offline] [#152][link-152]
* Updated examples [#179][link-179]
* Added missing unit tests to improve code stability
* 2.2.0

@@ -362,2 +416,3 @@ * Allow full dynamic configurations [#158][link-158]

[link-webpack-libtarget]: https://webpack.github.io/docs/configuration.html#output-librarytarget
[link-webpack-tree]: https://webpack.js.org/guides/tree-shaking/
[link-webpack-externals]: https://webpack.github.io/docs/configuration.html#externals

@@ -389,1 +444,11 @@ [link-examples]: ./examples

[link-165]: https://github.com/elastic-coders/serverless-webpack/issues/165
[link-116]: https://github.com/elastic-coders/serverless-webpack/issues/116
[link-117]: https://github.com/elastic-coders/serverless-webpack/issues/117
[link-120]: https://github.com/elastic-coders/serverless-webpack/issues/120
[link-151]: https://github.com/elastic-coders/serverless-webpack/issues/151
[link-152]: https://github.com/elastic-coders/serverless-webpack/issues/152
[link-173]: https://github.com/elastic-coders/serverless-webpack/issues/173
[link-179]: https://github.com/elastic-coders/serverless-webpack/pull/179
[link-185]: https://github.com/elastic-coders/serverless-webpack/pull/185
[link-186]: https://github.com/elastic-coders/serverless-webpack/pull/186
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc