NekoMio

NekoMio

telegram
github

Deploy Hexo to Cloudflare Workers

0. Introduction#

Recently, I learned that Cloudflare Workers KV has a free quota, which seems to be able to do some interesting things. Since my own blog server is in China, I want to use the method of diversion to allow direct access to Cloudflare from abroad for a better experience.

1. Preparation#

To deploy Hexo Blog to Cloudflare Workers, you need to have a Hexo Blog. You also need a Cloudflare account~

2. Apply for an API key#

Log in to Cloudflare and apply for an API token in Profile-API Tokens. You can use the built-in Cloudflare Workers template.
1649775724987-156-2.webp
Remember your Key, you will need it later.

3. Install Wrangler CLI locally for initial deployment#

Install wrangler#

Since you have Hexo, you must have Node.js environment. So, install wrangler via npm or yarn~

npm i @cloudflare/wrangler -g
# yarn global add @cloudflare/wrangler
Initialize the project#

Go to your Hexo root directory and initialize it.

wrangler init --site my-static-site # You can change the name at the end to your liking~

After initialization, you should see the wrangler.toml file and workers-site directory added to the directory.

Modify the configuration#

We need to modify wrangler.toml to configure our project.

[site]
bucket = "./public"
entry-point = "workers-site"

The most important part is these two lines. We need to modify the value of bucket to the directory we want to deploy, which is ./public for Hexo.

We also need to modify the personal information above.

account_id = ""
workers_dev = true
route = "www.nekomio.com/*"
zone_id = ""

You can find account_id after logging in. If you haven't bound your own domain name, you can temporarily ignore route and zone_id.

Deployment#

Now you need to run wrangler config and enter the API Token we obtained earlier.

You can preview it using preview.

wrangler preview --watch

Deploy it using publish.

wrangler publish

Now, we can open our website on Cloudflare.

4. Custom Router#

Here, I used a configuration file provided by Sukka, mainly to redirect requests ending with index.html to URLs without index.html using a 301 redirect, and extended the cache time for css.
Here is the configuration for reference.

import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'

addEventListener('fetch', event => {
  try {
    event.respondWith(handleEvent(event))
  } catch (e) {
    if (DEBUG) {
      return event.respondWith(
        new Response(e.message || e.toString(), {
          status: 500,
        }),
      )
    }
    event.respondWith(new Response('Internal Error', { status: 500 }))
  }
})

async function handleEvent(event) {
  const { origin, pathname: path, search } = new URL(event.request.url);
  if (path.endsWith('/index.html')) {
    return new Response(null, {
      status: 301,
        headers: {
          'Location': `${origin}${path.substring(0, path.length - 10)}${search}`,
          'Cache-Control': 'max-age=3600'
        }
    });
  }
  if (path === '/atom.xml') {
    return getAssetFromKV(event, {
      cacheControl: {
        edgeTtl: 60 * 60,
        browserTtl: 2 * 60 * 60
      }
    });
  }
  
  if (path.startsWith('/css/'))  {
    const response = await getAssetFromKV(event, {
      cacheControl: {
        edgeTtl: 365 * 24 * 60 * 60,
        browserTtl: 365 * 24 * 60 * 60
      }
    });
    // getAssetFromKV does not add immutable, so we need to manually override Cache-Control
    response.headers.set('cache-control', `public, max-age=${365 * 24 * 60 * 60}, immutable`);
    return response;
  }
  
  const response = await getAssetFromKV(event, {
    cacheControl: {
      edgeTtl: 60 * 60,
      browserTtl: 5 * 60
    }
  });
  
  response.headers.set('X-XSS-Protection', '1; mode=block');
  return response;
}

Finally, it's done~~

This is the free limitation provided by Cloudflare. It should be sufficient if the traffic is not large. If you have a large number of articles, the number of deployments per day may be limited.

  • Workers functionality

    • Including 100,000 requests/day (UTC+0)
    • Each request can use up to 10 milliseconds of CPU time
    • Lowest latency after the first request
  • Key-value storage functionality

    • 100,000 read operations per day
    • 1,000 write, delete, and list operations per day
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.