緣起
我原先是使用的hexo
的,這裏我們從hexo ==> Gatsby的原因如下:
- 都是靜態頁面框架,SEO,部署等,靜態頁面的優勢
- 使用現代化框架開發 —— React ,可以不斷的迭代
- 社區資源成熟,目前Gatsby的插件已經非常成熟 鏈接
- 性能強悍,相比其他的靜態頁面框架,Gatsby的性能比較出衆
- GraphQL 來請求數據, 靈活 優雅,待會介紹
install
安裝全局 gastby 命令行,通過這個初始化腳手架。
yarn global add gastby-cli
script
- develop
- build
- serve
結構-範式
├── content
├── gatsby-browser.js
├── gatsby-config.js // 主要配置文件
├── gatsby-node.js // 視圖層配置
├── package.json
├── public
├── src
├── components // 組件
├── pages // 頁面文件
├── templates // 模版文件
Gatsby 採用約定式路由,page文件夾要注意,全都是採用小寫命名,例如:
about.js ==> http://localhost/about/
另外在生產頁面的時候 createPage
可以手動設置路由,但是還是建議遵守約定
Data
數據層,Gatsby 使用的是Graphql,文檔
Gatsby 是自帶 圖像調試界面的
http://localhost:8000/___graphql
🔥蕾絲 這樣的一個界面,稍後講解他的簡單使用
⚠️注意:可以通過右邊的Query
查詢參數,方便的一批~
在Gatsby中的數據分爲2種
- 文件數據
- 配置數據
通過插件實現
gatsby-source-filesystem
讀本地文件列表,
query {
allFile {
edges {
node {
relativePath
prettySize
extension
birthTime(fromNow: true)
}
}
}
通過 gatsby-transformer-remark 讀 markdown 文件內容
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
fields {
slug
}
frontmatter {
date(formatString: "YYYY 年 MM 月 DD 日")
title
tags
}
}
}
}
}
`
)
應該注意到了吧 我上面的 graphql 有稍許不同,我在獲取markdown的時候對他進行了排序,根據時間date 的倒序排序,
還吧時間格式化了以下,它能做的遠不止這些 還包括 sort
、filter
、skip
和 limit
等參數對數據做處理. 詳情可看文檔
Gatsby 中的數據都是通過 Promise 來實現的, 例如要拿到上面的 markdown 文件內容
可以 通過 await
或者 直接 .then (res => { ... })
—— 下面是獲取配置數據 也就是 gatsby-config.js
的數據
query {
site {
siteMetadata {
title
}
}
我的配置文件結構如👇
module.exports = {
siteMetadata: {
title: `Ruoduan' Blog`,
author: `Ruoduan`,
description: `我的介紹...`,
siteUrl: `https://github.com/Chad97`,
keywords: 'react, 前端, python, js, ',
},
},
plugins: [
安裝的插件 配置
......
],
}
一目瞭然了吧 ~~
黑魔法
在Gatsby page 頁面中想要獲取數據只需要通過:👇
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC },
) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "YYYY 年 MM 月 DD 日")
title
tags
categories
}
}
}
}
}
`
只需要 export 導出一個graphql
獲取到到數據就會就會掛載到當前頁面到 props
上,是不是很神奇 🚀🚀🚀
useStaticQuery
除了上面的方式 我們想在組件中拿到一些數據該怎麼辦呢?
Gatsby 有一種非常優雅的方式 ———— useStaticQuery
useStaticQuery 和 上面方式不同 這裏拿到的數據只存在於當前組件的 runtime,
例如下面一個組件 我要拿到所有文章標題
import { useStaticQuery, graphql } from "gatsby"
const data = useStaticQuery(graphql`
query titleQuery {
allMarkdownRemark {
edges {
node {
frontmatter {
title
}
}
}
}
}
`)
const [titleData, setTitle] = useState(data.allMarkdownRemark.edges)
useStaticQuery 必須放在組件開頭 ,也就是 數據變量之前
是不是有異曲同工之妙啊~ 👏 👏 👏
createPages
我們在面對一些重複的頁面比如 blog 文章詳情頁面 ,只是數據不一樣其他的一樣,
我們不可能每個markdown都創建一個 page 頁面,這時候 我們就需要使用createPages
創建頁面
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
三個參數:
-
path: 路由地址,我這裏使用的是文章標題
-
component: 模版
-
context: 傳遞到該頁面的數據
我這裏創建頁面是 利用 上面 獲取所有 markdown 的數據來創建文章詳情頁
const result = await graphql(
`
{
allMarkdownRemark(
...... 如上
}
`
)
// 獲取md數據
const posts = result.data.allMarkdownRemark.edges
const blogPost = path.resolve(`./src/templates/blog-post.js`)
// 創建詳情頁
posts.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
Develop Tools
- babel
.babelrc
,然後 gatsby 安裝 babel-preset-gatsby,和我們平時沒有太大差別,只是安裝的包不同罷了
- webpack
webpack 想要自定義配置
gatsby-node.js
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
......
],
},
})
}
}
stage 有分爲:
- develop
- develop-html
- build-javascript
- build-html
Other
PWA 支持
yarn add gatsby-plugin-manifest gatsby-plugin-offline
plugins: [
//...
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `Destiny'Note`,
short_name: `Destiny`,
start_url: `/`,
background_color: `#6b37bf`,
theme_color: `#6b37bf`,
display: `standalone`,
icon: `src/images/icon.png`,
},
},
`gatsby-plugin-offline` // 這個插件必須在 manifest 後面
]
proxy
兩種方式,
- gatsby-config.js 裏配 proxy,和 umi 或 webpack-dev-server 的類似
- gatsby-node.js 裏配 developMiddleware,手寫中間件
SEO
yarn add gatsby-plugin-react-helmet react-helmet
{
siteMetadata: {
// 這三個屬性必須要有
title: `Destiny'Note`,
author: `destiny`,
description: `my own blog`,
keywords: `react, graphql, gatsby`
},
plugins: [
//...
`gatsby-plugin-react-helmet`
]
}
在 src/components 下增加 seo.js 文件:
/**
* SEO component that queries for data with
* Gatsby's useStaticQuery React hook
*
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function SEO({ description, lang, meta, title, tags }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
keywords
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
tags={tags}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:tags`,
content: tags,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
SEO.defaultProps = {
lang: `zh-CN`,
meta: [],
description: `若端的技術博客`,
}
SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default SEO
以上是我的示例🌰
然後把 seo 組件添加到各個 組件||模版 or 頁面中去
每個頁面的 head
meta
title
的優化數據就是 傳入的數據
個性化 設置吧
還有一些 例如 typescript 支持什麼的 plugins哪裏搜索安裝就好了
坑
我是用的一個 npm 包中 使用了 全局對象 如 :windows document 等。
gatsby develop
的時候是沒事的
gatsby build
就會報錯 !
Import breaks Gatsby Build : WebpackError: ReferenceError: Element is not defined
是因爲 在打包的時候 runtime 並沒有 page 對象,解決這個問題有2中方案
- 在使用的地方 判斷當前 有沒有 document 對象,沒有的話就
null
不執行
typeof window !== 'undefined' && windows.open()
那如果是 我的npm 包中使用了呢? 總不能 改源碼吧,我就是遇到的這種情況,遇到這種情況就要 配置 webpack 忽略
// 忽略全局對象
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /xxx-xxxx/,
use: loaders.null(),
},
],
},
})
}
}
有些情況下 我們在 yarn add xxx
的時候會報錯
yarn add xxxx
error “pngquant pre-build test failed”
- Every time I install the package, I get the error pngquant pre-build test failed, macOS cannot install “libpng-dev”, only “libpng”
安裝 libpng 就好了 issues
部署
gatsby build
這裏就不多做 敘述了,不管是 GitHub Pages / Netlify … , 往上扔就可以了
這裏鏈一個 我的 部署方式: GitHub Hooks + nodejs 實現 自動化部署:https://juejin.im/post/5e19d47e6fb9a0300c54ce09
About
我的Gatsby Blog 地址 : http://new.ruocuan.cn
- 求star ⭐️ 🙏🙏🙏
倉庫地址: https://github.com/Chad97/my-Gatsby-Blog