Open programmer-yang opened 4 years ago
这个 Blog 我选了一个我很不熟悉的技术栈 Gatsby,这应该算是就是跳出舒适圈吧。
先说说我的诉求,我希望我的 Blog 可控性比较高,这样方便我做一些自己想做的事情。然后我希望它尽可能的简洁跟简单,个人有点极简主义。然后我希望 Blog 的内容使用 MarkDown 编写,最后我希望它可以自动部署,我 push 到 Github 就可以自动发布。
好吧,就这些,让我们开始吧。
Gatsby 是一个很优秀的基于 React 的开源架构,使用它,你可以很简单很快速构建你的网站,它已经帮你做了很多事情,比如静态化页面、统一的数据获取方式等。我很久前就有学习它的计划,但一直搁置,这次我选择使用它。
使用 Gatsby 跟我使用之前的 React 架构最大的区别应该是在数据资源层上,Gatsby 有一个内置的数据层,是基于 GraphQL 的,这个数据层包含了你开发过程需要的所有资源,比如,图片、视频、JSON 数据等。GraphQL 是一种查询语言,我在几年前就开始关注,但因为使用起来需要涉及到服务端的改造(原来的理解,但现在似乎也可以独立在展示层使用),就一直停留在只会基础的使用阶段,没有深入了解,我计划会在另一篇博客中在讲讲我的理解,这里就不明细说了。
使用 Gatsby 开发 Blog 系统,markdown 文件也是一种静态资源,我们需要使用 Gatsby 的插件把 markdown 文件加载到 Gatsby 的数据层,然后在应用就可以随意的使用了。
module.exports = { plugins: [ { resolve: "gatsby-source-filesystem", options: { name: "content", path: `${__dirname}/src/content`, }, }, "gatsby-transformer-remark", ], }
我们先使用 gatsby-source-filesystem 插件把我们 markdown 文件添加到系统内,然后使用 gatsby-transformer-remark 插件把刚刚添加的内容转换为我们可以使用的数据。
当你启动了 Gatsby 的开发模式,它会自同时给你启动一个 graphql 服务,可以通过http://localhost:8001/___graphql来访问。在使用了 gatsby-transformer-remark 插件后,你会发现你的数据源里多了 allMarkdownRemark 跟 markdownRemark,一个是用来查询所有的 markdown 数据,一个是来获取单个 markdown 数据的详情
http://localhost:8001/___graphql
allMarkdownRemark
markdownRemark
Gatsby 提供了很多类似生命周期的接口,你可以使用这些接口来完成你的业务,比如在我们这个场景下,我们要使用 Gatsby 的创建页面的接口,因为我的诉求是最终通过 markdown 的方式来写 blog,那么在我每次创建一个新的 markdown 文件后,都需要把这个文件转换为一个页面。
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions const result = await graphql(` query MyQuery { allMarkdownRemark { edges { node { frontmatter { path } } } } } `) result.data.allMarkdownRemark.edges.forEach(edge => { const { node } = edge createPage({ path: node.frontmatter.path, component: path.resolve(`src/templates/post.js`), }) }) }
上面的代码就是使用 Gatsby 给我们提供 graphql,来查询到所有的 markdown 数据,然后通过 createPage 方法创建对应的页面,这样我们就可以通过路由来访问我们的页面了,这里需要注意,在创建页面的时候,我们还需要指定一个模板文件,每个页面的具体内容,我们需要在模板里再通过 markdownRemark 去查询,查询条件就是路由 path,如下所示:
export const pageQuery = graphql` query($path: String!) { markdownRemark(frontmatter: { path: { eq: $path } }) { html frontmatter { date(formatString: "YYYY MM DD") title path } } } `
然后我们就可以写我们最熟悉的组件代码了
const Templates = props => { const { markdownRemark } = props.data const { html, frontmatter } = markdownRemark return ( <div> <h1>{frontmatter.title}</h1> <h2>{frontmatter.date}</h2> <div dangerouslySetInnerHTML={{ __html: html }} /> </div> ) }
开始处理自动发布需求,虽然网上有很多类似的架构跟教程,但我觉得既然底层原理很简单,还是自己实现一个,这样比较好控制。
自动发布的核心是 Git 的 Hook 机制,在 Github 里对应的是 Settings 页面的 Webhooks 选项,可以让用户填写一个 API,在你的库发生改变的时候就自动调用里设置的 API。
然后我用 node 的 Express 在服务端运行了一个 Web 程序,通过 shelljs 这个库来执行一个写好的脚本,在脚本里做安装依赖、编译、重启 Nginx 的操作,这样看起来一个简单的自动化发布系统就做好了,虽然很简陋。
到目前为止,我的需求都已经满足了,一个干净的用 Markdown 编写的可以自动发布的 Blog 系统。其实还有很多细节跟踩坑我没细说,主要是因为我不太会把控技术细节跟描述文字之间的界线,担心太多的技术内容导致阅读体验下降。
我比较喜欢兴趣式学习方式,所以我也用这种方式来学习前端技术,就像你看到的这个 Blog,因为兴趣,我在这个过程中学习了使用 Gatsby,学习了自动发布等工作中会遇到的一些技术,我很喜欢这种方式跟节奏。
这个 Blog 我选了一个我很不熟悉的技术栈 Gatsby,这应该算是就是跳出舒适圈吧。
先说说我的诉求,我希望我的 Blog 可控性比较高,这样方便我做一些自己想做的事情。然后我希望它尽可能的简洁跟简单,个人有点极简主义。然后我希望 Blog 的内容使用 MarkDown 编写,最后我希望它可以自动部署,我 push 到 Github 就可以自动发布。
好吧,就这些,让我们开始吧。
基础架构
Gatsby 是一个很优秀的基于 React 的开源架构,使用它,你可以很简单很快速构建你的网站,它已经帮你做了很多事情,比如静态化页面、统一的数据获取方式等。我很久前就有学习它的计划,但一直搁置,这次我选择使用它。
使用 Gatsby 跟我使用之前的 React 架构最大的区别应该是在数据资源层上,Gatsby 有一个内置的数据层,是基于 GraphQL 的,这个数据层包含了你开发过程需要的所有资源,比如,图片、视频、JSON 数据等。GraphQL 是一种查询语言,我在几年前就开始关注,但因为使用起来需要涉及到服务端的改造(原来的理解,但现在似乎也可以独立在展示层使用),就一直停留在只会基础的使用阶段,没有深入了解,我计划会在另一篇博客中在讲讲我的理解,这里就不明细说了。
Markdown
使用 Gatsby 开发 Blog 系统,markdown 文件也是一种静态资源,我们需要使用 Gatsby 的插件把 markdown 文件加载到 Gatsby 的数据层,然后在应用就可以随意的使用了。
我们先使用 gatsby-source-filesystem 插件把我们 markdown 文件添加到系统内,然后使用 gatsby-transformer-remark 插件把刚刚添加的内容转换为我们可以使用的数据。
当你启动了 Gatsby 的开发模式,它会自同时给你启动一个 graphql 服务,可以通过
http://localhost:8001/___graphql
来访问。在使用了 gatsby-transformer-remark 插件后,你会发现你的数据源里多了allMarkdownRemark
跟markdownRemark
,一个是用来查询所有的 markdown 数据,一个是来获取单个 markdown 数据的详情Gatsby 提供了很多类似生命周期的接口,你可以使用这些接口来完成你的业务,比如在我们这个场景下,我们要使用 Gatsby 的创建页面的接口,因为我的诉求是最终通过 markdown 的方式来写 blog,那么在我每次创建一个新的 markdown 文件后,都需要把这个文件转换为一个页面。
上面的代码就是使用 Gatsby 给我们提供 graphql,来查询到所有的 markdown 数据,然后通过 createPage 方法创建对应的页面,这样我们就可以通过路由来访问我们的页面了,这里需要注意,在创建页面的时候,我们还需要指定一个模板文件,每个页面的具体内容,我们需要在模板里再通过 markdownRemark 去查询,查询条件就是路由 path,如下所示:
然后我们就可以写我们最熟悉的组件代码了
自动发布
开始处理自动发布需求,虽然网上有很多类似的架构跟教程,但我觉得既然底层原理很简单,还是自己实现一个,这样比较好控制。
自动发布的核心是 Git 的 Hook 机制,在 Github 里对应的是 Settings 页面的 Webhooks 选项,可以让用户填写一个 API,在你的库发生改变的时候就自动调用里设置的 API。
然后我用 node 的 Express 在服务端运行了一个 Web 程序,通过 shelljs 这个库来执行一个写好的脚本,在脚本里做安装依赖、编译、重启 Nginx 的操作,这样看起来一个简单的自动化发布系统就做好了,虽然很简陋。
总结
到目前为止,我的需求都已经满足了,一个干净的用 Markdown 编写的可以自动发布的 Blog 系统。其实还有很多细节跟踩坑我没细说,主要是因为我不太会把控技术细节跟描述文字之间的界线,担心太多的技术内容导致阅读体验下降。
我比较喜欢兴趣式学习方式,所以我也用这种方式来学习前端技术,就像你看到的这个 Blog,因为兴趣,我在这个过程中学习了使用 Gatsby,学习了自动发布等工作中会遇到的一些技术,我很喜欢这种方式跟节奏。