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.
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