Browse Source

Merge branch 'master' of https://github.com/cyyuen/serverless-webpack into cyyuen-master

master
Nicola Peduzzi 8 years ago
parent
commit
25f443caa5
  1. 38
      README.md
  2. 7
      examples/include-external-npm-packages/package.json
  3. 3
      examples/include-external-npm-packages/serverless.yml
  4. 4
      examples/include-external-npm-packages/webpack.config.js
  5. 7
      index.js
  6. 1
      lib/compile.js
  7. 91
      lib/packExternalModules.js

38
README.md

@ -67,26 +67,46 @@ module.exports = {
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 (aws-sdk) and handling webpack-incompatible modules. In this case,
you add all the modules, you want to exclude from bundled files, into `externals` field
of your `webpack.config.js` and add those, you want to include in final distribution,
into `serverless.yml`:
builtin package (ie: `aws-sdk`) and handling webpack-incompatible modules.
```javascript
In this case you might add external modules in
[Webpack `externals` configuration](https://webpack.github.io/docs/configuration.html#externals).
Those modules can be included in the Serverless bundle with the `webpackIncludeModules`
option in `serverless.yml`:
```js
// webpack.config.js
{
externals: ["module1", "module2"] // modules to be excluded from bundled file
var nodeExternals = require('webpack-node-externals')
modules.export = {
// we use webpack-node-externals to excludes all node deps.
// You can manually set the externals too.
externals: [nodeExternals()],
}
```
```yaml
# serverless.yml
custom:
webpackIncludeModules: 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`, 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 conf, set `packagePath` to your custom package.json. eg:
```yaml
# serverless.yml
custom:
webpackIncludeModules:
- module1 # modules to be included in distribution
packagePath: '../package.json' # relative path to custom package.json file.
```
> Note that only relative path is supported at the moment.
You can find an example setup in the [`examples`](./examples) folder.
You can find an example setups in the [`examples`](./examples) folder.
## Usage

7
examples/include-external-npm-packages/package.json

@ -10,10 +10,11 @@
"license": "MIT",
"devDependencies": {
"serverless-webpack": "^1.0.0-beta.2",
"webpack": "^1.13.1"
"webpack": "^1.13.1",
"webpack-node-externals": "^1.3.3",
"aws-sdk": "^2.5.3" // packages in devDependencies won't be included in distribution
},
"dependencies": {
"aws-sdk": "^2.5.3",
"dependencies": { // packages in dependencies will be included in distribution if required
"fbgraph": "^1.3.0"
}
}

3
examples/include-external-npm-packages/serverless.yml

@ -9,8 +9,7 @@ provider:
runtime: nodejs4.3
custom:
webpackIncludeModules: # modules to be included in distribution
- fbgraph
webpackIncludeModules: true # enable auto including modules
functions:
first:

4
examples/include-external-npm-packages/webpack.config.js

@ -1,7 +1,7 @@
var path = require('path');
var nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './handler.js',
target: 'node',
externals: ["fbgraph", "aws-sdk"] // modules to be excluded from bundled file
externals: [nodeExternals()] // exclude external modules
};

7
index.js

@ -7,7 +7,7 @@ const compile = require('./lib/compile');
const cleanup = require('./lib/cleanup');
const run = require('./lib/run');
const serve = require('./lib/serve');
const packExternalModules = require('./lib/packExternalModules')
const packExternalModules = require('./lib/packExternalModules');
class ServerlessWebpack {
constructor(serverless, options) {
@ -30,7 +30,6 @@ class ServerlessWebpack {
lifecycleEvents: [
'validate',
'compile',
'packExternalModules',
],
options: {
out: {
@ -102,9 +101,7 @@ class ServerlessWebpack {
.then(this.validate),
'webpack:compile': () => BbPromise.bind(this)
.then(this.compile),
'webpack:packExternalModules': () => BbPromise.bind(this)
.then(this.compile)
.then(this.packExternalModules),
'webpack:invoke:invoke': () => BbPromise.bind(this)

1
lib/compile.js

@ -12,6 +12,7 @@ module.exports = {
return BbPromise
.fromCallback(cb => compiler.run(cb))
.then(stats => {
this.serverless.cli.consoleLog(stats.toString({
colors: true,
hash: false,

91
lib/packExternalModules.js

@ -5,8 +5,69 @@ const fs = require('fs');
const path = require('path');
const npm = require('npm-programmatic');
function getProdModules(externalModules, packagePath) {
const packageJson = require(path.join(process.cwd(), packagePath));
const prodModules = [];
// only process the module stated in dependencies section
if (!packageJson.dependencies) {
return []
}
externalModules.forEach(module => {
const moduleVersion = packageJson.dependencies[module];
if (moduleVersion) {
prodModules.push(`${module}@${moduleVersion}`);
}
});
return prodModules;
}
function getExternalModuleName(module) {
const path = /^external "(.*)"$/.exec(module.identifier())[1];
const pathComponents = path.split('/');
const main = pathComponents[0];
// this is a package within a namespace
if (main.charAt(0) == '@') {
return `${main}/${pathComponents[1]}`
}
return main
}
function isExternalModule(module) {
return module.identifier().indexOf('external ') === 0;
}
function getExternalModules(stats) {
const externals = new Set();
stats.compilation.chunks.forEach(function(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:
if (isExternalModule(module)) {
externals.add(getExternalModuleName(module));
}
});
});
return Array.from(externals);
}
module.exports = {
packExternalModules() {
packExternalModules(stats) {
const includes = (
this.serverless.service.custom &&
@ -14,11 +75,23 @@ module.exports = {
);
return BbPromise.resolve().then(() => {
if (!includes || includes.length === 0) {
if (!includes) {
return;
}
this.serverless.cli.log('Packing external modules: ' + includes.join(","));
const packagePath = includes.packagePath || './package.json';
const externalModules = getExternalModules(stats);
// this plugin will only install modules stated in dependencies section of package.json
const prodModules = getProdModules(externalModules, packagePath);
if (prodModules.length === 0) {
return;
}
this.serverless.cli.log('Packing external modules: ' + prodModules.join(", "));
const tmpPackageJson = path.join(this.serverless.config.servicePath, 'package.json');
@ -26,17 +99,17 @@ module.exports = {
fs.writeFileSync(tmpPackageJson, "{}");
return new BbPromise((resolve, reject) => {
npm.install(includes, {
npm.install(prodModules, {
cwd: this.serverless.config.servicePath,
save: false
save: true
}).then(() => {
fs.unlink(tmpPackageJson);
// fs.unlink(tmpPackageJson);
resolve()
}).catch(e => {
fs.unlink(tmpPackageJson);
// fs.unlink(tmpPackageJson);
reject(e);
})
})
})
},
});
}
};

Loading…
Cancel
Save