Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add cloudflare-pages preset #210

Merged
merged 22 commits into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5095270
feat: add cloudflare-pages preset
DaniFoldi May 7, 2022
6e6c904
chore: add missing newline
DaniFoldi May 7, 2022
a8be954
chore(deps): update all non-major dependencies (#211)
renovate[bot] May 9, 2022
daa2038
fix: add missing include path `../../**/*` in generated tsconfig.json…
didavid61202 May 9, 2022
234fffd
refactor: Use regular function style
DaniFoldi May 10, 2022
59f47c0
fix: Reorganize structure
DaniFoldi May 10, 2022
5a1fb54
fix: use correct main
DaniFoldi May 10, 2022
55c4036
fix: Use .js extension for functions
DaniFoldi Jun 10, 2022
00fadab
fix: use direct upload from wrangler
DaniFoldi Jun 10, 2022
18adce2
fix: Use esm
DaniFoldi Jun 14, 2022
24eb10a
fix: Call next function for assets
DaniFoldi Jun 14, 2022
26b77a0
fix: wrangler pages dev also requires static folder
DaniFoldi Jun 14, 2022
179b87f
Merge branch 'main' into DaniFoldi/main
danielroe Jun 14, 2022
29faa36
fix: pages internally caches assets as needed
DaniFoldi Jun 15, 2022
8edc5e1
fix: try to use rollup's entrypoint name config
DaniFoldi Jun 15, 2022
0343554
fix: rename file after rollup output is compiled
DaniFoldi Jun 15, 2022
f3ae71d
feat: auto-detect `cloudflare_pages` preset
DaniFoldi Aug 13, 2022
3e4a548
docs: Add docs for cloudflare pages preset
DaniFoldi Aug 13, 2022
5c4a88c
Merge branch 'main' into pr/DaniFoldi/210
pi0 Aug 24, 2022
19343ea
refactor: merge into cloudflare.ts
pi0 Aug 24, 2022
7bbf70c
add testing notice to merge
pi0 Aug 24, 2022
abe5fd5
add type for ctx and remove unused params as todo
pi0 Aug 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/content/2.deploy/0.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ When running Nitro in development mode, Nitro will always use a special preset c
When deploying to the production using CI/CD, Nitro tries to automatically detect the provider environment and set the right one without any additional configuration. Currently, providers below can be auto-detected with zero config.

- [azure](/deploy/providers/azure)
- [cloudflare_pages](/deploy/providers/cloudflare_pages)
- [netlify](/deploy/providers/netlify)
- [stormkit](/deploy/providers/stormkit)
- [vercel](/deploy/providers/vercel)
Expand Down
44 changes: 41 additions & 3 deletions docs/content/2.deploy/providers/cloudflare.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: Cloudflare
description: 'Discover Cloudflare preset for Nitro!'
---

## Cloudflare Workers (service workers syntax)

**Preset:** `cloudflare` ([switch to this preset](/deploy/#changing-the-deployment-preset))

Login to your [Cloudflare Workers](https://workers.cloudflare.com) account and obtain your `account_id` from the sidebar.
Expand All @@ -27,7 +29,7 @@ command = ""
upload.format = "service-worker"
```

## Testing locally
### Testing locally

You can use [miniflare](https://miniflare.dev/), a local Cloudflare Workers development server, to test your app locally:

Expand All @@ -36,7 +38,7 @@ NITRO_PRESET=cloudflare yarn build
npx miniflare .output/server/index.mjs --site .output/public
```

## Deploy from your local machine using wrangler
### Deploy from your local machine using wrangler

Install [wrangler](https://github.com/cloudflare/wrangler) and login to your Cloudflare account:

Expand All @@ -63,7 +65,7 @@ Publish:
wrangler publish
```

## Deploy within CI/CD using GitHub Actions
### Deploy within CI/CD using GitHub Actions

Create a token according to [the wrangler action docs](https://github.com/marketplace/actions/deploy-to-cloudflare-workers-with-wrangler#authentication) and set `CF_API_TOKEN` in your repository config on GitHub.

Expand Down Expand Up @@ -119,3 +121,39 @@ jobs:
```


## Cloudflare Pages

**Preset:** `cloudflare_pages` ([switch to this preset](/deploy/#changing-the-deployment-preset))

::: info Zero Config Provider
Integration with this provider is possible with zero configuration. ([Learn More](/deploy/#zero-config-providers))
:::

### Git integration

If you use the GitHub/GitLab [integration](https://developers.cloudflare.com/pages/get-started/#connect-your-git-provider-to-pages) with Pages, Nitro does not require any configuration. When you push to the repository, Pages will automatically build your project, and Nitro will detect the environment.

### Direct Upload

Alternatively, you can use [wrangler](https://github.com/cloudflare/wrangler2) to upload your project to Cloudflare. In this case, you will have to set the preset manually:

### Deploy from your local machine using wrangler

Install [wrangler](https://github.com/cloudflare/wrangler) and login to your Cloudflare account:

```bash
npm i wrangler -g
wrangler login
```

Create project:

```bash
wrangler pages project create <project-name>
```

Publish:

```bash
wrangler pages publish
```
25 changes: 25 additions & 0 deletions src/presets/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { resolve } from 'pathe'
import { move } from 'fs-extra'
import { writeFile } from '../utils'
import { defineNitroPreset } from '../preset'
import type { Nitro } from '../types'
Expand All @@ -17,3 +18,27 @@ export const cloudflare = defineNitroPreset({
}
}
})

export const cloudflarePages = defineNitroPreset({
extends: 'cloudflare',
entry: '#internal/nitro/entries/cloudflare-pages',
commands: {
preview: 'npx wrangler pages dev .output/public',
deploy: 'npx wrangler pages publish .output/public'
},
output: {
serverDir: '{{ rootDir }}/functions'
},
rollupConfig: {
output: {
entryFileNames: 'path.js',
format: 'esm'
}
},
hooks: {
async 'compiled' (nitro: Nitro) {
await move(resolve(nitro.options.output.serverDir, 'path.js'), resolve(nitro.options.output.serverDir, '[[path]].js'))
await move(resolve(nitro.options.output.serverDir, 'path.js.map'), resolve(nitro.options.output.serverDir, '[[path]].js.map'))
}
}
})
52 changes: 52 additions & 0 deletions src/runtime/entries/cloudflare-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import '#internal/nitro/virtual/polyfill'
import { requestHasBody, useRequestBody } from '../utils'
import { nitroApp } from '../app'

export async function onRequest (context) {
// Contents of context object
const {
request, // same as existing Worker API
env, // same as existing Worker API
// params, // if filename includes [id] or [[path]]
// waitUntil, // same as ctx.waitUntil in existing Worker API
next // used for middleware or to fetch assets
// data, // arbitrary space for passing data between middlewares
} = context

try {
// const asset = await env.ASSETS.fetch(request, { cacheControl: assetsCacheControl })
const asset = await next()
if (asset.status !== 404) {
return asset
}
} catch (_err) {
// Ignore
}

const url = new URL(request.url)
let body
if (requestHasBody(request)) {
body = await useRequestBody(request)
}

const r = await nitroApp.localCall({
env,
context,
Copy link
Member

@pi0 pi0 Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI this currently has no effect (src). unenv only picks known keys from input (url, method, headers, host, protocol, body). But we should definitely add cf context in later changes.

url: url.pathname + url.search,
host: url.hostname,
protocol: url.protocol,
headers: request.headers,
method: request.method,
redirect: request.redirect,
body
})
return new Response(r.body, {
headers: normalizeOutgoingHeaders(r.headers),
status: r.status,
statusText: r.statusText
})
}

function normalizeOutgoingHeaders (headers: Record<string, string | string[] | undefined>) {
return Object.entries(headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(',') : v])
}
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function replaceAll (input: string, from: string, to: string) {

const autodetectableProviders = {
azure_static: 'azure',
cloudflare_pages: 'cloudflare_pages',
netlify: 'netlify',
stormkit: 'stormkit',
vercel: 'vercel'
Expand Down