我在 2010 年开始了我的第一个博客。当时使用WordPress是显而易见的(那是在HackerNoon和Medium之前)。这是一个不错的选择,因为它易于使用,并且有数以千计的主题和插件。
WordPress 是一个了不起的引擎,但它也有其缺点。它需要资源,并且存在许多与WordPress相关的漏洞。一种可能的解决方案是将整个站点置于 CloudFront 或任何其他 CDN 后面。
CDN 可以很好地扩展并确保站点安全,但就我而言,博客只是一个存档,我不想让我的服务器保持运行。这就是我选择 GitHub Pages 的原因。
GitHub Pages 是“穷人的托管解决方案”。它是免费的,您可以将您的域指向它。
它的缺点是它只能托管静态站点,所以我不得不从我的 WordPress 博客生成一个静态站点。
幸运的是,WordPress 可以将整个站点的内容导出(管理员上的工具/导出)到 XML 文件中,所以我唯一要做的就是开发一个简单的静态站点生成器,从导出中生成内容。
我选择TypeScript进行开发,因为我熟悉它,并且有很多很酷且易于使用的JS库可以做到这一点。
首先,我必须找到一个简单易用的 XML 解析器。经过短暂的谷歌搜索,我找到了一个快速的xml解析器。此解析器从 XML 创建一个可以轻松处理的 JS 对象树。
我需要的另一件事是一个简单的模板引擎。为此,ejs 是最好的。它很容易学习,因为你可以简单地将你的 JS 嵌入到 HTML 代码中,而且速度也很快,因为在后台,引擎会把你的模板编译成 JS。
对于小型项目,我无法想象一个更简单、更好的解决方案。
我拥有我需要的一切,所以我开始开发我的小型静态站点生成器。
为了创建ejs模板,我只需下载WordPress生成的HTML文件,并在其中添加ejs标签。我创建了 2 个模板。一个用于帖子,一个用于目录。
导出 XML 的结构非常简单。它基本上是一个由项目构建的 RSS 提要。每个项目都有一个类型(帖子、附件等),但我只需要帖子和附件。代码如下所示:
(async function () { const parser = new XMLParser(); let wp_export = parser.parse(readFileSync('wordpress-export.xml')); let posts = wp_export.rss.channel.item; let pinned_posts: any[] = [] let post_list: any[] = [] for (const post of posts) { // download attachments if (post['wp:post_type'] == 'attachment') { const url = post['wp:attachment_url']; for (const post_meta of post['wp:postmeta']) { if (post_meta['wp:meta_key'] == '_wp_attached_file') { const file_path = post_meta['wp:meta_value'] const full_path = `wp-content/uploads/${file_path}` mkdirSync(dirname(full_path), { recursive: true }); const file = createWriteStream(full_path); http.get(url, (resp) => { resp.pipe(file); file.on("finish", () => { file.close(); }); }) } } } // generate post page if it's published if (post['wp:post_type'] == 'post' && post['pubDate']) { post['content:encoded'] = post['content:encoded'].split(/\r?\n|\r|\n/g).reduce((accumulator: string, currentValue: string) => accumulator + `<p>${currentValue}</p>`) const content = await ejs.renderFile("template.ejs", { post: post }, { async: true }) mkdirSync(`archives/${post['wp:post_id']}`, { recursive: true }); writeFileSync(`archives/${post['wp:post_id']}/index.html`, content) const element = { id: post['wp:post_id'], title: post.title, summary: truncate(post['content:encoded'].replace(/<[^>]*>?/gm, ''), 300) } if (pinned_post_ids.includes(post['wp:post_id'])) { pinned_posts.push(element) } else { post_list.push(element) } } } // generate toc pinned_posts.sort((a, b) => { return b.id - a.id }) let merged_posts = pinned_posts.concat(post_list.sort((a, b) => { return b.id - a.id })) // readme.md let readme = ` # my-wordpress-blog This is a backup of my WordPress blog. (http://lf.estontorise.hu/) ` for (const post of merged_posts) readme += `[${post.title}](https://thebojda.github.io/my-wordpress-blog/archives/${post.id})\n\n` writeFileSync('README.md', readme) // index.html const content = await ejs.renderFile("template_toc.ejs", { posts: merged_posts }, { async: true }) writeFileSync(`index.html`, content) })()
该代码循环访问项并检查其类型。如果类型为“attachment”,则它将读取包含附件 URL 的“_wp_attached_file”元数据的值,并使用 HTTP 模块下载它。
如果项目类型为“post”,并且已发布(pubDate 不为空),则生成页面。页面内容位于 HTML 格式的“content:encoded”标签中,略有变化。
每一行都是一个单独的段落,因此您必须将换行符转换为段落。这是通过以下代码行完成的:
post['content:encoded'] = post['content:encoded'] .split(/\r?\n|\r|\n/g) .reduce((accumulator: string, currentValue: string) => accumulator + `<p>${currentValue}</p>`)
10 年前,当我开始写博客时,我对 SEO 一无所知,所以帖子链接如下所示:…/archives/123,其中最后一个数字是帖子 ID。
在更好的情况下,帖子 URL 更具表现力并包含关键字,但在这两种情况下,您都将面临 GitHub Pages 不支持没有“.html”扩展名的 HTML 页面的问题。
如果您上传的 HTML 文件没有扩展名,浏览器将下载该文件而不是显示它。因此,您必须将这些 URL 转换为包含 index.html 文件的目录。
例如,/archives/123 必须转换为 /archives/123/index.html。有了这个新结构,一切都像魅力一样工作。
代码的最后一个块生成 ToC HTML 和 readme.md 文件。如果有人在 GitHub 上找到您的页面,第二个可能非常有用,因为她可以轻松导航到您的帖子。
静态页面生成完成后,我只需将我的站点上传到 GitHub 并在“设置”中启用 GitHub Pages。
在DNS提供商的管理员上设置CNAME记录后,GitHub对其进行了检查。通过选中“强制执行 HTTPS”复选框,GitHub 生成了一个 HTTPS 证书,过了一会儿,站点就准备好了。在这里您可以观看结果:https://lf.estontorise.hu。
该博客是匈牙利语的,所以你可能不会理解内容,但你可以看到一切正常,URL与WordPress URL相同。
正如我所说,这个博客只是一个存档,我不打算创建新帖子,但如果我愿意,我可以将我的 WordPress 引擎安装到我的本地机器上。
我可以写新的帖子并更新存储库中新生成的页面,所以如果你想使用 WordPress 写博客和 GitHub 托管页面,这也是可能的。
这是我从 WordPress 到 GitHub Pages 的短暂旅程;我希望这篇简短的文章可以帮助你迁移自己的博客,如果你愿意的话。
(你可以在我的 GitHub 存储库中找到所有内容。