Gatsby精粹,面向未來的blog
緣起
我原先是使用的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種1. 文件數據2. 配置數據
通過插件實現
gatsby-source-filesystem
讀本地文件列表,
query{allFile{edges{node{relativePathprettySizeextensionbirthTime(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 的數據來創建文章詳情頁
constresult=awaitgraphql(`{allMarkdownRemark(......如上}`)//獲取md數據constposts=result.data.allMarkdownRemark.edgesconstblogPost=path.resolve(`./src/templates/blog-post.js`)//創建詳情頁posts.forEach((post,index)=>{constprevious=index===posts.length-1?null:posts[index+1].nodeconstnext=index===0?null:posts[index-1].nodecreatePage({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/*/importReactfrom"react"importPropTypesfrom"prop-types"importHelmetfrom"react-helmet"import{useStaticQuery,graphql}from"gatsby"functionSEO({description,lang,meta,title,tags}){const{site}=useStaticQuery(graphql`query {site {siteMetadata {titledescriptionauthorkeywords}}}`)constmetaDescription=description||site.siteMetadata.descriptionreturn(<HelmethtmlAttributes={{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,}exportdefaultSEO
以上是我的範例
然後把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 ...... , 往上扔就可以了
這裡鏈一個我的部署方式
About
- 求star ⭐️
倉庫地址: