Repository: serverless-heaven/serverless-webpack (js)
Issue: Skip webpack on a per function basis
# This is a Feature Proposal

## Description

I have a use case where in the same project I need to mix javascript and python lambda functions. The use case is I have a custom cloudformation resource written in python which I want to deploy before I use it in the ```resources``` section.

I think it would be useful to be able to skip this plugin on a perfunction basis.

For example

```yaml
functions:
  pthon_func:
    runtime: python2.7
    webpack: false
```
Pull request description: Check for node runtimes first
webpack should not try to load handlers of different runtime than node.

<!--
1. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the PR
2. Please follow the template, otherwise we'll have to ask you to update it and it will take longer until your PR is merged
-->

## What did you implement:

Closes #255 or #256, #535 

<!--
Briefly describe the feature if no issue exists for this PR. If possible only
submit PRs for existing issues. If the PR is trivial (like doc changes or simple
code fixes) it can be submitted without a related issue, but as soon as it adds
or changes functionality, a related issue should be present.
-->

## How did you implement it:

<!--
If this is a nontrivial change please briefly describe your implementation so its easy for us to understand and review your code.
-->

## How can we verify it:

This config will work:
```yaml
provider:
  name: aws
  runtime: nodejs12.x 

functions:
  echo:
    handler: lambda.echo
    events:
      - http:
          path: /api/echo2
          method: any
  all:
    handler: backend.lambda.LambdaFunction
    runtime: java8
    events:
      - http:
          path: /api/v1/{api+}
          method: any     
```
<!--
Add any applicable config, commands, screenshots or other resources
to make it easy for us to verify this works. The easier you make it for us
to review a PR, the faster we can review and merge it.

Examples:
* Step by step description, how to verify
* Screenshots - Showing the difference between your output and the master
* Other - Anything else that comes to mind to help us evaluate
-->

## Todos:

- [ ] Write tests
- [ ] Write documentation
- [x] Fix linting errors
- [ ] Make sure code coverage hasn't dropped
- [x] Provide verification config / commands / resources
- [x] Enable "Allow edits from maintainers" for this PR
- [x] Update the messages below

***Is this ready for review?:*** YES
***Is it a breaking change?:*** NO


Patch:
diff --git a/lib/validate.js b/lib/validate.js
index 72d09b9..21fcafb 100644
--- a/lib/validate.js
+++ b/lib/validate.js
@@ -96,8 +96,12 @@ module.exports = {
       _.merge(entries, entry);
     } else {
       _.forEach(functions, (func, index) => {
-        const entry = getEntryForFunction.call(this, functions[index], this.serverless.service.getFunction(func));
-        _.merge(entries, entry);
+        const loadedFunc = this.serverless.service.getFunction(func);
+        const runtime = loadedFunc.runtime || this.serverless.service.provider.runtime;
+        if (runtime.match(/^node/)) {
+          const entry = getEntryForFunction.call(this, functions[index], loadedFunc);
+          _.merge(entries, entry);
+        }
       });
     }
 
@@ -145,11 +149,6 @@ module.exports = {
           filename: '[name].js'
         };
       }
-      
-      // Default node
-      if (!this.webpackConfig.node || _.isEmpty(this.webpackConfig.node)) {
-        this.webpackConfig.node = false;
-      }
 
       // Custom output path
       if (this.options.out) {


Test patch:
diff --git a/tests/validate.test.js b/tests/validate.test.js
index 96ae118..1ff9901 100644
--- a/tests/validate.test.js
+++ b/tests/validate.test.js
@@ -212,21 +212,6 @@ describe('validate', () => {
     });
   });
 
-  describe('default node', () => {
-    it('should turn NodeStuffPlugin and NodeSourcePlugin plugins off by default', () => {
-      const testEntry = 'testentry';
-      const testConfig = {
-        entry: testEntry,
-      };
-      const testServicePath = 'testpath';
-      module.serverless.config.servicePath = testServicePath;
-      _.set(module.serverless.service, 'custom.webpack.config', testConfig);
-      return module
-        .validate()
-        .then(() => expect(module.webpackConfig.node).to.eql(false));
-    });
-  });
-
   describe('config file load', () => {
     it('should load a webpack config from file if `custom.webpack` is a string', () => {
       const testConfig = 'testconfig';
@@ -422,7 +407,8 @@ describe('validate', () => {
                 path: 'func1path'
               }
             }
-          ]
+          ],
+          runtime: 'node10.x'
         },
         func2: {
           handler: 'module2.func2handler',
@@ -437,7 +423,8 @@ describe('validate', () => {
             {
               nonhttp: 'non-http'
             }
-          ]
+          ],
+          runtime: 'node10.x'
         },
         func3: {
           handler: 'handlers/func3/module2.func3handler',
@@ -446,7 +433,8 @@ describe('validate', () => {
             {
               nonhttp: 'non-http'
             }
-          ]
+          ],
+          runtime: 'node10.x'
         },
         func4: {
           handler: 'handlers/module2/func3/module2.func3handler',
@@ -455,7 +443,18 @@ describe('validate', () => {
             {
               nonhttp: 'non-http'
             }
-          ]
+          ],
+          runtime: 'node10.x'
+        },
+        func5: {
+          handler: 'com.serverless.Handler',
+          artifact: 'target/hello-dev.jar',
+          events: [
+            {
+              nonhttp: 'non-http'
+            }
+          ],
+          runtime: 'java8'
         }
       };
 
@@ -469,19 +468,24 @@ describe('validate', () => {
                 path: 'func1path'
               }
             }
-          ]
+          ],
+          runtime: 'node10.x'
         }
       };
 
-      it('should expose all functions if `options.function` is not defined', () => {
+      it('should expose all node functions if `options.function` is not defined', () => {
         const testOutPath = 'test';
         const testConfig = {
           entry: 'test',
           context: 'testcontext',
           output: {
             path: testOutPath
+          },
+          getFunction: func => {
+            return testFunctionsConfig[func];
           }
         };
+
         _.set(module.serverless.service, 'custom.webpack.config', testConfig);
         module.serverless.service.functions = testFunctionsConfig;
         globSyncStub.callsFake(filename => [_.replace(filename, '*', 'js')]);
@@ -894,4 +898,3 @@ describe('validate', () => {
     });
   });
 });
-