Skip to content
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit 3ad3b39

Browse files
add support for background functions in api pages only (#171)
* add support for background functions in api pages only * logItem when bground func is set up + README + test
1 parent a73045f commit 3ad3b39

File tree

9 files changed

+50
-8
lines changed

9 files changed

+50
-8
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ The plugin can be found on [npm here](https://www.npmjs.com/package/@netlify/plu
4848
- [Preview Locally](#preview-locally)
4949
- [Custom Netlify Redirects](#custom-netlify-redirects)
5050
- [Custom Netlify Functions](#custom-netlify-functions)
51+
- [Background Functions](#background-functions)
5152
- [Using Netlify Identity](#using-netlify-identity)
5253
- [Caveats](#caveats)
5354
- [Fallbacks for Pages with `getStaticPaths`](#fallbacks-for-pages-with-getstaticpaths)
@@ -223,7 +224,12 @@ Currently, there is no support for redirects set in your `netlify.toml` file.
223224
### Custom Netlify Functions
224225

225226
`next-on-netlify` creates one Netlify Function for each of your
226-
SSR pages and API endpoints. It is currently not possible to create custom Netlify Functions. This feature is on our list to do.
227+
SSR pages and API endpoints. Currently, you can only create custom Netlify functions using [@netlify/plugin-nextjs](https://github.com/netlify/netlify-plugin-nextjs#custom-netlify-functions).
228+
229+
### Background Functions
230+
231+
If your Next.js API page/route ends in `-background`, it will be treated as a [Netlify background function](https://docs.netlify.com/functions/background-functions/).
232+
Note: background functions are only available on certain plans.
227233

228234
### Using Netlify Identity
229235

lib/helpers/getNetlifyFunctionName.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const path = require("path");
55
// The function name will be next_directory_subdirectory_[id]
66
// We do this because every function needs to be at the top-level, i.e.
77
// nested functions are not allowed.
8-
const getNetlifyFunctionName = (filePath) => {
8+
const getNetlifyFunctionName = (filePath, isApiPage) => {
99
// Remove pages/ from file path:
1010
// pages/directory/page.js > directory/page.js
1111
const relativeFilePath = path.relative("pages", filePath);
@@ -24,7 +24,16 @@ const getNetlifyFunctionName = (filePath) => {
2424
// Netlify Function names may not contain periods or square brackets.
2525
// To be safe, we keep only alphanumeric characters and underscores.
2626
// See: https://community.netlify.com/t/failed-to-upload-functions-file-function-too-large/3549/8
27-
functionName = functionName.replace(/[^\w\d]/g, "");
27+
const cleanNameRegex = new RegExp(/[^\w\d]/g);
28+
// Allow users to use background functions for /api pages *only*
29+
// Note: this means that there is a chance a Next on Netlify user could
30+
// unknowingly create a background function if they're not familiar with them
31+
// and their syntax
32+
const allowBackgroundRegex = new RegExp(/[^\w\d-]|-(?!background$)/g);
33+
functionName = functionName.replace(
34+
isApiPage ? allowBackgroundRegex : cleanNameRegex,
35+
""
36+
);
2837

2938
return functionName;
3039
};

lib/helpers/setupNetlifyFunctionForPage.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@ const {
66
FUNCTION_TEMPLATE_PATH,
77
} = require("../config");
88
const getNetlifyFunctionName = require("./getNetlifyFunctionName");
9+
const { logItem } = require("./logger");
910

1011
// Create a Netlify Function for the page with the given file path
11-
const setupNetlifyFunctionForPage = ({ filePath, functionsPath }) => {
12+
const setupNetlifyFunctionForPage = ({
13+
filePath,
14+
functionsPath,
15+
isApiPage,
16+
}) => {
1217
// Set function name based on file path
13-
const functionName = getNetlifyFunctionName(filePath);
18+
const functionName = getNetlifyFunctionName(filePath, isApiPage);
1419
const functionDirectory = join(functionsPath, functionName);
1520

16-
// Copy function template
21+
if (isApiPage && functionName.endsWith("-background")) {
22+
logItem(
23+
`👁 Setting up API page ${functionName} as a Netlify background function`
24+
);
25+
}
26+
27+
// Copy function templates
1728
const functionTemplateCopyPath = join(
1829
functionDirectory,
1930
`${functionName}.js`

lib/pages/api/redirects.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const pages = require("./pages");
33

44
const redirects = pages.map(({ route, filePath }) => ({
55
route,
6-
target: `/.netlify/functions/${getNetlifyFunctionName(filePath)}`,
6+
target: `/.netlify/functions/${getNetlifyFunctionName(filePath, true)}`,
77
}));
88

99
module.exports = redirects;

lib/pages/api/setup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const setup = (functionsPath) => {
1212
// Create Netlify Function for every page
1313
pages.forEach(({ filePath }) => {
1414
logItem(filePath);
15-
setupNetlifyFunctionForPage({ filePath, functionsPath });
15+
setupNetlifyFunctionForPage({ filePath, functionsPath, isApiPage: true });
1616
});
1717
};
1818

tests/__snapshots__/defaults.test.js.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ exports[`Routing creates Netlify redirects 1`] = `
2424
/_next/data/%BUILD_ID%/getStaticProps/withFallbackBlocking/4.json /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200! Cookie=__prerender_bypass,__next_preview_data
2525
/_next/data/%BUILD_ID%/getStaticProps/withRevalidate/1.json /.netlify/functions/next_getStaticProps_withRevalidate_id 200
2626
/_next/data/%BUILD_ID%/getStaticProps/withRevalidate/2.json /.netlify/functions/next_getStaticProps_withRevalidate_id 200
27+
/api/hello-background /.netlify/functions/next_api_hello-background 200
2728
/api/static /.netlify/functions/next_api_static 200
2829
/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200
2930
/getStaticProps/1 /.netlify/functions/next_getStaticProps_id 200! Cookie=__prerender_bypass,__next_preview_data

tests/__snapshots__/i18n.test.js.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ exports[`Routing creates Netlify redirects 1`] = `
2323
/_next/data/%BUILD_ID%/es/getStaticProps/static.json /.netlify/functions/next_getStaticProps_static 200! Cookie=__prerender_bypass,__next_preview_data
2424
/_next/data/%BUILD_ID%/es/getStaticProps/with-revalidate.json /.netlify/functions/next_getStaticProps_withrevalidate 200
2525
/_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200
26+
/api/hello-background /.netlify/functions/next_api_hello-background 200
2627
/api/static /.netlify/functions/next_api_static 200
2728
/en /.netlify/functions/next_index 200
2829
/en/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200

tests/defaults.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ describe("API Pages", () => {
129129
join(functionsDir, "next_api_shows_params", "next_api_shows_params.js")
130130
)
131131
).toBe(true);
132+
expect(
133+
existsSync(
134+
join(
135+
functionsDir,
136+
"next_api_hello-background",
137+
"next_api_hello-background.js"
138+
)
139+
)
140+
).toBe(true);
132141
});
133142
});
134143

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default (req, res) => {
2+
res.setHeader("Content-Type", "application/json");
3+
res.status(200);
4+
res.json({ message: "hello world :)" });
5+
};

0 commit comments

Comments
 (0)