, 4 min read

Hosting Static Content with Cloudflare

I wrote about hosting static sites on various platforms:

  1. Hosting Static Content with surge.sh
  2. Hosting Static Content with now.sh, now.sh renamed themself to vercel.app
  3. Hosting Static Content with netlify.app

Since end of 2021 Cloudflare greatly enhanced their static site offering: Cloudflare Pages Goes Full Stack.

Start with npm install wrangler. This will install the JavaScript command to control your "Cloudflare Pages" account. The wrangler command has the following options:

$ wrangler

Commands:
  wrangler docs [command..]            📚 Open wrangler's docs in your browser
  wrangler init [name]                 📥 Initialize a basic Worker project, including a wrangler.toml file
  wrangler generate [name] [template]  ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
  wrangler dev [script]                👂 Start a local server for developing your worker
  wrangler deploy [script]             🆙 Deploy your Worker to Cloudflare.  [aliases: publish]
  wrangler delete [script]             🗑  Delete your Worker from Cloudflare.
  wrangler tail [worker]               🦚 Starts a log tailing session for a published Worker.
  wrangler secret                      🤫 Generate a secret that can be referenced in a Worker
  wrangler secret:bulk [json]          🗄  Bulk upload secrets for a Worker
  wrangler kv:namespace                🗂  Interact with your Workers KV Namespaces
  wrangler kv:key                      🔑 Individually manage Workers KV key-value pairs
  wrangler kv:bulk                     💪 Interact with multiple Workers KV key-value pairs at once
  wrangler pages                       ⚡ Configure Cloudflare Pages
  wrangler queues                      🇶 Configure Workers Queues
  wrangler r2                          📦 Interact with an R2 store
  wrangler dispatch-namespace          📦 Interact with a dispatch namespace
  wrangler d1                          🗄  Interact with a D1 database
  wrangler constellation               🤖 Interact with Constellation models
  wrangler pubsub                      📮 Interact and manage Pub/Sub Brokers
  wrangler mtls-certificate            🪪 Manage certificates used for mTLS connections
  wrangler login                       🔓 Login to Cloudflare
  wrangler logout                      🚪 Logout from Cloudflare
  wrangler whoami                      🕵  Retrieve your user info and test your auth config
  wrangler types                       📝 Generate types from bindings & module rules in config
  wrangler deployments                 🚢 List and view details for deployments
  wrangler rollback [deployment-id]    🔙 Rollback a deployment

Flags:
  -j, --experimental-json-config  Experimental: Support wrangler.json  [boolean]
  -c, --config                    Path to .toml configuration file  [string]
  -e, --env                       Environment to use for operations and .env files  [string]
  -h, --help                      Show help  [boolean]
  -v, --version                   Show version number  [boolean]

And specifically for the pages subcommand:

$ wrangler pages

⚡ Configure Cloudflare Pages

Commands:
  wrangler pages dev [directory] [-- command..]  🧑💻 Develop your full-stack Pages application locally
  wrangler pages project                         ⚡ Interact with your Pages projects
  wrangler pages deployment                      🚀 Interact with the deployments of a project
  wrangler pages deploy [directory]              🆙 Deploy a directory of static assets as a Pages deployment  [aliases: publish]

Flags:
  -j, --experimental-json-config  Experimental: Support wrangler.json  [boolean]
  -c, --config                    Path to .toml configuration file  [string]
  -e, --env                       Environment to use for operations and .env files  [string]
  -h, --help                      Show help  [boolean]
  -v, --version                   Show version number  [boolean]

To deploy your current directory to Cloudflare, see Use Direct Upload with continuous integration:

CLOUDFLARE_ACCOUNT_ID=<ACCOUNT_ID> npx wrangler pages publish <DIRECTORY> --project-name=<PROJECT_NAME>

Your account id is this 32 byte long hash, not your e-mail address.

The so called "project name" is your previously specified name for your pages. In my case it is klm. Therefore I run:

$ time CLOUDFLARE_ACCOUNT_ID='d4ba2e3c15c942c374380afd7fb7f441' wrangler pages deploy --project-name=klm .
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/(...)
Successfully logged in.
🌍  Uploading... (1014/1014)

✨ Success! Uploaded 1014 files (88.23 sec)

✨ Deployment complete! Take a peek over at https://3493e64d.klm.pages.dev
        real 118.45s
        user 4.63s
        sys 0
        swapped 0
        total space 0

Deploying more than 1,000 files takes around two minutes. Some time has to be substracted from this as I had to log in manually via browser.

If you have already uploaded and just want to change some files, then deployment is much faster.

$ time CLOUDFLARE_ACCOUNT_ID='2a73fd651205801dfe83244b968920bb' wrangler pages deploy . --project-name=klm
🌎  Uploading... (1023/1023)

✨ Success! Uploaded 9 files (1014 already uploaded) (2.92 sec)

✨ Deployment complete! Take a peek over at https://e885abe0.klm.pages.dev
        real 11.29s
        user 1.80s
        sys 0
        swapped 0
        total space 0

My static site on Cloudflare is here: klm.pages.dev.

Added 23-May-2023: Instead of setting CLOUDFLARE_ACCOUNT environment variable in front of wrangler, you have to first login via

wrangler login

Then

npx wrangler pages deploy <DIRECTORY> --project-name=<PROJECT_NAME>

In my case this is

$ time wrangler pages deploy . --project-name=klm

Added 29-Aug-2023: wrangler script seems to be broken. It emits below error message:

✘ [ERROR] A request to the Cloudflare API (/accounts/Elmar.Klausmeier@gmail.com/pages/projects/klm) failed.

  Could not route to /client/v4/accounts/Elmar.Klausmeier@gmail.com/pages/projects/klm, perhaps your
  object identifier is invalid? [code: 7003]

  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose

Remedy: Go to your dashboard in Cloudflare, remove the "project", then upload zip-file with all your files.

Added 24-Sep-2023: Previously you had to use your e-mail address, i.e., your accound id. Now you have to use your Account ID, which is this 32 byte long hash. If you still use your e-mail address, you will get below error:

✘ [ERROR] A request to the Cloudflare API (/accounts/Elmar.Klausmeier@gmail.com/pages/projects) failed.

See BUG: #3862.

Added 02-Jul-2024: Latest twist:

time wrangler pages deploy --project-name klm .