├── examples └── aws-sdk-parts │ ├── lib │ └── bigFile.json │ ├── someDir1 │ ├── somedirFile.json │ └── someDir2 │ │ └── something.json │ ├── models │ └── index.js │ ├── package.json │ ├── users │ ├── list.js │ └── get.js │ ├── README.md │ └── serverless.yml ├── lib ├── validate.js ├── bundle.js └── configure.js ├── .gitignore ├── LICENSE ├── package.json ├── index.js └── README.md /examples/aws-sdk-parts/lib/bigFile.json: -------------------------------------------------------------------------------- 1 | { 2 | "I": "am really not big" 3 | } -------------------------------------------------------------------------------- /examples/aws-sdk-parts/someDir1/somedirFile.json: -------------------------------------------------------------------------------- 1 | { 2 | "someDir1": "file1" 3 | } -------------------------------------------------------------------------------- /examples/aws-sdk-parts/someDir1/someDir2/something.json: -------------------------------------------------------------------------------- 1 | { 2 | "someDir2": "file2" 3 | } -------------------------------------------------------------------------------- /examples/aws-sdk-parts/models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const deadEnd = function() { 4 | console.log('hi'); 5 | }; 6 | 7 | module.exports.deadEnd = deadEnd; -------------------------------------------------------------------------------- /examples/aws-sdk-parts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-sdk-parts-browserify-ex", 3 | "version": "0.0.1", 4 | "description": "Showcase bundling de-coupled aws-sdk-js services", 5 | "repository": { 6 | "url": "https://github.com/doapp-ryanp/serverless-browserify" 7 | }, 8 | "author": "Ryan Pendergast ", 9 | "license": "MIT", 10 | "dependencies": { 11 | "aws-sdk": "^2.6.12", 12 | "request": "^2.75.0", 13 | "rxjs": "^5.0.0-rc.1" 14 | }, 15 | "devDependencies": { 16 | "serverless-plugin-browserify": "^1.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/validate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports.validate = function() { 4 | if (process.env.SLS_DEBUG) { 5 | this.serverless.cli.log('SlsBrowserify::validate'); 6 | } 7 | 8 | if (!this.serverless.service.provider.runtime || -1 == this.serverless.service.provider.runtime.indexOf('nodejs')) { 9 | throw new this.serverless.classes.Error('Browserify plugin only works against nodejs runtimes'); 10 | } 11 | 12 | if (!this.serverless.service.package || !this.serverless.service.package.individually) { 13 | throw new this.serverless.classes.Error('Browserify plugin only works when packaging functions individually. package.individually must be true in serverless.yml', 'skip'); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /examples/aws-sdk-parts/users/list.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let S3 = require('aws-sdk/clients/s3'), 4 | bigFile = require('../lib/bigFile.json'), 5 | models = require('../models'); 6 | 7 | let s3 = new S3(); 8 | 9 | module.exports.hello = (event, context, callback) => { 10 | s3.getObject({ 11 | Bucket: 'yourbucket', 12 | Key: 'users.json', 13 | }, function(err, data) { 14 | if (err) { 15 | callback(err); 16 | } else { 17 | const response = { 18 | statusCode: 200, 19 | body: JSON.stringify({ 20 | message: 'Got users from S3', 21 | s3Body: JSON.parse(data.Body), 22 | input: event, 23 | }), 24 | }; 25 | 26 | console.log('I was not browserified!', bigFile); 27 | 28 | callback(null, response); 29 | } 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | dist 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | #IDE 25 | .idea 26 | .vscode 27 | 28 | #OS 29 | .DS_Store 30 | .tmp 31 | 32 | node_modules 33 | 34 | #SERVERLESS 35 | admin.env 36 | .serverless 37 | 38 | #angular2 39 | typings 40 | 41 | # Users Environment Variables 42 | .lock-wscript 43 | .tsdrc 44 | .typingsrc 45 | 46 | #IDE configuration files 47 | 48 | tools/**/*.js 49 | dev 50 | docs 51 | test 52 | tmp 53 | 54 | gulpfile.js 55 | gulpfile.js.map 56 | -------------------------------------------------------------------------------- /examples/aws-sdk-parts/README.md: -------------------------------------------------------------------------------- 1 | # AWS SDK Parts Example 2 | 3 | As of AWS SDK `v2.6.0` their monolithic code design has been decoupled into [individually usable service classes](https://github.com/aws/aws-sdk-js/issues/696#issuecomment-257350083). 4 | 5 | In addition to producing super small code sizes (with the help of browserify). This functionality will allow you to stay up to date with the most recent aws-sdk-js without paying a performance penalty. 6 | 7 | ## What does this example show me? 8 | 9 | That you can use the `serverless-plugin-browserify` to produce super small node code, bringing in only the modlues you use WITHOUT tons of configuration. 10 | 11 | This example also showcaes this plugin's integration with serverless `package.include/exclude`. 12 | 13 | ## Usage 14 | 15 | from `aws-sdk-parts` dir run `npm install`. Then run `env SLS_DEBUG=true sls browserify -f usersList`. I use [FishShell](https://fishshell.com), change this cmd for however your shell sets env vars. 16 | 17 | The output will tell you a directory where the bundled zip file was put. Extract it and inspect. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-plugin-browserify", 3 | "version": "1.1.3", 4 | "description": "Serverless v1.0 plugin that uses Browserify to bundle NodeJS Lambda functions.", 5 | "main": "index.js", 6 | "author": "Ryan Pendergast (http://rynop.com)", 7 | "contributors": [ 8 | "Ricardo Nolde " 9 | ], 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/doapp-ryanp/serverless-plugin-browserify.git" 13 | }, 14 | "keywords": [ 15 | "serverless", 16 | "1.0", 17 | "plugin", 18 | "browserify", 19 | "bundle" 20 | ], 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/doapp-ryanp/serverless-plugin-browserify/issues" 24 | }, 25 | "homepage": "https://github.com/doapp-ryanp/serverless-plugin-browserify#readme", 26 | "dependencies": { 27 | "archiver": "~1.1.0", 28 | "bluebird": "~3.4.6", 29 | "browserify": "~13.1.1", 30 | "fs-extra": "~0.30.0", 31 | "glob-all": "^3.1.0", 32 | "lodash.union": "4.6.0", 33 | "xtend": "~4.0.1" 34 | }, 35 | "devDependencies": {} 36 | } 37 | -------------------------------------------------------------------------------- /examples/aws-sdk-parts/users/get.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let Rx = require('rxjs/Rx'); 4 | let request = require('request'); 5 | 6 | var doGet = function(url) { 7 | return Rx.Observable.create(function(observer) { 8 | request( 9 | { 10 | method: 'GET', 11 | uri: url, 12 | gzip: true, 13 | }, function(error, response, body) { 14 | if (error) { 15 | observer.error(); 16 | } else if (response.statusCode != 200) { 17 | observer.error(response); 18 | } else { 19 | observer.next(response); 20 | } 21 | 22 | observer.complete(); 23 | }); 24 | }); 25 | }; 26 | 27 | var responseStream = doGet('https://gist.githubusercontent.com/doapp-ryanp/bdba55784d79c8a9118fcd2c45e21f49/raw/412326d4b135ad2e0b9082126dcdad146f39f595/test.json'); 28 | 29 | module.exports.hello = (event, context, callback) => { 30 | responseStream.subscribe( 31 | r => { 32 | const response = { 33 | statusCode: 200, 34 | body: JSON.stringify({ 35 | message: 'test multi module w exclude', 36 | httpBody: r, 37 | input: event, 38 | }), 39 | }; 40 | 41 | callback(null, response); 42 | }, 43 | error => { 44 | callback(error); 45 | } 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /examples/aws-sdk-parts/serverless.yml: -------------------------------------------------------------------------------- 1 | service: aws-sdk-parts-browserify-ex 2 | 3 | custom: 4 | dev: 5 | profile: browserify-ex 6 | prod: 7 | profile: browserify-ex 8 | # browserify: 9 | # disable: true 10 | 11 | package: 12 | individually: true 13 | include: 14 | - someDir1/** 15 | # exclude: 16 | # - excluded-by-default.json 17 | 18 | plugins: 19 | - serverless-plugin-browserify 20 | 21 | provider: 22 | name: aws 23 | runtime: nodejs4.3 24 | stage: dev 25 | region: us-east-1 26 | deploymentBucket: ${self:provider.stage}-useast1-slsdeploys.yourdomain.org 27 | profile: ${self:custom.${self:provider.stage}.profile} 28 | iamRoleStatements: 29 | - Effect: "Allow" 30 | Action: 31 | - "lambda:InvokeFunction" 32 | Resource: "*" 33 | - Effect: "Allow" 34 | Action: 35 | - "s3:G*" 36 | - "s3:L*" 37 | Resource: "*" 38 | 39 | functions: 40 | usersList: 41 | name: ${self:provider.stage}-${self:service}-usersList 42 | description: list users 43 | handler: users/list.hello 44 | memorySize: 512 45 | timeout: 10 46 | browserify: 47 | noParse: 48 | - "../lib/bigFile.json" #tell browserify to not parse, can't optimize, dont waste time 49 | 50 | usersGet: 51 | name: ${self:provider.stage}-${self:service}-usersGet 52 | description: get user 53 | handler: users/get.hello 54 | memorySize: 512 55 | timeout: 10 56 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BbPromise = require('bluebird'); 4 | 5 | const validate = require('./lib/validate'), 6 | configure = require('./lib/configure'), 7 | bundle = require('./lib/bundle'); 8 | 9 | class SlsBrowserify { 10 | constructor(serverless, options) { 11 | this.serverless = serverless; 12 | this.options = options; 13 | this.globalBrowserifyConfig = {}; 14 | 15 | Object.assign( 16 | this, 17 | validate, 18 | configure, 19 | bundle 20 | ); 21 | 22 | this.commands = { 23 | browserify: { 24 | usage: 'Bundle NodeJS lambda with Browserify', 25 | lifecycleEvents: [ 26 | 'validate', 27 | 'bundle', 28 | ], 29 | options: { 30 | out: { 31 | usage: 'Path to output directory', 32 | shortcut: 'o', 33 | }, 34 | function: { 35 | usage: 'Name of the function', 36 | shortcut: 'f', 37 | required: true, 38 | }, 39 | }, 40 | commands: {}, 41 | }, 42 | }; 43 | 44 | this.hooks = { 45 | //Handle `sls deploy` 46 | 'before:deploy:createDeploymentArtifacts': () => BbPromise.bind(this) 47 | .then(this.validate) 48 | .then(this.globalConfig) 49 | .then(() => { 50 | const functionNames = this.serverless.service.getAllFunctions(); 51 | const bundleQueue = functionNames.map(functionName => { 52 | return this.bundle(functionName); 53 | }); 54 | 55 | return BbPromise.all(bundleQueue); 56 | }) 57 | .catch(handleSkip), 58 | 59 | //Handle `sls deploy function` 60 | 'before:deploy:function:packageFunction': () => BbPromise.bind(this) 61 | .then(this.validate) 62 | .then(this.globalConfig) 63 | .then(() => this.bundle(this.options.function)) 64 | .catch(handleSkip), 65 | 66 | //Handle `sls browserify` 67 | 'browserify:validate': () => BbPromise.bind(this) 68 | .then(this.validate) 69 | .then(this.globalConfig) 70 | .then(() => this.bundle(this.options.function)) 71 | .catch(handleSkip), 72 | }; 73 | } 74 | } 75 | 76 | function handleSkip(e) { 77 | if ('skip' != e.statusCode) { //User explicitly chose to skip this function's browserification 78 | throw e; 79 | } else { 80 | this.serverless.cli.log(`WARNING: ${e.message} SKIPPING bundling`); 81 | } 82 | } 83 | 84 | module.exports = SlsBrowserify; 85 | -------------------------------------------------------------------------------- /lib/bundle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BbPromise = require('bluebird'), 4 | os = require('os'), 5 | browserify = require('browserify'), 6 | path = require('path'), 7 | fs = BbPromise.promisifyAll(require('fs-extra')), 8 | archiver = require('archiver'), 9 | glob = require('glob-all'); 10 | 11 | module.exports = { 12 | bundle(functionName) { 13 | let functionObject = this.serverless.service.getFunction(functionName); 14 | const outputDir = this.options.out || path.join(os.tmpdir(), functionName), 15 | functionBrowserifyConfig = this.getFunctionConfig(functionName), 16 | finalZipFilePath = path.resolve(path.join(outputDir, '..', `${functionName}.zip`)); 17 | 18 | let b = browserify(functionBrowserifyConfig); 19 | 20 | this.serverless.cli.log(`Bundling ${functionName} with Browserify...`); 21 | 22 | if (process.env.SLS_DEBUG) { 23 | this.serverless.cli.log(`Writing browserfied bundle to ${outputDir}`); 24 | } 25 | 26 | fs.emptyDirSync(outputDir); 27 | 28 | functionBrowserifyConfig.exclude.forEach(file => b.exclude(file)); 29 | functionBrowserifyConfig.ignore.forEach(file => b.ignore(file)); 30 | 31 | return new BbPromise((resolve, reject) => { 32 | let includeFiles = glob.sync(functionBrowserifyConfig.include, { 33 | cwd: this.serverless.config.servicePath, 34 | dot: true, 35 | silent: true, 36 | follow: true, 37 | }); 38 | 39 | if (process.env.SLS_DEBUG) { 40 | this.serverless.cli.log(`Copying includes: ` + includeFiles); 41 | } 42 | includeFiles.forEach((includeFile) => { 43 | fs.copySync(this.serverless.config.servicePath + path.sep + includeFile, outputDir + path.sep + includeFile); 44 | }); 45 | 46 | b.bundle((err, bundledBuf) => { 47 | if (err) { 48 | return reject(err); 49 | } 50 | 51 | const handlerPath = path.join(outputDir, functionObject.handler.split('.')[0] + '.js'); 52 | fs.mkdirsSync(path.dirname(handlerPath), '0777'); //handler may be in a subdir 53 | fs.writeFile(handlerPath, bundledBuf, (err) => { 54 | (err) ? reject(err) : resolve(); 55 | }); 56 | }); 57 | }) 58 | .then(() => { 59 | if (process.env.SLS_DEBUG) { 60 | this.serverless.cli.log(`Zipping ${outputDir} to ${finalZipFilePath}`); 61 | } 62 | 63 | return zipDir(outputDir, finalZipFilePath); 64 | }) 65 | .then((sizeBytes) => { 66 | const fileSizeInMegabytes = sizeBytes / 1000000.0; 67 | this.serverless.cli.log(`Created ${functionName}.zip (${Math.round(fileSizeInMegabytes * 100) / 100} MB)...`); 68 | 69 | if (!functionObject.package) { 70 | functionObject.package = {}; 71 | } 72 | 73 | //This is how we tell Serverless to not do any bunding or zipping 74 | //@see https://serverless.com/framework/docs/providers/aws/guide/packaging/#artifact 75 | functionObject.package.artifact = finalZipFilePath; 76 | }); 77 | } 78 | }; 79 | 80 | function zipDir(dirPath, destZipFilePath) { 81 | return new BbPromise((resolve, reject) => { 82 | let output = fs.createWriteStream(destZipFilePath); 83 | let archive = archiver.create('zip'); 84 | 85 | output.on('close', () => resolve(archive.pointer())); 86 | archive.on('error', (err) => reject(err)); 87 | 88 | archive.pipe(output); 89 | archive.directory(dirPath, ''); 90 | archive.finalize(); 91 | }); 92 | } 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serverless Browserify Plugin 2 | 3 | [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) 4 | 5 | A [Serverless](https://serverless.com) v1.0 plugin that uses [Browserify](https://github.com/substack/node-browserify) to bundle your NodeJS Lambda functions. 6 | 7 | **Why?** Lambda's with smaller code start and run faster. Lambda also has an account wide [deployment package size limit](http://docs.aws.amazon.com/lambda/latest/dg/limits.html). 8 | 9 | [aws-sdk-js](https://github.com/aws/aws-sdk-js) now officially [supports browserify](https://github.com/aws/aws-sdk-js/issues/696). Read more about why this kicks ass [on my blog](https://rynop.wordpress.com/2016/11/01/aws-sdk-for-javascript-now-fully-componentized/). 10 | 11 | With the example `package.json` and javascript code below, the default packaging for NodeJs lambdas in Serverless produces a zip file that is **11.3 MB**, because it blindly includes all of `node_modules` in the zip. 12 | 13 | This plugin with 2 lines of configuration produces a zip file that is **400KB!** 14 | 15 | ``` 16 | ... 17 | "dependencies": { 18 | "aws-sdk": "^2.6.12", 19 | "moment": "^2.15.2", 20 | "request": "^2.75.0", 21 | "rxjs": "^5.0.0-rc.1" 22 | }, 23 | ... 24 | ``` 25 | 26 | ```javascript 27 | const Rx = require('rxjs/Rx'); 28 | const request = require('request'); 29 | ... 30 | ``` 31 | 32 | ## Install 33 | 34 | From your serverless project run: 35 | ``` 36 | npm install serverless-plugin-browserify --save-dev 37 | ``` 38 | 39 | Add the plugin to your `serverless.yml` file and set `package.individually` to `true`: 40 | 41 | ```yaml 42 | plugins: 43 | - serverless-plugin-browserify 44 | package: 45 | individually: true 46 | ``` 47 | 48 | `package.individually` is required because it makes configuration more straight forward, and if you are not packaging individually size is not a concern of yours in the 1st place. 49 | 50 | ## Configure 51 | 52 | For most use cases you should **NOT** need to do any configuration. If you are a code ninja, read on. 53 | 54 | The base config for browserify is read from the `custom.browserify` section of `serverless.yml`. All [browserify options](https://github.com/substack/node-browserify#browserifyfiles--opts) are supported (most are auto configured by this plugin). This plugin adds one special option `disable` which if `true` will bypass this plugin. 55 | 56 | The base config can be over-ridden on a function by function basis. Again `custom.browserify` is not required and should not even need to be defined in most cases. 57 | 58 | ```yaml 59 | custom: 60 | browserify: 61 | #any option defined in https://github.com/substack/node-browserify#browserifyfiles--opts 62 | 63 | functions: 64 | usersGet: 65 | name: ${self:provider.stage}-${self:service}-pageGet 66 | description: get user 67 | handler: users/handler.hello 68 | browserify: 69 | noParse: 70 | - ./someBig.json #browserify can't optimize json, will take long time to parse for nothing 71 | ``` 72 | 73 | **Note:** `package.include` can be used with this plugin. All other options can be handled by leveraging [browserify options](https://github.com/substack/node-browserify#browserifyfiles--opts) in your `serverless.yml` custom `browserify` section. 74 | 75 | ## Usage 76 | 77 | When this plugin is enabled, and `package.individually` is `true`, running `serverless deploy` and `serverless deploy -f ` will automatically browserify your node lambda code. 78 | 79 | If you want to see output of bundled file or zip simply set `SLS_DEBUG`. Ex (using [Fish Shell](https://fishshell.com)): `env SLS_DEBUG=true sls deploy function -v -f usersGet` 80 | 81 | Also check out the [examples](./examples) directory 82 | 83 | ### Bundle only 84 | 85 | Run `serverless browserify -f `. You can optionally dictate where the bundling output dir is by using the `-o` flag. Ex: `sls browserify -o /tmp/test -f pageUpdate`. 86 | 87 | ## FAQ 88 | 89 | - **Should I use Webpack instead of this plugin?** I prefer Browserify over [webpack](https://webpack.github.io/) because I have found it supports more modules, optimizes better, and requires less configuration. 90 | - **Why is UglifyJS not built-in?** No ES6 support. [Issue](https://github.com/mishoo/UglifyJS2/issues/448) been open since 2014. 91 | - **My code is not bundling correctly** The bundled code is always stored in a tmp dir on your computer. Set `SLS_DEBUG=true` then re-run your command to output the directory. Fish Shell ex: `env SLS_DEBUG=true sls browserify` 92 | -------------------------------------------------------------------------------- /lib/configure.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const xtend = require('xtend'), 4 | union = require('lodash.union'); 5 | 6 | module.exports = { 7 | /** 8 | * Compute the base configuration 9 | */ 10 | globalConfig() { 11 | if (process.env.SLS_DEBUG) { 12 | this.serverless.cli.log('SlsBrowserify::globalConfig'); 13 | } 14 | 15 | const globalCustom = (this.serverless.service.custom && this.serverless.service.custom.browserify) || {}; 16 | 17 | if (globalCustom.disable) { 18 | throw new this.serverless.classes.Error('custom.browserify.disable is true in serverless.yml', 'skip'); 19 | } 20 | 21 | let globalDefault = { //Browserify plugin config 22 | disable: false, //Not an official option, used as internal option to skip browserify 23 | exclude: [], //Not an option, but will use for setting browserify.exclude() if defined in yml 24 | ignore: [], //Not an option, but will use for setting browserify.ignore() if defined in yml 25 | 26 | basedir: this.serverless.config.servicePath, 27 | entries: [], 28 | standalone: 'lambda', 29 | browserField: false, // Setup for node app (copy logic of --node in bin/args.js) 30 | builtins: false, 31 | commondir: false, 32 | ignoreMissing: true, // Do not fail on missing optional dependencies 33 | detectGlobals: true, // We don't care if its slower, we want more mods to work 34 | insertGlobalVars: { // Handle process https://github.com/substack/node-browserify/issues/1277 35 | //__filename: insertGlobals.lets.__filename, 36 | //__dirname: insertGlobals.lets.__dirname, 37 | process: function() { 38 | }, 39 | }, 40 | debug: false, 41 | }; 42 | 43 | //Merge in global config 44 | this.globalBrowserifyConfig = xtend(globalDefault, globalCustom); 45 | 46 | if (this.serverless.service.package) { 47 | //Merge together package.exclude and custom.browserify.exclude 48 | if (this.serverless.service.package.exclude && this.serverless.service.package.exclude.length) { 49 | this.globalBrowserifyConfig.exclude = union(this.serverless.service.package.exclude, this.globalBrowserifyConfig.exclude); 50 | } 51 | //Save service package.include 52 | if (this.serverless.service.package.include && this.serverless.service.package.include.length) { 53 | this.globalBrowserifyConfig.include = this.serverless.service.package.include; 54 | } 55 | } 56 | 57 | if (process.env.SLS_DEBUG) { 58 | console.log('computed globalBrowserifyConfig', this.globalBrowserifyConfig); 59 | } 60 | }, 61 | 62 | /** 63 | * Merge the global base configuration with given lambda function contextual configuration 64 | * 65 | * @param {string} functionName 66 | * @returns {*} 67 | */ 68 | getFunctionConfig(functionName) { 69 | const functionObject = this.serverless.service.getFunction(functionName); 70 | let functionBrowserifyConfig = xtend(this.globalBrowserifyConfig, functionObject.browserify || {}); 71 | 72 | if (functionBrowserifyConfig.disable) { 73 | throw new this.serverless.classes.Error('browserify.disable is true on this function in serverless.yml', 'skip'); 74 | } 75 | 76 | if (process.env.SLS_DEBUG) { 77 | console.log(`functionObject for ${functionName}`, functionObject); 78 | } 79 | 80 | if (!functionBrowserifyConfig.entries.length) { 81 | const bundleEntryPt = functionObject.handler.split('.')[0] + '.js'; 82 | functionBrowserifyConfig.entries = [bundleEntryPt]; 83 | } 84 | 85 | if (functionObject.package) { 86 | //Merge together functions.FUNCTION.package.exclude and browserify exclude 87 | if (functionObject.package.exclude && functionObject.package.exclude.length) { 88 | functionBrowserifyConfig.exclude = union(functionBrowserifyConfig.exclude, functionObject.package.exclude); 89 | } 90 | //Merge together service and function includes 91 | if (functionObject.package.include && functionObject.package.include.length) { 92 | functionBrowserifyConfig.include = union(functionBrowserifyConfig.include, functionObject.package.include); 93 | } 94 | } 95 | 96 | if (process.env.SLS_DEBUG) { 97 | console.log('computed function BrowserifyConfig', functionBrowserifyConfig); 98 | } 99 | 100 | return functionBrowserifyConfig; 101 | } 102 | }; 103 | --------------------------------------------------------------------------------