Gatsby精粹,面向未來的blog

Gatsby精粹,面向未來的blog

貼一個我的新blog地址new.ruoduan.cn

舊的

緣起

我原先是使用的hexo的,這裡我們從hexo ==> Gatsby的原因如下:

  1. 都是靜態頁面框架,SEO,部署等,靜態頁面的優勢
  2. 使用現代化框架開發—— React ,可以不斷的迭代
  3. 社區資源成熟,目前Gatsby的插件已經非常成熟鏈接
  4. 性能強悍,相比其他的靜態頁面框架,Gatsby的性能比較出眾
  5. 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的倒序排序,還吧時間格式化了以下,它能做的遠不止這些還包括sortfilterskiplimit等參數對數據做處理.詳情可看文檔

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

兩種方式,

  1. gatsby-config.js 裡配proxy,和umi 或webpack-dev-server 的類似
  2. 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

stack-overflow

是因為在打包的時候runtime 並沒有page 對象,解決這個問題有2中方案

  1. 在使用的地方判斷當前有沒有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

我的Gatsby Blog地址

  • 求star ⭐️

倉庫地址

What do you think?

Written by marketer

除了SSR,就沒有別的辦法了嗎?

如何掌握React 的秘密武器:Gatsby