为什么选择 Cloudflare Workers?
Cloudflare Workers 是一个革命性的无服务器平台,它允许你在 Cloudflare 的全球边缘网络上运行 JavaScript 代码。这意味着:
项目结构
我们将创建一个简洁的博客系统,包含以下功能:
text
.
├── src/
│ ├── index.js # Worker 入口文件
│ ├── router.js # 路由处理器
│ ├── data.js # 数据层
│ └── templates.js # HTML 模板
├── wrangler.toml # 部署配置
└── package.json # 项目配置第一步:初始化项目
首先创建项目目录并初始化:
bash
mkdir cloudflare-worker-blog
cd cloudflare-worker-blog
npm init -y安装 Wrangler CLI 工具:
bash
npm install --save-dev wrangler创建
wrangler.toml 配置文件:
toml
name = "cloudflare-worker-blog"
main = "src/index.js"
compatibility_date = "2024-01-01"第二步:创建路由系统
创建一个简单的路由处理器
src/router.js:
javascript
export class Router {
constructor() {
this.routes = [];
}
get(path, handler) {
this.routes.push({ method: 'GET', path, handler });
}
async handle(request) {
const url = new URL(request.url);
const method = request.method;
const pathname = url.pathname;
for (const route of this.routes) {
if (route.method !== method) continue;
const params = this.matchPath(route.path, pathname);
if (params !== null) {
return await route.handler(params);
}
}
return null;
}
matchPath(routePath, actualPath) {
if (!routePath.includes(':')) {
return routePath === actualPath ? {} : null;
}
const routeParts = routePath.split('/').filter(Boolean);
const actualParts = actualPath.split('/').filter(Boolean);
if (routeParts.length !== actualParts.length) {
return null;
}
const params = {};
for (let i = 0; i < routeParts.length; i++) {
if (routeParts[i].startsWith(':')) {
params[routeParts[i].slice(1)] = decodeURIComponent(actualParts[i]);
} else if (routeParts[i] !== actualParts[i]) {
return null;
}
}
return params;
}
}这个路由系统支持:
/about)/post/:slug)第三步:准备博客数据
创建
src/data.js,包含示例文章:
javascript
const SAMPLE_POSTS = [
{
id: 1,
title: '开始使用 Cloudflare Workers',
slug: 'getting-started-with-cloudflare-workers',
excerpt: 'Cloudflare Workers 是一个强大的无服务器平台...',
content: '<p>详细内容...</p>',
author: '博客作者',
date: '2024-01-15',
tags: ['Cloudflare', 'Workers', 'Serverless'],
readTime: 5
},
// 更多文章...
];
export async function getPosts(env) {
// 支持 KV 存储和内存存储
if (env?.BLOG_KV) {
const posts = await env.BLOG_KV.get('posts', 'json');
if (posts) return posts;
}
return SAMPLE_POSTS;
}
export async function getPostBySlug(env, slug) {
if (env?.BLOG_KV) {
const post = await env.BLOG_KV.get(post:${slug}, 'json');
if (post) return post;
}
return SAMPLE_POSTS.find(post => post.slug === slug) || null;
}
export async function getPostsByTag(env, tag) {
const posts = await getPosts(env);
return posts.filter(post =>
post.tags.some(t => t.toLowerCase() === tag.toLowerCase())
);
}第四步:创建 HTML 模板
创建
src/templates.js 来渲染页面:
javascript
function baseLayout(title, content) {
return <!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title}</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header>
<nav>
<a href="/" class="logo">我的博客</a>
<ul class="nav-links">
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
</ul>
</nav>
</header>
<main>${content}</main>
<footer>
<p>© ${new Date().getFullYear()} Cloudflare Worker 博客</p>
</footer>
</body>
</html>;
}
export function renderHomePage(posts) {
const content =
<h1>最新文章</h1>
<div class="post-list">
${posts.map(post =>
<article class="post-item">
<h2><a href="/post/${post.slug}">${post.title}</a></h2>
<div class="post-meta">
${post.date} · ${post.author} · ${post.readTime}分钟阅读
</div>
<p>${post.excerpt}</p>
<div class="post-tags">
${post.tags.map(tag =>
<a href="/tag/${tag}" class="tag">${tag}</a>
).join('')}
</div>
</article>
).join('')}
</div>
;
return baseLayout('首页', content);
}
export function renderPostPage(post) {
const content =
<article class="post-detail">
<h1>${post.title}</h1>
<div class="post-meta">
${post.date} · ${post.author} · ${post.readTime}分钟阅读
</div>
<div class="post-content">${post.content}</div>
</article>
;
return baseLayout(post.title, content);
}第五步:创建主入口文件
创建
src/index.js,整合所有功能:
javascript
import { Router } from './router.js';
import { renderHomePage, renderPostPage } from './templates.js';
import { getPosts, getPostBySlug, getPostsByTag } from './data.js';
export default {
async fetch(request, env, ctx) {
const router = new Router();
// CSS 样式
router.get('/style.css', () => {
return new Response(CSS_CONTENT, {
headers: { 'Content-Type': 'text/css' }
});
});
// API 路由
router.get('/api/posts', async () => {
const posts = await getPosts(env);
return jsonResponse(posts);
});
router.get('/api/posts/:slug', async (params) => {
const post = await getPostBySlug(env, params.slug);
if (!post) {
return jsonResponse({ error: '文章不存在' }, 404);
}
return jsonResponse(post);
});
// 页面路由
router.get('/', async () => {
const posts = await getPosts(env);
return htmlResponse(renderHomePage(posts));
});
router.get('/post/:slug', async (params) => {
const post = await getPostBySlug(env, params.slug);
if (!post) {
return htmlResponse('<h1>404</h1>', 404);
}
return htmlResponse(renderPostPage(post));
});
router.get('/tag/:tag', async (params) => {
const posts = await getPostsByTag(env, params.tag);
return htmlResponse(renderHomePage(posts, params.tag));
});
const response = await router.handle(request);
if (response) return response;
return htmlResponse('<h1>404 - 页面不存在</h1>', 404);
}
};
function jsonResponse(data, status = 200) {
return new Response(JSON.stringify(data), {
status,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
}
function htmlResponse(html, status = 200) {
return new Response(html, {
status,
headers: { 'Content-Type': 'text/html;charset=UTF-8' }
});
}
// CSS 样式内容
const CSS_CONTENT =
/ 你的 CSS 样式 /
body { font-family: system-ui, sans-serif; line-height: 1.6; }
.container { max-width: 800px; margin: 0 auto; padding: 0 20px; }
/ ... 更多样式 /
;第六步:本地测试
在部署之前,先在本地测试:
bash
npx wrangler dev这将启动本地开发服务器,通常在
http://localhost:8787。
访问以下地址测试:
http://localhost:8787/ - 首页http://localhost:8787/api/posts - API 接口http://localhost:8787/post/getting-started-with-cloudflare-workers - 文章详情第七步:部署到 Cloudflare
首先登录 Cloudflare:
bash
npx wrangler login这会在浏览器中打开认证页面,登录你的 Cloudflare 账号。
然后部署:
bash
npx wrangler deploy部署成功后,你会看到类似这样的输出:
text
Uploaded cloudflare-worker-blog
Deployed cloudflare-worker-blog triggers
https://cloudflare-worker-blog.your-account.workers.dev🎉 恭喜!你的博客已经上线!
进阶:使用 KV 存储
要支持动态添加文章,可以配置 Cloudflare KV:
wrangler.toml:toml
[[kv_namespaces]]
binding = "BLOG_KV"
id = "your-kv-namespace-id"bash
npx wrangler deploy总结
通过本教程,你学会了:
这个博客系统虽然简单,但具备了核心功能。你可以在此基础上继续扩展:
Cloudflare Workers 的潜力无限,期待你创造出更多精彩的应用!
相关链接:
完整代码: [GitHub 仓库链接]
💬 评论区 (0)
暂无评论,快来抢沙发吧!