利用CloudFlare Worker来搭建免费高速的博客
本文最后更新于 1663 天前,其中的信息可能已经有所发展或是发生改变。

注意:本篇文章部份内容引用了2890kasuganosoras的内容

 title=

 title=

是什么?

Cloudflare workers + Github 实现的动态博客系统,使用边缘计算,无需服务器,Workers是CloudFlare提供的边缘计算,每天有10万次的访问次数,而且速度十分快。

源代码

Github项目地址

伸手党可以直接复制下面这个我修改了CDN节点的版本,因为官方的CDN不稳定。

// 定义 Github 项目,文章会从这里读取
const github_base = "kasuganosoras/frp-blog";

// 设置站点信息
var default_title     = "SakuraFrp Blog - 樱花内网穿透官方博客";                    // 站点标题(显示在浏览器标题栏)
var default_intitle     = "SakuraFrp Blog";                                // 站点名称(显示在首页)
var default_description  = "欢迎访问 Sakura Frp 官方博客,本博客分享与 Frp 相关的技术以及记录一些日常。";     // 站点简介,有利于 SEO
var site_domain         = "blog.natfrp.org";                                // 站点域名
var site_subtitle     = "樱花内网穿透官方博客";                            // 站点副标题
var site_favicon     = "https://cn.tql.ink:4443/gitea/img/favicon.png";                // 站点 Logo

// 博主信息
var owner_name = "Akkariin";                                    // 博主名字
var owner_logo = "https://secure.gravatar.com/avatar/80962ca1ced98d0e679b2bc315d049f2?s=256"    // 博主头像
var owner_desc = "鸽子王/咸鱼/phper,日常水贴摸鱼,佛系出租服务器";                    // 博主简介

// 设置站点资源文件地址
var css_bootstrap     = "https://cdn.lo-li.icu/wwf/bootstrap.min.css";    // Boostrap css 文件地址
var css_hljs_github   = "https://cdn.lo-li.icu/wwf/github.css";  // Highlight js css 地址
var js_jquery         = "https://cdn.lo-li.icu/wwf/jquery.min.js";        // JQuery 地址
var js_bootstrap    = "https://cdn.lo-li.icu/wwf/bootstrap.min.js";    // Bootstrap 地址
var js_instantclick   = "https://cdn.lo-li.icu/wwf/instantclick.min.js";    // InstantClick 地址
var js_showdown     = "https://cdn.lo-li.icu/wwf/showdown.min.js";        // Showdown 地址
var js_showdown_table = "https://cdn.lo-li.icu/wwf/showdown-table.min.js";    // Showdown table 地址
var js_highlight    = "https://cdn.lo-li.icu/wwf/highlight.min.js";    // Highlight 地址
var js_highlight_pack = "https://cdn.lo-li.icu/wwf/highlight.pack.js";        // Highlight pack 地址

// 这是一些临时变量,无需修改
var title = "";
var intitle = "";
var title2 = "";
var description = "";
var ctime = "unknown";
var isunknown = "";

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
});

