JAMStack
我很讨厌这种概念含糊不清的新生词汇。但是当你想要交流的时候,又必须给它一个名称。本文不打算用过多的篇幅介绍 JAMStack。下面是有用的链接&引用,可以帮助你更好的理解这种理念。
技术雷达 vol 21
许多年前从手机原生开发兴起的后端即服务开发模式,现在在Web开发上变得流行起来。我们将这种集合了静态站点生成和利用第三方API进行客户端渲染的框架被称为JAMstack(JAM代表JavaScript,API 和 Markup),例如Gatsby.js。这种方式之所以能给用户提供丰富的体验,主要依靠的是API和SaaS。因为HTML不管是在网页浏览器中还是在构建时渲染,它的部署模型和全静态生成的网站是一样的,共同的好处是服务端的攻击面很小,而使用很少的资源可以获得极好的性能。事实上,像这种在部署上对内容发布网络(CDN)非常友好的技术,我们开玩笑想把它称为CDN优先应用程序。
定性的来说它是一种开发架构,由 Netlify 的提出并且实现,同样 Netlify 也提供部分对应的服务。
Gatsby
关于 Gatsby 的介绍,上一篇文章中有提到一些,这里不再赘述。
技术雷达 vol 21
Gatsby.js是一个用于编写JAMstack架构风格网络应用的框架。应用的一部分在构建时生成并且以静态站点的形式进行部署。剩余的功能以渐进式网络应用的方式进行实现并运行在浏览器中。这些应用无需服务端代码即可运行。通常来说,渐进式网络应用会通过调用第三方API,或者现成的SaaS解决方案实现内容管理等功能。在Gatsby.js的例子中,所有的客户端和构建代码都是用React编写。框架包含了一些优化来让程序运行得更快。它将代码与数据分离来最大程度地减少加载时间,并且通过在应用内跳转时预先加载资源来提高性能。接口通过GraphQL进行调用并且通过一些插件来简化和现有服务的集成。
广而告之
📢 GatsbyJS 简体中文文档目前正在翻译中,欢迎大家加入翻译小组 🎉 🎉 🎉
Notion
Notion 引入了 block-styled 的编辑模式。万物皆 block 的理念贯穿于整个应用中。当你使用 Notion 时,会有一种玩乐高、我的世界的感觉。这种 block 的模式能激发使用者的创造力。sspai 上一堆 Notion 吹,这里我就不吹了。
喜欢 Notion 的人,大都不会吝啬他的溢美之词。下面是 Jamie(notion-py 作者) 的彩虹🌈屁。
Notion was no longer just a productivity tool. It was now a general-purpose widget-rich responsive UI layer and data store that could serve as a dashboard, control panel, task manager, or a CRM system with mail-merge. It’s the holy grail of API-lovers: a central system, with a great UI and flexible schemas, into which all-the-things can be integrated.
我非常赞同 Jamie 的观点,这也是我喜欢 Notion Database 的原因 ,程序员懂得都懂。
Database 是 Notion 2.0 推出的功能,在此之前 Notion 跟其它的笔记软件比起来并没有太大的优势。
Notion Database 提供了数据存储服务 & API(非官方)。至此为止 JAMStack 的要素齐全了。
- [x] Javascript —— gatsby
- [x] API —— notion
- [x] Markup —— gatsby
让我们看看这些东西混在一起,能起什么样的化学反应。下面是我基于 Notion 的数据服务造的一些轮子。
- gine-blog —— 个人博客
block-styled 的编辑器写作体验很好。Database 可以结构化地组织数据。公开页面,即可享受图床服务。在 Notion 中我通过 Database 来组织博文,gine-blog 在 build 时,会拉取 Notion Database 中的数据,构建出一个静态站点。博客托管在 Netlify 上,每当我写完文章后,我只需要向 Netlify 发用一个 POST 请求,告诉它重新构建我的站点,既可以完成文章的发布。为此我还写了个 Chrome 的插件,它可以帮助我发送 POST 请求(构建站点),在 Notion 中完成一站式的操作:从写作到发布,我都无需离开 Notion 页面。
- phos —— PWA 音乐播放器
网易云灰掉的歌(还有越来越臃肿的 app),让我转投了 Spotify 。但是 Spotify 也没法完全解决版权问题。流媒体服务带来便利的同时,也让我们失去了很多自由。自建仿佛是最好的出路,于是乎便有了这个项目。Notion Database 存储歌曲数据,PWA 提供跨平台的使用体验。其中绝大部分歌曲直接使用网易云的音源,对于网易云没有版权的歌曲,可以使用 youtube 音源替换,都没有的可以去找一些网络资源,然后上传到 notion 的音乐表中。 《跳舞的梵谷》 这张专辑是我在网易云买的,下载 ncm 后转码为 mp3 上传到 Notion 表中。
渐进策略:网易云 > youtube > 购买数字音频 / 下载网络资源上传到 Notion
写 Phos 时,我意识到数据服务+PWA 离线应用的模式非常讨人喜欢,即它没有隐私和版权的问题,并且是跨平台的。就好比多年前的本地播放器,它虽然没有集成云服务,无法多端同步。但是它就是一个纯粹的播放器,做它份内的事情,绝不越界。
$$ 服务 = 数据 + 应用 $$
我希望未来的服务可以像这样拆分,服务不再跟服务商耦合(现在的服务商即掌握数据又掌握应用的发布),数据是自己的,原始数据是对用户可见的。可以有多个数据服务商,可以有多个应用。我选择我喜欢的,不是非要去吃某一陀屎。
我以为我发现了什么了不得的新趋势,搜索一番。原来我们的李爵士在十年前就提出了这样的观点:
Raw Data Now!
后来发展成了 Solid 项目,感兴趣的可以看一看。Solid 似乎是一种反商业模式的模式,可能很难取得大的进展。不过我喜欢这种愿景。
https://www.youtube.com/watch?v=OM6XIICm_qo
实践
看了上面这么多,基于 Notion 开发应用是种怎样的体验?为什么不自己试一试一下呢。
下面的实践,会引导读者构建一个展示博文&书单的站点,它可以作为个人博客的基础。
前置技能
- 掌握基本的 Javascript + HTML + CSS
- 接触过 React 开发
开发环境
- node
- npm / yarn
新手包
Notion API 尚未正式推出(已经鸽了好几年了),可以使用非官方的 API(基于 Web 版网络请求的封装)。我为 Notion 的 Database 专门写了API Wrapper —— notabase
,它可以让你使用 Javascript 与 Notion Database 中数据交互。然后基于 notabase
构建了数据源插件 —— gatsby-source-notion-database
,方便在 Gatsby 中使用。
这里有一个stater 可以帮你快速搭建起开发环境。
- 通过 gatsby-cli 快速搭建 starter
如果你已经安装了 gatsby-cli ,可以使用下列命令,快速获取 starter。
gatsby new my-gatsby-notion-site https://github.com/mayneyao/gatsby-starter-notion
- 或者先获取源码,然后再安装依赖。
git clone https://github.com/mayneyao/gatsby-starter-notion
cd gatsby-starter-notion
yarn // or npm install
安装完依赖后, yarn develop
会在你本机的 8000 端口,开启一个开发服务器。访问 http://localhost:8000 我们会看到一个类似这样的站点。
https://gatsby-stater-notion.netlify.com/
至此为止,一个用 Notion 和 Gatsby 搭建的站点就诞生了🎉 。
这篇文章不打算一步一步的教你怎么用 Gatbsy,关于如何使用 gatbsy 你应该去查阅它的官方文档。
https://www.gatsbyjs.com/docs/quick-start/
下面我会介绍建站过程中几个重要的步骤。
建立数据库
在 Notion 中建立 Database 页面,可以理解为 Notion 中的一个 Database page 映射数据库中的一张表。在此之前你需要构思下 schema 该如何设计,不用太过谨慎,Notion 的 Database 是十分灵活的,后面怎么修改都可以,不必考虑数据之间的约束和完整性,这使得你可以快速地验证想法。
这里有个模板,你可以克隆到自己的 Notion 中。
https://www.notion.so/mayne/gatsby-starter-notion-2c5e3d685aa341088d4cd8daca52fcc2
此页面包含了2张表格
- posts —— 文章表
- title —— 文章标题
- tags —— 文章标签
- books —— 文章可能关联了某本图书
- status —— 文章状态。一个 idea,或者正在写,或者已经发布。
- publish_date —— 发布时间
- books —— 书单表
- title —— 图书标题
- cover —— 图书封面
- status —— 状态。在读,已读,未读。
- comment —— 如何评价这本书
- posts —— 和这本书有关联的文章。
文章表和书单表是相互关联的,例如我看了《流畅的 Python》这本书,我有一些感悟,因此我写了一遍赞美 Python 的文章。
连接 Notion & Gatsby
// gatsby-config.js
{
resolve: `gatsby-source-notion-database`,
options: {
sourceConfig: [
{
name: 'posts',
table: 'https://www.notion.so/4b50defc60ce4e89a6539f511d9d946f?v=8e71dde4479040b5a3e6ca0d91d3d8e6',
cacheType: 'html'
},
{
name: 'books',
table: 'https://www.notion.so/4ae9328e650945eb9adbd882b3b453d3?v=0966bdbd0645437cbcc62e6a933e241c',
cacheType: 'static'
}
]
}
},
在 gatsby-config.js
的 plugins 中,完成 gatsby-source-notion-database
数据源插件的配置。
cacheType
- static
表格数据会转化成 graphql 节点 ,本地开发时可以在 http://localhost:8000/___graphql 中查看调试。
- html
在 static 的基础上,将记录对应页面的 html 缓存下来(使用 Puppeteer 抓取页面 HTML )。可通过 html 字段访问。
- dynamic
数据不会在 build 时候存储,仅记录表格 meta 信息,方便后续在页面中动态获取数据。
运行 yarn develop
时,gatsby-source-notion-database
会将指定 Notion Database 中的数据全部拉取下来,转化为 GraphQL 的数据节点。
探索 Gatsby 中的 GraphQL 数据
开发服务器开启后,我们可以在本地的 8000 端口,查看数据。访问 http://localhost:8000/___graphql
你不了解 GraphQL 也没有关系。通过与左边的 Explorer 交互,可以快速生成查询语句,查询出我们想要的数据。整个过程非常自然、简单。
下图中,查询出了所有已发布的文章数据,并且文章数据中包含了关联的书籍数据。这些信息适用于在列表页中展示。
我们可以通过 html 字段访问文章的 html 内容,在后面的文章详情页中会使用到它。
query MyQuery {
allPosts(filter: {status: {eq: "published"}}) {
nodes {
title
tags
status
publish_date(fromNow: false)
books {
title
slug
cover
}
}
}
}
数据 > UI
数据已经有了,接下来在页面中渲染出来。对于 React 用户来说,这一步是应该是轻车熟路了。
//src/pages/index.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import PostItem from "../components/postItem"
const IndexPage = (props) => {
const { data: { allPosts } } = props
return (
<Layout>
<SEO title="My Posts" />
{
allPosts.nodes.map(node => <PostItem data={node} />)
}
</Layout>
)
}
export default IndexPage
export const query = graphql`
query {
allPosts(filter: {status: {eq: "published"}}) {
nodes {
title
tags
status
slug
publish_date(fromNow: false)
books {
title
slug
cover
}
}
}
}
`
小结
至此为止,我们回顾一下整个过程。
- 在 Notion 中设计 Database 表格。
- 使用
gatsby-source-notion-database
数据源插件,将 Notion Database 中的数据转化为 GraphQL 节点数据。 - 在 GraphQL Explorer 中探索要想要查询的数据。构建出查询语句。
- 在 UI 构建中,使用查询语句,得到想要的数据,再将数据渲染成页面。
整体的过程就是这样子。如果你恰好是 Notion 用户,又了解前端开发。那么使用 Notion 作为 CMS,使用 Gatsby 构建现代化的站点,整个过程是水到渠成的。
总结
JAMStack 是 Serverless 中一种不错的实践。其最大的优势是降低了开发&运维成本。
如果是以前,我要搭建个人博客,我要先去买服务器,然后配置 LAMP,WordPress。一套折腾下来,人都累死。如果想要服务高可用,我需要掌握服务器/数据库运维、WordPress 配置等等一系列的知识,其中任何一环出现问题,都会让我的站点跑不起来。
而现在,服务器、数据库都不用我操心了,每一个 SaSS 服务都能保证高可用,这是付费的结果。将那些乱七八糟的"脏活"交给专业的人去做。这使得开发可以更加关注应用本身的设计,带来更好的使用体验,也能提高开发效率。这种趋势也十分符合 Unix 哲学和社会分工的理论。
Do One Thing and Do It Well
使用服务远比自建要好,除非服务达不到要求。这就跟造轮子一样,如果有现成的轮子,为什么不用呢?请把专门的事情交给专业的人去做。绝大多数公司都达不到 AWS 的体量,没必要什么都自己整一套,为什么不试试神奇的 AWS(或同类服务) 呢,是认为自己公司能活得比 AWS 更久嘛。
Serverless 的趋势对个人开发者是十分友好的。它降低了运维成本,提高了开发效率,从 idea 到产品,可以快速试错。专注精力投入到产品的设计和交互上,赢取更多用户的青睐。
参见
- 技术雷达 vol 21
https://assets.thoughtworks.com/assets/technology-radar-vol-21-cn.pdf
- gatsby-starter-notion 仓库
https://github.com/mayneyao/gatsby-starter-notion
- gine-blog
- Phos 仓库
https://github.com/mayneyao/phos
- notabase 仓库
https://github.com/mayneyao/notabase
- gatsby-source-notion-database 仓库