如何使用 Cloudflare Workers 在 30 分钟内构建一个高性能博客

在这个教程中,我将带你一步步使用 Cloudflare Workers 构建一个完整的博客系统。无需服务器,无需复杂的配置,只需要一个 Cloudflare 账号和几行代码。

为什么选择 Cloudflare Workers?



Cloudflare Workers 是一个革命性的无服务器平台,它允许你在 Cloudflare 的全球边缘网络上运行 JavaScript 代码。这意味着:
  • 极速访问:代码运行在距离用户最近的 200+ 数据中心
  • 零运维:无需管理服务器,自动扩展
  • 成本低廉: generous 的免费额度,适合个人博客
  • 全球 CDN:内容自动分发到全球


  • 项目结构



    我们将创建一个简洁的博客系统,包含以下功能:
  • 文章列表页
  • 文章详情页
  • 标签分类
  • 响应式设计
  • RESTful API


  • 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:
  • 在 Cloudflare Dashboard 创建 KV 命名空间
  • 更新 wrangler.toml


  • toml
    [[kv_namespaces]]
    
    binding = "BLOG_KV"
    id = "your-kv-namespace-id"
  • 重新部署:


  • bash
    npx wrangler deploy


    总结



    通过本教程,你学会了:
  • ✅ 使用 Cloudflare Workers 构建 Web 应用
  • ✅ 创建自定义路由系统
  • ✅ 渲染 HTML 模板
  • ✅ 提供 RESTful API
  • ✅ 部署到全球边缘网络


  • 这个博客系统虽然简单,但具备了核心功能。你可以在此基础上继续扩展:
  • 添加评论系统(使用 KV 或 D1 数据库)
  • 实现文章管理后台
  • 添加搜索功能
  • 集成 Markdown 渲染
  • 添加 RSS 订阅


  • Cloudflare Workers 的潜力无限,期待你创造出更多精彩的应用!




    相关链接:
  • Cloudflare Workers 文档
  • Wrangler CLI 文档
  • KV 存储文档


  • 完整代码: [GitHub 仓库链接]

    💬 评论区 (0)

    暂无评论,快来抢沙发吧!