var header = `



    
        
        
        
        
        
        
        
        
        
        {title}{title_2}
        .pageid{margin-bottom:-26px}code{color:#484848;background-color:#f5f5f5;border-radius:0px;border:1px solid #dadada;}pre>code{color:unset;background-color:unset;border-radius:unset;border:0px;}.post-a {color: #000;text-decoration: none ! important;}.post-box {padding: 12px 20px 12px 20px;border-bottom: 1px solid rgba(0,0,0,0.07);cursor: pointer;border-left: 0px solid rgba(66, 66, 66, 0);transition-duration: 0.3s;}.post-box:hover {transition-duration: 0.3s;border-left: 5px solid rgba(66, 66, 66, 0.15);}.thread h2 {border-bottom: 1px solid rgb(238,238,238);padding-bottom: 10px;}.editor-preview pre, .editor-preview-side pre{padding: 0.5em;}.hljs{background: unset ! important;padding: 0px;}.CodeMirror{height: calc(100% - 320px);min-height: 360px;}.msgid{font-family:Consolas;}.tooltip {word-break: break-all;}h2 a{font-weight: 400;}body{/*background:url(https://i.natfrp.org/cbf5973ce9da283bc9abe307cdea7f30.jpg);*/font-family:'-apple-system','BlinkMacSystemFont','Segoe UI','Helvetica','Arial','sans-serif','Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol' ! important;font-weight:400;background-attachment:fixed;background-size:cover;background-repeat:no-repeat;background-position:center;}h2 a{color: #000;} h2 a:hover{color: #000; text-decoration: none;}.full-width{width: 100%;}.thread img{vertical-align:text-bottom ! important;max-width:100% ! important;margin-top:8px;margin-bottom:8px;}.thread table{display:block;width:100%;overflow:auto;margin-bottom:8px;}.thread table tr{background-color:#fff;border-top:1px solid #c6cbd1;}.thread table tr:nth-child(2n){background-color:#f7f7f7;}.thread table th,.thread table td{padding:10px 12px 0px 12px;border:1px solid #dfe2e5;font-size:14px;}.thread table th {padding-bottom: 10px;background: #f7f7f7;}.thread pre{margin-bottom:16px;}pre{border:none ! important;}blockquote{font-size:15px ! important;}@media screen and(max-width:768px){.copyright{text-align:center;}}
        
            var _hmt = _hmt || [];
            (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?b1f3cc985ea87c4141634fa0572a1612";
            var s = document.getElementsByTagName("script")[0]; 
            s.parentNode.insertBefore(hm, s);
            })();
        
    
    
        
            
                
                    {intitle}
                    ${site_subtitle}
                    
                
                
                    
                        `;

var modifyHeader = {};
var cookieText = "";

function getRequestParams(str) {
    var index = str.indexOf("?");
    str = str.substring(index + 1, str.length);
    if(typeof(str) == "string"){
        u = str.split("&");
        var get = {};
        for(var i in u){
            var j = u[i].split("=");
            get[j[0]] = j[1];
        }
        return get;
    } else {
        return {};
    }
}

