个人博客搭建
经过 1 个月的咕咕咕,总算把博客初步搭建好了,按照惯例先丢个链接大家有兴趣可以来逛逛: blog.mytyiluo.cn。
主要特点如下:
- Modernized - 基于 Gatsbyjs,React,Typescript 构建;
- Opinionated - 以约束优先,减少博客中的必需参数;
- Git-based - 基于 GitHub 以及 Netlify 的自动化构建/部署;
为什么不使用现有的博客框架?
之前其实一直用的是 GitBook,但说实话,GitBook 还是更加适合书籍/教程等的写作,对随笔来说还是感觉少了点功能。而且官方也表示之后不再维护命令行程序了,因此决定慢慢的从这平台迁移出来。
在这过程中,有考虑过使用 Hexo 作为博客引擎,想自己写一套主题,但无奈不习惯它的模板语法,最终还是选择了放弃。
然后,考虑到开发的难度和灵活性,决定使用基于 React 的静态网页引擎,也就是 GatsbyJS。
其中,最吸引我的便是它对多数据源的内建支持,并以 GrapQL 的形式统一提供数据,非常符合我对后期拓展的预期。此外,丰富的社区插件倒算是额外的惊喜,特别是支持 TypeScript 和 Less 对开发带来了极大的方便,支持响应式图片和 PWA 也省去了我大量的精力。
我希望的博客体验
-
在本地用 VS Code 来编写 Markdown,并将博客内容托管在 GitHub 上;
-
博客应该支持丰富的元信息,但大多数参数应该根据约定生成默认值;
例如,博客标题一般会和文件名相同;
同一文件夹下的博客应该为同一个主题; -
博客对各类代码应该有良好的展示,且支持插入多媒体内容,例如:Gist,B 站视频等;
搭建过程
废话了那么多,还是得讲些技术性的话题。
参考资料
关于 Gatsby 的参考资料其实并不需要太大,官方文档再加官方教程已经足够了。若涉及到插件的话,相应的文档和源码也都可以在 GitHub 找到。
GraphQL 数据的 TypeScript 支持
默认 GraphQL 执行的结果类型,不出意外都是 any 。但既然在使用 Ts 了,我还是希望它是强类型的变量。可问题是根据不同的查询语句返回的类型也都不一样,所以单独为每一个查询定义类型工程量太大(懒)。
解决方案就是采用现成的代码生成器:
yarn add --dev @graphql-codegen/cli @graphql-codegen/typescript
在根目录下添加配置文件 codegen.yml :
# 这里端口为 gatsby develop 的端口
schema: http://localhost:8000/___graphql
generates:
src/types.ts:
plugins:
- typescript
# 默认类型为 T | null | undefined
# 这里为了偷懒就直接改为了 T
config:
avoidOptionals: true
maybeValue: T
然后运行:
graphql-codegen --config codegen.yml
即可,我们可以在 src 文件夹中找到定义文件 types.ts 。
CSS Module 的 TypeScript 支持
CSS Module 是 Gatsby 所支持的一种样式表导入方式,其优点是在独立的 css/less 文件中编写,可以获得完美的 IDE 支持,且不同模块之间的样式不会相互干扰。
但当其导入 ts 文件中后,会被提示无法解析类型。
我采用的解决方案相对暴力,在 src 文件夹下建立一个 global.d.ts 文件:
// 若你使用的不是less的话,改成相应的后缀就行
declare module "*.less" {
const content: { [className: string]: string };
export = content;
}
如果 IDE 还不能识别其类型,可以在根目录的 tsconfig.json 中添加:
{
// ...
"typeAcquisition": {
"include": ["./src/global.d.ts"]
}
}
若还不行可以尝试重启下 IDE。
CSS Module 生成的样式名过长
默认的情况下,CSS Module 生成的样式名的格式为:
[path][name]__[local]--[hash:base64:5]
显然在多级目录镶嵌之后,其长度会是非常吓人的,而且会影响传输效率(即使用 Gzip)。
总之,我希望这样式名在生产环境下短一些,解决方案如下:
在 gatsby-config.js 中配置 gatsby-plugin-less 选项:
{
resolve: `gatsby-plugin-less`,
options: {
cssLoaderOptions: {
minifyClassNames: true,
localIdentName:
process.env.NODE_ENV === "development"
? "[path][name]__[local]--[hash:base64:5]"
: "[hash:base64:5]",
},
},
}
依赖项 sharp 安装太慢
sharp 是 gatsby-plugin-sharp 的依赖项,提供图像编辑处理的能力。
通过分析其安装过程和文档,我们可以将问题定位到 libvips 上,sharp 在 build 阶段会从 github 下载 libvips 的预编译版本(大概 14MB),但由于国内网速的原因导致其加载时间过长甚至加载失败。
那解决方案就是通过任意手段下载对应版本的 libvips 将其复制到对应的缓存目录下,一般为:
C:\Users\[你的用户名]\AppData\Roaming\npm-cache\_libvips
添加百度统计
考虑到 GA 在国内可能有些问题,这里还是选用了百度统计作为统计分析平台。同时,百度统计平台还可以主动将站点信息提交到百度搜索引擎,提高站点收录的效率。
在 Gatsby 的社区插件中已经有实现了添加百度统计的插件,但我看了下它的源码感觉挺简单的,且为了方便之后再更换其他统计平台,这里打算是自己实现一下。
首先,我们需要注册一个百度统计的账号,然后在管理界面中获取对应的代码:
根据文档说明,我们需要将这段代码添加到每个页面的<head>
中。
这里,就需要用到 gatsby-ssr.js 中的接口 onRenderBody ,具体信息可以查看文档。
代码如下:
// 因为在下方用到了JSX,所以需要导入React
var React = require("react");
exports.onRenderBody = ({ setHeadComponents }) => {
if (process.env.NODE_ENV === `production`) {
setHeadComponents([
// 这里的形式是为了异步加载
<script
key="baidu-analytics-script"
dangerouslySetInnerHTML={{
__html: `
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?ff306397dbce7dab4357bd037fa286ca";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
`
}}
/>
]);
}
};
统计博客标签
在我设置的字段中,每篇博客都会包含一个 tags,类型为 string[]。在首页中,我希望根据标签计数的降序显示计数大于 2 的标签。
其实,这个问题就相当于处理镶嵌数组,处理难度并不高,但此前往往需要写不少的代码,这里基于 lodash 的 chain 实现了一个相对“简洁”的版本:
// data 就是根据 GraphQL 得到的数据
// const data = this.props.data.statistics.nodes;
//
// Scheme 定义如下:
// statistics: allMarkdownRemark(
// filter: { fields: { name: { ne: "README" }, posted: { ne: false } } }
// ) {
// nodes {
// fields {
// topic
// tags
// }
// }
// }
const tags = _
// 包装为 chain 对象
.chain(data)
// 只需要 tags 字段
.map(e => e.fields.tags)
// 展开二维数组
.flatten()
// 对标签计数
// 这里返回的为对象 { tag: count }
.countBy()
// 筛选计数大于 2 的标签
.pickBy((value, key) => value > 2)
// 将对象转为数组
.map((value, key) => ({ tag: key, count: value }))
// 根据计数降序排列
.orderBy("count", "desc")
// 只需要 tag 字段
.map(e => e.tag)
// 解除 chain 包装
.value();
小结
至此,主要记录的是在开发阶段遇到的一些坑和小技巧。下一篇,我想简要叙述一下设计这个博客的思路,如果我还记得这个坑的话。
来源:oschina
链接:https://my.oschina.net/u/4357854/blog/3566460