Skip to content

Commit 91f0928

Browse files
committed
[WIP] Split out content
1 parent a65a358 commit 91f0928

File tree

11 files changed

+502
-446
lines changed

11 files changed

+502
-446
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
pcx-content-type: how-to
3+
title: Pricing and limits
4+
weight: 10
5+
---
6+
7+
# Pricing and limits
8+
9+
While still in open beta, there is no additional cost to deploy Functions within a Pages project. However, during beta, there is a total limit of 100,000 invocation requests per day. If you reach your daily limit, Pages will stop executing your Functions and fallback to serving only static assets.
10+
11+
If you reach this limit or need it increased in order to migrate your existing Workers applications into a Pages project, [complete this form](https://forms.gle/fK65trEL67cTvGQG6) to request an increase. You may track this limit by going to **Account Home** > **Pages** > and reviewing **Functions requests today**.
12+
13+
In the future, you can expect billing to reflect that of the Workers Bundled plan.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
pcx-content-type: get-started
3+
title: Get started
4+
weight: 1
5+
---
6+
7+
# Get Started
8+
9+
## Built with Cloudflare Workers
10+
11+
Cloudflare Workers provides a serverless [execution environment](https://www.cloudflare.com/en-gb/learning/serverless/what-is-serverless/) that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure.
12+
13+
Previously, you could only add dynamic functionality to your Pages site by manually deploying a Worker using Wrangler, which meant that your application is written across both Pages and Workers. Functions allow you to leverage the Workers platform directly from within a Pages project by utilizing a project's filesystem convention. This enables you to deploy your entire site – both its static and dynamic content – when you `git push`.
14+
15+
## Setup
16+
17+
To get started, create a `/functions` directory at the root of your project. Writing your Functions files in this directory will automatically generate a Worker with custom functionality at the predesignated routes.
18+
19+
## Demo
20+
21+
To get started with your first Pages project with Functions, refer to the [demo blog post on how to build an image sharing application](http://blog.cloudflare.com/building-full-stack-with-pages). In this demo, you will build a JSON API with Functions (storing data on KV and Durable Objects), integrate with [Cloudflare Images](/images/) and [Cloudflare Access](/cloudflare-one/), and use React for your front end.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
pcx-content-type: tutorial
3+
title: Writing your first Function
4+
weight: 2
5+
---
6+
7+
# Writing your first Function
8+
9+
When writing request handlers within your Pages application, each `/functions` file must `export` a function to handle the incoming request. Each function will receive a singular `context` object, which contains all the information for the request:
10+
11+
```js
12+
export async function onRequest(context) {
13+
// Contents of context object
14+
const {
15+
request, // same as existing Worker API
16+
env, // same as existing Worker API
17+
params, // if filename includes [id] or [[path]]
18+
waitUntil, // same as ctx.waitUntil in existing Worker API
19+
next, // used for middleware or to fetch assets
20+
data, // arbitrary space for passing data between middlewares
21+
} = context;
22+
23+
return new Response("Hello, world!");
24+
}
25+
```
26+
27+
When migrating from a [Module Worker](/workers/runtime-apis/fetch-event/#syntax-module-worker), this signature combines the traditional `fetch` handler's arguments into a single object along with additional, Pages-specific keys.
28+
29+
In the previous example, an `onRequest` function was exported. This is a generic name because it generically handles all HTTP requests. However, to react to specific HTTP request methods, you may use the method name as a suffix to the exported function. For example, a handler that should only receive `GET` requests should be named `onRequestGet`. The following other handlers are supported:
30+
31+
- `onRequestPost`
32+
- `onRequestPut`
33+
- `onRequestPatch`
34+
- `onRequestDelete`
35+
- `onRequestHead`
36+
- `onRequestOptions`
37+
38+
These are the requests you export to write your first function. For example, you can write a function to output `"Hello World"` when it hits a `/functions/hello-world.js` file:
39+
40+
```js
41+
---
42+
filename: functions/hello-world.js
43+
---
44+
// Reacts to POST /hello-world
45+
export async function onRequestPost(request) {
46+
// ...
47+
return new Response(`Hello world`);
48+
}
49+
```
50+
51+
Another helpful example for handling single path segments can be querying an API for data, for example, [Rick and Morty API](https://rickandmortyapi.com/documentation/#rest) for information on the show characters. You can write a function to show each character on request using the ID to identify them:
52+
53+
```js
54+
---
55+
filename:function/character/[id].js
56+
---
57+
export async function onRequestGet({ params }) {
58+
const res = await fetch(`https://rickandmortyapi.com/api/character/${params.id}`);
59+
const data = await res.json();
60+
const info = JSON.stringify(data, null, 2);
61+
return new Response(info);
62+
}
63+
```
64+
65+
The above will return each character at `/character/{id}` ID being associated with the character.
66+
67+
### Handling multiple requests in a single function
68+
69+
You can define multiple HTTP handlers in a single file by defining multiple exports within the same file. For example, this file will handle `POST` and `PUT` requests with the same handler code:
70+
71+
```js
72+
export async function onRequestPost(context) {
73+
// ...
74+
}
75+
76+
export const onRequestPut = onRequestPost;
77+
```
78+
79+
Additionally, an exported handler may be an array of function handlers. This allows you to easily compose Functions as a group, which may include a mix of shared and/or one-off behaviors:
80+
81+
```js
82+
import { extraLogging } from "middlewares.ts";
83+
84+
export const onRequest = [
85+
extraLogging,
86+
87+
async ({ request }) => {
88+
// ...
89+
},
90+
];
91+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
pcx-content-type: how-to
3+
title: API Reference
4+
weight: 3
5+
---
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
pcx-content-type: how-to
3+
title: Routing
4+
weight: 4
5+
---
6+
7+
# Functions routing
8+
9+
Using a `/functions` directory will generate a routing table based on the files present in the directory. You may use JavaScript (`*.js`) or TypeScript (`*.ts`) to write your Functions. A `PagesFunction` type is declared in the [@cloudflare/workers-types](https://github.com/cloudflare/workers-types) library which you can use to type-check your Functions.
10+
11+
For example, assume this directory structure:
12+
13+
├── ...
14+
├── functions
15+
| └── api
16+
│ ├── [[path]].ts
17+
│ ├── [username]
18+
│ │ └── profile.ts
19+
│ ├── time.ts
20+
│ └── todos
21+
│ ├── [[path]].ts
22+
│ ├── [id].ts
23+
│ └── index.ts
24+
└── ...
25+
26+
The following routes will be generated based on the file structure, mapping the URL pattern to the `/functions` file that will be invoked:
27+
28+
/api/time => ./functions/api/time.ts
29+
/api/todos => ./functions/api/todos/index.ts
30+
/api/todos/* => ./functions/api/todos/[id].ts
31+
/api/todos/*/** => ./functions/api/todos/[[path]].ts
32+
/api/*/profile => ./functions/api/[username]/profile.ts
33+
/api/** => ./functions/api/[[path]].ts
34+
35+
## Path segments
36+
37+
In the [example above](/pages/platform/functions/#functions-routing):
38+
39+
- A `*` denotes a placeholder for a single path segment (for example, `/todos/123`).
40+
- A `**` matches one or more path segments (for example, `/todos/123/dates/confirm`).
41+
42+
When naming your files:
43+
44+
- `[name]` is a placeholder for a single path segment.
45+
- `[[name]]` matches any depth of route below this point.
46+
47+
{{<Aside type="note" header="Route specificity">}}
48+
49+
More specific routes (that is, those with fewer wildcards) take precedence over less specific routes.
50+
51+
{{</Aside>}}
52+
53+
When a filename includes a placeholder, the `name` must be alphanumeric and cannot contain spaces. In turn, the URL segment(s) that match the placeholder will be available under the `context.params` object using the filename placeholder as the key.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
pcx-content-type: how-to
3+
title: Bindings
4+
weight: 5
5+
---
6+
7+
# Bindings
8+
9+
## Adding bindings
10+
11+
A binding is how your Function (Worker) interacts with external resources. You can add KV, Durable Object, and plain-text bindings to your project. A binding is a runtime variable that the Workers runtime provides to your code. You can also use these bindings in development with [Wrangler](/pages/platform/functions/#develop-and-preview-locally).
12+
13+
### KV namespace
14+
15+
Workers KV is Cloudflare's globally replicated key-value storage solution. Within Pages, you can choose from the list of KV namespaces that you created from the dashboard by going to **Account Home** > **Pages** > **your Pages project** > **Settings** > **Functions** > **KV namespace bindings**. Select **Add binding** and input a **Variable name** and select a _KV namespace_ from the list of your existing Workers KV namespaces. You will need to repeat this for both the **Production** and **Preview** environments.
16+
17+
![Editing a KV namespace Binding and adding a Variable name](/pages/platform/media/KV-functions.png)
18+
19+
### KV namespace locally
20+
21+
While developing locally, you can interact with your KV namespace by add `-k, --kv [Namespace binding]` to your run command. For example, if your namespace is bound to `TodoList`, you can access the KV namespace in your local dev by running `npx wrangler pages dev dist --kv TodoList`. The data from this namespace can be accessed using `context.env`.
22+
23+
```js
24+
export async function onRequest({ env }) {
25+
const task = await env.TodoList.get("Task:123");
26+
return new Response(task);
27+
}
28+
```
29+
30+
### Durable Object namespace
31+
32+
Durable Objects are Cloudflare's strongly consistent coordination primitive that power capabilities such as connecting WebSockets, handling state, and building applications. As with Workers KV, you first have to [create the Durable Object](/workers/learning/using-durable-objects/#uploading-a-durable-object-worker). You can then configure it as a binding to your Pages project.
33+
34+
Go to **Account Home** > **Pages** > **your Pages project** > **Settings** > **Functions** > **Durable Object bindings**. Select **Add binding** and input a **Variable name** and select a _Durable Object namespace_ from the list of your existing Durable Objects. You will need to repeat this for both the **Production** and **Preview** environments.
35+
36+
![Editing a Durable Object namespace Binding and adding a Variable name](/pages/platform/media/DO-functions.png)
37+
38+
### Durable Objects locally
39+
40+
Just as you can access kv with `-k` or `--kv` you can access durable objects in your local builds with `-o`, `--do` followed by your Durable object name and class.
41+
42+
### Environment variable
43+
44+
An [environment variable](/workers/platform/environment-variables/) is an injected value that can be accessed by your Functions. It is stored as plaintext. You can set your environment variables directly within the Pages interface for both your production and preview environments at run-time and build-time.
45+
46+
To add environment variables, go to **Account Home** > **Pages** > **your Pages project** > **Settings** > **Environment variables**.
47+
48+
![Editing an environment variable by adding a variable name and value](/pages/platform/media/ENV-functions.png)
49+
50+
### Adding environment variables locally
51+
52+
When developing locally, you can access environment variables by adding a binding to your Wrangler commands like `npx wrangler pages dev dist --binding ENV_NAME="ENV_VALUE"`. This allows you to then access the environment value in your component by using `env.ENV_NAME`.
53+
54+
For example, you can run `npx wrangler pages dev dist --binding COLOR="BLUE"` and then:
55+
56+
```js
57+
export async function onRequest({ env }) {
58+
return new Response(env.COLOR);
59+
}
60+
```
61+
62+
Here is a real-world example of using environment variables inside a middleware function. To connect [Sentry](https://www.sentry.io/) to a Cloudflare Worker, you can use [Toucan js](https://github.com/robertcepa/toucan-js) and access your Sentry Data Source Name (DSN) in your function.
63+
64+
```js
65+
const SentryMiddleware = async ({ request, next, env, waitUntil }) => {
66+
const sentry = new Toucan({
67+
dsn: env.SENTRY_DSN,
68+
context: { waitUntil, request },
69+
});
70+
try {
71+
return await next();
72+
} catch (thrown) {
73+
sentry.captureException(thrown);
74+
return new Response(`Error ${thrown}`, {
75+
status: 500,
76+
});
77+
}
78+
};
79+
export const onRequest = [SentryMiddleware];
80+
```

0 commit comments

Comments
 (0)