Skip to content

Commit e61776b

Browse files
author
sw-yx
committed
update docs and some warnings
1 parent 046f413 commit e61776b

File tree

5 files changed

+1449
-1041
lines changed

5 files changed

+1449
-1041
lines changed

README.md

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ The goal is to make it easy to write Lambda's with transpiled JS/Typescipt featu
66

77
## Installation
88

9-
**We recommend installing locally** rather than globally:
9+
**We recommend installing locally** rather than globally:
1010

1111
```bash
1212
yarn add -D netlify-lambda
1313
```
1414

1515
This will ensure your build scripts don't assume a global install which is better for your CI/CD (for example with Netlify's buildbot).
1616

17-
If you don't have a [`netlify.toml`](https://www.netlify.com/docs/netlify-toml-reference/) file, you'll need one ([example](https://github.com/netlify/create-react-app-lambda/blob/master/netlify.toml)). Define the `functions` field where the functions will be built to and served from, e.g.
17+
If you don't have a [`netlify.toml`](https://www.netlify.com/docs/netlify-toml-reference/) file, you'll need one ([example](https://github.com/netlify/create-react-app-lambda/blob/master/netlify.toml)). Define the `functions` field where the functions will be built to and served from, e.g.
1818

1919
```toml
2020
# example netlify.toml
@@ -45,12 +45,22 @@ folder/hello.js -> http://localhost:9000/.netlify/functions/hello
4545

4646
It also watches your files and restarts the dev server on change. Note: if you add a new file you should kill and restart the process to pick up the new file.
4747

48-
**IMPORTANT**:
48+
**IMPORTANT**:
4949

5050
- You need a [`netlify.toml`](https://www.netlify.com/docs/netlify-toml-reference/) file with a `functions` field.
5151
- Every function needs to be a top-level js/ts/mjs file. You can have subfolders inside the `netlify-lambda` folder, but those are only for supporting files to be imported by your top level function.
5252
- Function signatures follow the [AWS event handler](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) syntax but must be named `handler`. [We use Node v8](https://www.netlify.com/blog/2018/04/03/node.js-8.10-now-available-in-netlify-functions/) so `async` functions **are** supported ([beware common mistakes](https://serverless.com/blog/common-node8-mistakes-in-lambda/)!). Read [Netlify Functions docs](https://www.netlify.com/docs/functions/#javascript-lambda-functions) for more info.
5353

54+
<details>
55+
<summary><b>Environment variables in build and branch contextx</b>
56+
57+
Read Netlify's [documentation on environment variables](https://www.netlify.com/docs/continuous-deployment/#build-environment-variables).
58+
`netlify-lambda` should respect the env variables you supply in `netlify.toml` accordingly (except for deploy previews, which make no sense to locally emulate).
59+
60+
However, this is a [relatively new feature](https://github.com/netlify/netlify-lambda/issues/59), so if you encounter issues, file one.
61+
62+
</details>
63+
5464
## Using with `create-react-app`, Gatsby, and other development servers
5565

5666
`react-scripts` (the underlying library for `create-react-app`) and other popular development servers often set up catchall serving for you; in other words, if you try to request a route that doesn't exist, the dev server will try to serve you `/index.html`. This is problematic when you are trying to hit a local API endpoint like `netlify-lambda` sets up for you - your browser will attempt to parse the `index.html` file as JSON. This is why you may see this error:
@@ -67,7 +77,7 @@ When your function is deployed on Netlify, it will be available at `/.netlify/fu
6777

6878
Say you are running `webpack-serve` on port 8080 and `netlify-lambda serve` on port 9000. Mounting `localhost:9000` to `/.netlify/functions/` on your `webpack-serve` server (`localhost:8080/.netlify/functions/`) will closely replicate what the final production environment will look like during development, and will allow you to assume the same function url path in development and in production.
6979

70-
- If you are using with `create-react-app`, see [netlify/create-react-app-lambda](https://github.com/netlify/create-react-app-lambda/blob/f0e94f1d5a42992a2b894bfeae5b8c039a177dd9/src/setupProxy.js) for an example of how to do this with `create-react-app`. [setupProxy is partially documented in the CRA docs](https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development#configuring-the-proxy-manually). You can also learn how to do this from scratch in a video: https://www.youtube.com/watch?v=3ldSM98nCHI
80+
- If you are using with `create-react-app`, see [netlify/create-react-app-lambda](https://github.com/netlify/create-react-app-lambda/blob/f0e94f1d5a42992a2b894bfeae5b8c039a177dd9/src/setupProxy.js) for an example of how to do this with `create-react-app`. [setupProxy is partially documented in the CRA docs](https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development#configuring-the-proxy-manually). You can also learn how to do this from scratch in a video: https://www.youtube.com/watch?v=3ldSM98nCHI
7181
- If you are using Gatsby, see [their Advanced Proxying docs](https://www.gatsbyjs.org/docs/api-proxy/#advanced-proxying). This is implemented in the [JAMstack Hackathon Starter](https://github.com/sw-yx/jamstack-hackathon-starter), and here is an accompanying blogpost: [Turning the Static Dynamic: Gatsby + Netlify Functions + Netlify Identity](https://www.gatsbyjs.org/blog/2018-12-17-turning-the-static-dynamic/).
7282
- If you are using Next.js, see [this issue for how to proxy](https://github.com/netlify/netlify-lambda/pull/28#issuecomment-439675503).
7383
- If you are using Vue CLI, you may just use https://github.com/netlify/vue-cli-plugin-netlify-lambda/.
@@ -77,12 +87,12 @@ Say you are running `webpack-serve` on port 8080 and `netlify-lambda serve` on p
7787

7888
```js
7989
module.exports = {
80-
mode: "development",
90+
mode: 'development',
8191
devServer: {
8292
proxy: {
83-
"/.netlify": {
84-
target: "http://localhost:9000",
85-
pathRewrite: { "^/.netlify/functions": "" }
93+
'/.netlify': {
94+
target: 'http://localhost:9000',
95+
pathRewrite: { '^/.netlify/functions': '' }
8696
}
8797
}
8898
}
@@ -99,7 +109,7 @@ CORS issues when trying to use netlify-lambdas locally with angular? you need to
99109
Firstly make sure you are using relative paths in your app to ensure that your app will work locally and on Netlify, example below...
100110

101111
```js
102-
this.http.get('/.netlify/functions/jokeTypescript')
112+
this.http.get('/.netlify/functions/jokeTypescript');
103113
```
104114

105115
Then place a `proxy.config.json` file in the root of your project, the contents should look something like...
@@ -136,6 +146,7 @@ To make your life easier you can add these to your `scripts` in `package.json`
136146
```
137147

138148
Obviously you need to run up `netlify-lambda` & `angular` at the same time.
149+
139150
</details>
140151

141152
## Webpack Configuration
@@ -204,6 +215,10 @@ There are additional CLI options:
204215
-s --static
205216
```
206217

218+
### --config option
219+
220+
If you need to use additional webpack modules or loaders, you can specify an additional webpack config with the `-c`/`--config` option when running either `serve` or `build`.
221+
207222
### --port option
208223

209224
The serving port can be changed with the `-p`/`--port` option.
@@ -212,24 +227,24 @@ The serving port can be changed with the `-p`/`--port` option.
212227

213228
If you need an escape hatch and are building your lambda in some way that is incompatible with our build process, you can skip the build with the `-s` or `--static` flag. [More info here](https://github.com/netlify/netlify-lambda/pull/62).
214229

215-
## Debugging
230+
## Netlify Identity
216231

217-
To debug lambdas, prepend the `serve` command with [npm's package runner npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) `npx --node-arg=--inspect netlify-lambda serve ...`. Additionally:
232+
Make sure to [read the docs](https://www.netlify.com/docs/functions/#identity-and-functions) on how Netlify Functions and Netlify Identity work together. Basically you have to make your request with an `authorization` header and a `Bearer` token with your Netlify Identity JWT supplied. You can get this JWT from any of our Identity solutions from [gotrue-js](https://github.com/netlify/gotrue-js) to [netlify-identity-widget](https://github.com/netlify/netlify-identity-widget).
218233

219-
1. make sure that sourcemaps are built along the way (e.g. in the webpack configuration and the `tsconfig.json` if typescript is used)
220-
2. webpack's uglification is turned off with `optimization: { minimize: false }`. If using VSCode, it is likely that the `sourceMapPathOverrides` have to be adapted for breakpoints to work.
234+
Since for practical purposes we cannot fully emulate Netlify Identity locally, we provide [simple JWT decoding inside the `context` of your function](https://github.com/netlify/netlify-lambda/pull/57). This will give you back the `user` info you need to work with.
221235

222-
Netlify Functions [run in Node v8.10](https://www.netlify.com/blog/2018/04/03/node.js-8.10-now-available-in-netlify-functions/) and you may need to run the same version to mirror the environment locally. Also make sure to check that you aren't [committing one of these common Node 8 mistakes in Lambda!](https://serverless.com/blog/common-node8-mistakes-in-lambda/)
236+
Minor note: For the `identity` field, since we are not fully emulating Netlify Identity, we can't give you details on the Identity instance, so we give you [unambiguous strings](https://github.com/netlify/netlify-lambda/blob/master/lib/serve.js#L87) so you know not to rely on it locally: `NETLIFY_LAMBDA_LOCALLY_EMULATED_IDENTITY_URL` and `NETLIFY_LAMBDA_LOCALLY_EMULATED_IDENTITY_TOKEN`. In production, of course, Netlify Functions will give you the correct `identity.url` and `identity.token` fields. We find we dont use this info often in our functions so it is not that big of a deal in our judgment.
223237

224-
Don't forget to search our issues in case someone has run into a similar problem you have!
238+
## Debugging
225239

226-
## Netlify Identity
240+
To debug lambdas, prepend the `serve` command with [npm's package runner npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) `npx --node-arg=--inspect netlify-lambda serve ...`. Additionally:
227241

228-
Make sure to [read the docs](https://www.netlify.com/docs/functions/#identity-and-functions) on how Netlify Functions and Netlify Identity work together. Basically you have to make your request with an `authorization` header and a `Bearer` token with your Netlify Identity JWT supplied. You can get this JWT from any of our Identity solutions from [gotrue-js](https://github.com/netlify/gotrue-js) to [netlify-identity-widget](https://github.com/netlify/netlify-identity-widget).
242+
1. make sure that sourcemaps are built along the way (e.g. in the webpack configuration and the `tsconfig.json` if typescript is used)
243+
2. webpack's uglification is turned off with `optimization: { minimize: false }`. If using VSCode, it is likely that the `sourceMapPathOverrides` have to be adapted for breakpoints to work.
229244

230-
Since for practical purposes we cannot fully emulate Netlify Identity locally, we provide [simple JWT decoding inside the `context` of your function](https://github.com/netlify/netlify-lambda/pull/57). This will give you back the `user` info you need to work with.
245+
Netlify Functions [run in Node v8.10](https://www.netlify.com/blog/2018/04/03/node.js-8.10-now-available-in-netlify-functions/) and you may need to run the same version to mirror the environment locally. Also make sure to check that you aren't [committing one of these common Node 8 mistakes in Lambda!](https://serverless.com/blog/common-node8-mistakes-in-lambda/)
231246

232-
Minor note: For the `identity` field, since we are not fully emulating Netlify Identity, we can't give you details on the Identity instance, so we give you [unambiguous strings](https://github.com/netlify/netlify-lambda/blob/master/lib/serve.js#L87) so you know not to rely on it locally: `NETLIFY_LAMBDA_LOCALLY_EMULATED_IDENTITY_URL` and `NETLIFY_LAMBDA_LOCALLY_EMULATED_IDENTITY_TOKEN`. In production, of course, Netlify Functions will give you the correct `identity.url` and `identity.token` fields. We find we dont use this info often in our functions so it is not that big of a deal in our judgment.
247+
Don't forget to search our issues in case someone has run into a similar problem you have!
233248

234249
## Example functions and Tutorials
235250

lib/build.js

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
var fs = require("fs");
2-
var path = require("path");
3-
var conf = require("./config");
4-
var webpack = require("webpack");
5-
var merge = require("webpack-merge");
1+
var fs = require('fs');
2+
var path = require('path');
3+
var conf = require('./config');
4+
var webpack = require('webpack');
5+
var merge = require('webpack-merge');
66

77
// custom babel target for each node version
88
function getBabelTarget(envConfig) {
9-
var key = "AWS_LAMBDA_JS_RUNTIME";
10-
var runtimes = ["nodejs8.10", "nodejs4.3.2", "nodejs6.10.3"];
11-
var current = envConfig[key] || process.env[key] || "nodejs6.10.3";
9+
var key = 'AWS_LAMBDA_JS_RUNTIME';
10+
var runtimes = ['nodejs8.15.0', 'nodejs6.10.3'];
11+
var current = envConfig[key] || process.env[key] || 'nodejs8.15.0';
1212
var unknown = runtimes.indexOf(current) === -1;
13-
return unknown ? "6.10" : current.replace(/^nodejs/, "");
13+
return unknown ? '8.15.0' : current.replace(/^nodejs/, '');
1414
}
1515

1616
function haveBabelrc(functionsDir) {
1717
const cwd = process.cwd();
1818

1919
return (
20-
fs.existsSync(path.join(cwd, ".babelrc")) ||
21-
functionsDir.split("/").reduce((foundBabelrc, dir) => {
20+
fs.existsSync(path.join(cwd, '.babelrc')) ||
21+
functionsDir.split('/').reduce((foundBabelrc, dir) => {
2222
if (foundBabelrc) return foundBabelrc;
2323

2424
const indexOf = functionsDir.indexOf(dir);
2525
const dirToSearch = functionsDir.substr(0, indexOf);
2626

27-
return fs.existsSync(path.join(cwd, dirToSearch, ".babelrc"));
27+
return fs.existsSync(path.join(cwd, dirToSearch, '.babelrc'));
2828
}, false)
2929
);
3030
}
@@ -35,13 +35,13 @@ function webpackConfig(dir, additionalConfig) {
3535
var babelOpts = { cacheDirectory: true };
3636
if (!haveBabelrc(dir)) {
3737
babelOpts.presets = [
38-
["@babel/preset-env", { targets: { node: getBabelTarget(envConfig) } }]
38+
['@babel/preset-env', { targets: { node: getBabelTarget(envConfig) } }]
3939
];
4040

4141
babelOpts.plugins = [
42-
"@babel/plugin-proposal-class-properties",
43-
"@babel/plugin-transform-object-assign",
44-
"@babel/plugin-proposal-object-rest-spread"
42+
'@babel/plugin-proposal-class-properties',
43+
'@babel/plugin-transform-object-assign',
44+
'@babel/plugin-proposal-object-rest-spread'
4545
];
4646
}
4747

@@ -51,51 +51,56 @@ function webpackConfig(dir, additionalConfig) {
5151

5252
if (dirPath === functionsPath) {
5353
throw new Error(
54-
"Function source and publish folder should be in different locations"
54+
`
55+
netlify-lambda Error: Function source folder (specified in netlify-lambda serve/build command)
56+
and publish folder (specified in netlify.toml)
57+
should be different.
58+
For more info, check https://github.com/netlify/netlify-lambda#usage
59+
`
5560
);
5661
}
5762

5863
// Include environment variables from config if available
5964
var defineEnv = {};
6065
Object.keys(envConfig).forEach(key => {
61-
defineEnv["process.env." + key] = JSON.stringify(envConfig[key]);
66+
defineEnv['process.env.' + key] = JSON.stringify(envConfig[key]);
6267
});
6368

6469
var webpackConfig = {
65-
mode: "production",
70+
mode: 'production',
6671
resolve: {
67-
extensions: [".wasm", ".mjs", ".js", ".json", ".ts"]
72+
extensions: ['.wasm', '.mjs', '.js', '.json', '.ts']
6873
},
6974
module: {
7075
rules: [
7176
{
7277
test: /\.(m?js|ts)?$/,
7378
exclude: /(node_modules|bower_components)/,
7479
use: {
75-
loader: "babel-loader",
80+
loader: 'babel-loader',
7681
options: babelOpts
7782
}
7883
}
7984
]
8085
},
8186
context: dirPath,
8287
entry: {},
83-
target: "node",
88+
target: 'node',
8489
plugins: [
8590
new webpack.IgnorePlugin(/vertx/),
8691
new webpack.DefinePlugin(defineEnv)
8792
],
8893
output: {
8994
path: functionsPath,
90-
filename: "[name].js",
91-
libraryTarget: "commonjs"
95+
filename: '[name].js',
96+
libraryTarget: 'commonjs'
9297
},
9398
devtool: false
9499
};
95100
fs.readdirSync(dirPath).forEach(function(file) {
96101
if (file.match(/\.(m?js|ts)$/)) {
97-
var name = file.replace(/\.(m?js|ts)$/, "");
98-
webpackConfig.entry[name] = "./" + file;
102+
var name = file.replace(/\.(m?js|ts)$/, '');
103+
webpackConfig.entry[name] = './' + file;
99104
}
100105
});
101106
if (Object.keys(webpackConfig.entry) < 1) {

lib/config.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
var toml = require("toml");
2-
var fs = require("fs");
3-
var path = require("path");
1+
var toml = require('toml');
2+
var fs = require('fs');
3+
var path = require('path');
44

55
exports.load = function() {
6-
var configPath = path.join(process.cwd(), "netlify.toml");
6+
var configPath = path.join(process.cwd(), 'netlify.toml');
77
if (!fs.existsSync(configPath)) {
88
console.error(
9-
"No netlify.toml found. This is needed to configure the function settings"
9+
'No netlify.toml found. This is needed to configure the function settings. For more info: https://github.com/netlify/netlify-lambda#installation'
1010
);
1111
process.exit(1);
1212
}
@@ -16,16 +16,16 @@ exports.load = function() {
1616

1717
exports.loadContext = function(config) {
1818
var buildConfig = config.build;
19-
var contextConfig = (
20-
process.env.CONTEXT &&
21-
config.context &&
22-
config.context[process.env.CONTEXT]
23-
) || {};
24-
var branchConfig = (
25-
process.env.BRANCH &&
26-
config.context &&
27-
config.context[process.env.BRANCH]
28-
) || {};
19+
var contextConfig =
20+
(process.env.CONTEXT &&
21+
config.context &&
22+
config.context[process.env.CONTEXT]) ||
23+
{};
24+
var branchConfig =
25+
(process.env.BRANCH &&
26+
config.context &&
27+
config.context[process.env.BRANCH]) ||
28+
{};
2929
var buildEnv = buildConfig.environment || buildConfig.Environment || {};
3030
var contextEnv = contextConfig.environment || contextConfig.Environment || {};
3131
var branchEnv = branchConfig.environment || branchConfig.Environment || {};
@@ -36,7 +36,7 @@ exports.loadContext = function(config) {
3636
environment: {
3737
...buildEnv,
3838
...contextEnv,
39-
...branchEnv,
39+
...branchEnv
4040
}
4141
};
4242
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "netlify-lambda",
3-
"version": "1.1.1",
3+
"version": "1.2.0",
44
"description": "Build and serve lambda function with webpack compilation",
55
"homepage": "https://github.com/netlify/netlify-lambda#readme",
66
"main": "bin/cmd.js",

0 commit comments

Comments
 (0)