基於Gatsby的React靜態化實踐
Gatsby是一個令人難以置信的靜態站點生成器,它允許使用React作為渲染引擎來搭建一個靜態站點。其原理就是在構建時通過伺服器端渲染將動態的 React 組件呈現為靜態 HTML 內容
Gatsby最近發布了v1.0.0,推出了很多新特性。包括(但不限於)使用GraphQL創建內容查詢的能力,與各種cms集成——包括 WordPress、Contentful、Drupal 等等。還有基於路由的代碼分布使得用戶體驗更佳。在這次分享中,我們將簡單探討Gatsby 和一些新特性,並創建一個靜態博客。
一、起步
1.安裝cli
npminstall -g gatsby-cli
Gatsby帶有一個很好的 CLI ,它包含了一個工作站點的搭建功能,以及幫助開發該站點的命令
gatsby newfirst-blog && cd $_
該命令將創建文件夾 first-blog,然後進入該目錄。至此一個可供開發的環境已經搭建好了。Gatsby的 CLI 包含了許多常見的開發特性,比如 gatsbybuild (構建一個生產、靜態生成的項目版本)、gatsbydevelop(啟動一個熱載入的web開發伺服器)等等。
二、添加必要的插件
Gatsby支持使用豐富的插件,很多非常有用的插件都是為了完成普通任務而編寫的。插件可以分為三個主要類別:功能( functional )插件、源( source )插件和轉換器( transformer )插件
1.功能插件
功能插件用來實現某些功能(離線支持,生成一個站點地圖等等)或者用來擴展了 Gatsby 的 webpack 配置,增加了對 Typescript、Sass 等的支持。 對於這個特定的博客文章,我們想要一個單頁面應用的感覺(沒有頁面重載),以及在head 標籤中動態更改title標籤的能力。正如所提到的,Gatsby 插件的生態系統是豐富的、充滿活力的,而且還在不斷增長,所以通常一個已經存在的插件,可以解決你想要解決的特定問題。為了解決我們想要的這個博客的功能,我們將使用以下插件:
使用下面命令:
npm i -Sgatsby-plugin-catch-links gatsby-plugin-react-helmet
在安裝了這些功能插件之後,我們將編輯gatsby-config.js(Gatsby 在構建時載入指定插件的公開功能)。
module.exports= {
siteMetadata: {
title: `Bingo"s blog`,
author: `wangjun`,
},
plugins: [
"gatsby-plugin-catch-links",
"gatsby-plugin-react-helmet",
],
}
我們現在還可以編輯網站 head 標籤,同時還可以實現一個無需重新載入的單頁面應用。現在,讓我們通過實現一個源插件來增強基本功能,該插件可以實現從本地文件系統載入博客文章。
2.源插件
源插件創建節點,然後通過一個轉換器插件將其轉換為可用的格式。例如,一個典型的工作流通常需要使用gatsby-source-filesystem它從磁碟上載入文件,例如Markdown 文件,然後指定一個 Markdown 轉換器將 Markdown 轉換成 HTML 。 因為博客的大部分內容都使用 Markdown 格式,讓我們添加gatsby-source-filesystem,與我們之前的步驟類似,我們將安裝插件,然後將其注入到我們的 gatsby-config.js,像這樣:
npm i -Sgatsby-source-filesystem
module.exports= {
// previous configuration
plugins: [
...
{
resolve: `gatsby-source-filesystem`,
options: {
path: `$/src/pages`,
name: `pages`,
},
}
...
]
}
3.轉換器插件
正如前面提到的,轉換器插件採用了一些底層的數據格式,這種格式在當前的表單中是不可用的(Markdown,json,yaml等),我們可以用 GraphQL 查詢把它轉換成 Gatsby 能夠理解的格式。filesystem 源插件將從我們的文件系統中載入文件節點(如 Markdown ),然後 Markdown 轉換器將接管並轉換為可用的 HTML 。我們將只使用一個轉換器插件(用於 Markdown )。
安裝對應插件:
npm i -Sgatsby-transformer-remark gatsby-remark-images
編輯 gatsby-config.js
module.exports= {
// previous setup
plugins: [
...
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
{
resolve:"gatsby-remark-images",
options: {
maxWidth: 960,
linkImagesToOriginal:false
...
]
};
四、書寫第一個Markdown文章
我們先前配置的 gatsby-source-filesystem 插件希望我們的內容能夠放在src/pages。Gatsby 在命名規範方面並沒有什麼規定,但博客文章的一個典型做法是給文件夾起個類似MM-DD-YYYY-title的名字,例如03-01-2018-hello-world。讓我們創建一個文件夾src/pages/03-01-2018-getting-started,並創建index. md 。這個Markdown文件的內容將是我們的博客文章:
---
path:"/hello-gatsby"
date:"2018-01-03T17:12:33.962Z"
title:"My First Gatsby Post"
---
Ooooops,my first blog post!
被包含在橫線里的部分是什麼?這就是所謂的frontmatter,而這部分內容可以供 React 組件使用(例如path,date,title等等)你可以添加其他的數據,因此,你可以自由地進行實驗,找到必要的信息,以實現一個理想的博客系統,供你使用。重要的一點是,當我們動態創建頁面來指定頁面時,path將會被用到識別路由。在這個例子里http://localhost:8000/hello-gatsby將是這個文件的路徑。現在我們已經創建了一個帶有frontmatter和一些內容的博客文章,我們可以開始編寫一些可以顯示這些數據的 React 組件。
五、創建React模板
創建一個 src/templates/blog-post.js文件
importReact from "react";
importHelmet from "react-helmet";
exportdefault function Template({
data // this prop will be injected by theGraphQL query
}) {
const { markdownRemark: post } = data;
return (
);
}
看到上面,你會想什麼是markdownRemark?這個數據支持從何而來?這些問題,讓我們通過編寫一個GraphQL查詢來回答,以便為我們的組件添加內容。
六、編寫一個 GraphQL 查詢
在 Template 聲明下面,我們將添加一個 GraphQL 查詢。這是 Gatsby 的一個非常強大的工具。這讓我們可以很簡單地挑選出我們想要展示給我們的博客文章的數據片段。我們的查詢選擇的每個數據都將通過我們前面指定的數據屬性注入。
exportconst pageQuery = graphql`
query BlogPostByPath($path: String!) {
markdownRemark(frontmatter: { path: { eq:$path } }) {
html
frontmatter {
date(formatString: "MMMM DD,YYYY")
path
title
}
}
}
`;
七、創建靜態頁面
Gatsby開放了一個gatsby-node.js文件,它允許創建動態頁面這樣的功能(博客文章頁!),擴展 babel 或 webpack 配置,修改所創建的節點或頁面等。在這個文件中發現的每一個導出都將由 Gatsby 分析。Gatsby詳細地介紹了它的Node API規範。但是,我們這裡只關心這個實例中的一個特定的APIcreatePages。
const path= require("path");
exports.createPages= ({ boundActionCreators, graphql }) => {
/*
*使用了createPage激活了boundActionCreators,Gatsby在內部使用Redux來管理其狀態,
* boundActionCreators僅僅是Gatsby創造的一個action
*/
const { createPage } = boundActionCreators;
//獲取創建的blogPostTemplate的路徑
const blogPostTemplate =path.resolve(`src/templates/blog-post.js`);
//查詢文章
//構造GraphQL查詢,它將獲取所有的Markdown貼子
// excerpt用於預覽一個簡短的代碼片段
return graphql(`{
allMarkdownRemark(
sort: { order: DESC, fields:[frontmatter___date] }
limit: 1000
) {
edges {
node {
excerpt(pruneLength: 250)
html
id
frontmatter {
date
path
title
}
}
}
}
}`)
.then(result => {
if (result.errors) {
returnPromise.reject(result.errors);
}
//創建頁面
.forEach(({ node }) => {
createPage({
component:blogPostTemplate,
context: {
test:`666666`
} // additional data can bepassed via context
});
});
});
}
我們現在得到了一個 Promise 的 graphql 查詢。實際的貼子可以通過路徑 result.data.allMarkdownRemark.edges 獲得。我們將使用這些數據來構建一個包含 Gatsby 的頁面。我們的 GraphQL「形狀」直接反映在這個數據對象中,因此,當我們在GraphQL博客文章模板中查詢時,我們從該查詢中提取的每個屬性都將可用。createPage API接受一個需要定義path和component屬性的對象,我們已經在上面做過了。此外,可以使用可選屬性context來注入數據並使其可用於博客文章模板組件通過注入props(用各種 props 來查看每一個可用的 prop!)每一次我們構建 Gatsby 時, createPage 將被調用,Gatsby 將會創建一個靜態的 HTML 文件路徑根據我們在帖子的前面專門寫的 frontmatter。GraphQL查詢的數據將注入到 stringified 和 parsed 後的 React 模板。我們可以在這時運行 npm run develop 然後打開其中一個文章http://localhost:8000/hello-gatsby6
八、創建博客列表
創造一個 src/pages/tags.js 文件
importReact from "react";
importLink from "gatsby-link";
importHelmet from "react-helmet";
exportdefault function Index({
data
}) {
const { edges: posts } =data.allMarkdownRemark;
return (
return (
);
})}
);
}
exportconst pageQuery = graphql`
query IndexQuery {
allMarkdownRemark(sort: { order: DESC,fields: [frontmatter___date] }) {
edges {
node {
excerpt(pruneLength: 250)
id
frontmatter {
title
date(formatString: "MMMM DD,YYYY")
path
至此,一個簡單的博客文章站點就完成了,隨著我們對 Gatsby 及其API的探索,你應該感到有能力開始充分利用 Gatsby 的潛力,博客僅僅是一個起點;Gatsby 豐富的生態系統、可擴展的 API 和高級的查詢功能為構建真正令人難以置信的高性能站點提供了強大的工具集。
Links


※中國在遙遠的海外有一處領土?景色獨特還免簽,愛旅遊的人幸福了
TAG:全球大搜羅 |