async function bloghandle(request) {
    var cookie = {};
    var clist = undefined;
    try {
        cookieText.split(';').forEach(l => {
            var parts = l.split('=');
            cookie[parts[0].trim()] = unescape((parts[1] || '').trim());
        });
    } catch(e) {
        // 无可奉告
    }
    var $_GET = getRequestParams(request.url);
    var urls = new URL(request.url);
    var data = header;
    if(urls.pathname == "/") {
        var url = "https://raw.githubusercontent.com/" + github_base + "/master/list.json";
        const init = {
        method: "GET"
        };
        const response = await fetch(url, init);
        var resptxt = await response.text();
        if(cookie['list'] == undefined) {
            var Days = 30; 
            var exp = new Date(); 
            exp.setTime(exp.getTime() + Days*24*60*60*1000); 
            modifyHeader = {
                "Set-Cookie" : "list="+ escape (resptxt) + ";expires=" + exp.toGMTString()
            };
        }
        var json = JSON.parse(resptxt);
        // console.log(json);
        data += `所有文章
                        `;
        var before_page = 0;
        var current_page = 1;
        var next_page = 2;
        var pagenow = json.length;
        var pageval = json.length - 5;
        if($_GET['p'] != undefined && $_GET['p'] != "") {
            pageval = json.length - (parseInt($_GET['p']) * 5);
            pagenow = json.length - ((parseInt($_GET['p']) - 1) * 5) - 1;
            next_page = parseInt($_GET['p']) + 1;
            current_page = parseInt($_GET['p']);
            before_page = parseInt($_GET['p']) - 1;
        }
        console.log(pageval);
        var update_i = 0;
        for(var i = pagenow;i >= pageval;i--) {
        try {
            var tmpfilename = encodeURIComponent(json[i].file
            .replace(/"/g, "").replace(/posts\//ig, "").replace(/\.md/ig, ""));
            var tmptime = json[i].time;
            var tmptitle = json[i].title;
            data += `
                            
                                ${tmptitle}
                                发表于 ${tmptime}
                            
                        
                        `;
            update_i++;
        } catch(e) {
            // 收声
        }
        }
        console.log(update_i);
        if(update_i == 0) {
        data += `暂时没有文章!
                `
        }
        data += `
                        当前在第 ${current_page} 页
                        
                            `;
        if(current_page > 1) {
        data += `上一页   `;
        }
        if(update_i >= 5) {
        data += `下一页`;
        }
        data += `
                        
                    
                `;
        title = default_title;
        intitle = default_intitle;
        title2 = "";
    } else {
        var uname = unescape("posts" + urls.pathname + ".md");
        try {
        clist = cookie['list'];
        } catch(e) {
        var url = "https://raw.githubusercontent.com/" + github_base + "/master/list.json";
        const init = {
            method: "GET"
        };
        const response = await fetch(url, init);
        clist = await response.text();
        }
        if(clist != undefined) {
            try {
                var json = JSON.parse(clist);
                var found = false;
                for(var i in json) {
                    tmpfilename = json[i].file.replace(/"/g, "");
                    tmptime = json[i].time;
                    tmptitle = json[i].title;
                    if(tmpfilename == uname) {
                        title = tmptitle;
                        intitle = tmptitle;
                        ctime = tmptime;
                        found = true;
                    }
                }
                if(!found) {
                    var url = "https://raw.githubusercontent.com/" + github_base + "/master/list.json";
                    const init = {
                        method: "GET"
                    };
                    const response = await fetch(url, init);
                    clist = await response.text();
                    var json = JSON.parse(clist);
                    for(var i in json) {
                        tmpfilename = json[i].file.replace(/"/g, "");
                        tmptime = json[i].time;
                        tmptitle = json[i].title;
                        if(tmpfilename == uname) {
                            title = tmptitle;
                            intitle = tmptitle;
                            ctime = tmptime;
                        }
                    }
                    var Days = 30; 
                    var exp = new Date(); 
                    exp.setTime(exp.getTime() + Days*24*60*60*1000); 
                    modifyHeader = {
                        "Set-Cookie" : "list="+ escape (clist) + ";expires=" + exp.toGMTString()
                    };
                }
            } catch(e) {
                // 收声
            }
        } else {
            var url = "https://raw.githubusercontent.com/" + github_base + "/master/list.json";
            const init = {
                method: "GET"
            };
            const response = await fetch(url, init);
            var clist = await response.text();
            var json = JSON.parse(clist);
            for(var i in json) {
                tmpfilename = json[i].file.replace(/"/g, "");
                tmptime = json[i].time;
                tmptitle = json[i].title;
                if(tmpfilename == uname) {
                    title = tmptitle;
                    intitle = tmptitle;
                    ctime = tmptime;
                }
            }
            var Days = 30; 
            var exp = new Date(); 
            exp.setTime(exp.getTime() + Days*24*60*60*1000); 
            modifyHeader = {
                "Set-Cookie" : "list="+ escape (clist) + ";expires=" + exp.toGMTString()
            };
        }
        data += `
                        发表于 ${ctime}
                        `;
        var url = "https://raw.githubusercontent.com/" + github_base + "/master/posts" + urls.pathname + ".md";
        const init = {
            method: "GET"
        };
        const response = await fetch(url, init);
        if(response.status == 200) {
            var resptxt = await response.text();
            data += resptxt.replace(/&/g, "&").replace(//g, ">");
            description = resptxt.substring(0, 128).replace(/"/ig, "").replace(/\n/g, " ");
            data += `
                    
                    评论区加载中 qwq
                `;
        } else {
            data += `### 404 Not Found
未找到您访问的页面,原因可能是:
- 该文章已被删除
- 该文章已经更改名称
- 您输入的链接不正确
返回 ${default_intitle} 首页
                    
                `;
            title = `404 Not Found`;
            title2 = ` - ${default_title}`;
            intitle = `未找到指定的页面`;
            description = ``;
            isunknown = " hidden";
        }
        title2 = ` - ${default_title}`;
    }
    data += `
                
                    
                        
                        ${owner_name}
                        ${owner_desc}
                        
                        
                            友情链接
                            Sakura Frp
                        
                    
                
            
            
                
                Powered by CloudFlare Workers | Github
                © 2019 ${default_intitle}
                
                
            
        
        
        
        
        
        
        
        
        
        
            var init = {
            site: "${site_domain}",
            cid: "posts${urls.pathname}.md"
            };
            hljs.initHighlightingOnLoad();
            var md = new showdown.Converter({extensions: ['table']});
            md.setOption('simplifiedAutoLink', true);
            md.setOption('simpleLineBreaks', true);
            md.setOption('openLinksInNewWindow', true);
            md.setOption('noHeaderId', true);
            window.onload = function() {
                try {
                    $(".thread").html(md.makeHtml($("#textdata").val()));
                    document.querySelectorAll('pre code').forEach(function(e) {
                        hljs.highlightBlock(e);
                    });
                    CommentsInit(comments, init);
                } catch(e) {}
            }
        
        
            InstantClick.init();
            InstantClick.on('change', function() {
                try {
                    $(".thread").html(md.makeHtml($("#textdata").val()));
                    document.querySelectorAll('pre code').forEach(function(e) {
                        hljs.highlightBlock(e);
                    });
                    CommentsInit(comments, init);
                } catch(e) {}
            });
        
    

    `;
    data = data.replace(/\{title\}/ig, title)
        .replace(/\{intitle\}/ig, intitle)
        .replace(/\{title\_2\}/ig, title2)
        .replace(/\{isunknown\}/ig, isunknown)
        .replace(/\{description\}/ig, description);
    return data;
}

/**
 * Respond to the request
 * @param {Request} request
 */
async function handleRequest(request) {
    if(new URL(request.url).protocol != "https:") {
        var rhttps = new Response("Location to https", {status: 301});
        rhttps.headers.set("Location", request.url.replace("http://", "https://"));
        return rhttps;
    }
    cookieText = request.headers.get("cookie");
    var resp = new Response(await bloghandle(request), {status: 200});
    resp.headers.set("Content-Type", "text/html");
    if(modifyHeader != undefined) {
        for(var index in modifyHeader) {
        resp.headers.set(index, modifyHeader[index]);
        }
    }
    return resp;
}

如何写作?

首先创建一个 Github 项目,名字随意,然后将这个项目 clone 到本地。

# 示例
git clone https://github.com/kasuganosoras/cloudflare-worker-blog
cd cloudflare-worker-blog/

进入项目文件夹,新建一个 posts 文件夹

mkdir posts/

在里面编写文章,内容一般用 .md 后缀即可,例如 helloworld.md

写完之后回到项目根目录(就是上级目录),然后新建一个 list.json

touch list.json

编辑 list.json,在里面写入以下内容

[
      {
        "title":"文章名称",
        "time":"发布时间",
        "file":"posts/helloworld.md(或者其他名字)"
      }
    ]

如果你有多篇文章就这样写:

[
  {
        "title":"文章1",
        "time":"2019-06-01",
        "file":"posts/1.md"
      },
      {
        "title":"文章2",
        "time":"2019-06-03",
        "file":"posts/2.md"
      },
      {
        "title":"文章3",
        "time":"2019-06-07",
        "file":"posts/3.md"
      }    注意json格式,最后一篇文章的这里不需要逗号
    ]

一切就绪后,使用 git push 命令将代码推送到仓库上。

然后修改你的 workers,设置 github_base 为你的仓库名称,例如 kasuganosoras/cloudflare-worker-blog

现在访问你的 Workers 即可看到文章。

自定义域名

获取到自己的**.workers.dev
域名 Cname 到(**.workers.dev)
然后去 Workers 点击 ADD route
输入自定义域名,例如 iloli.icu/* 后面要加上 /* ,下面的 workers 选择刚才的项目

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