Gatsby精粹,面向將來的blog

先貼個人新blog地址 ==> new.ruoduan.cn/javascript

舊的html

緣起

我原先是使用的hexo的,這裏咱們從hexo ==> Gatsby的緣由以下:前端

  1. 都是靜態頁面框架,SEO,部署等,靜態頁面的優點
  2. 使用現代化框架開發 —— React ,能夠不斷的迭代
  3. 社區資源成熟,目前Gatsby的插件已經很是成熟 連接
  4. 性能強悍,相比其餘的靜態頁面框架,Gatsby的性能比較出衆
  5. GraphQL 來請求數據, 靈活 優雅,待會介紹

install

安裝全局 gastby 命令行,經過這個初始化腳手架。 yarn global add gastby-clijava

script

  • develop
  • build
  • serve

結構-範式

├── content
├── gatsby-browser.js
├── gatsby-config.js // 主要配置文件
├── gatsby-node.js // 視圖層配置
├── package.json
├── public
├── src
    ├── components // 組件
    ├── pages // 頁面文件
    ├── templates // 模版文件

複製代碼

Gatsby 採用約定式路由,page文件夾要注意,全都是採用小寫命名,例如:node

about.js ==> http://localhost/about/python

另外在生產頁面的時候 createPage 能夠手動設置路由,可是仍是建議遵照約定react

Data

數據層,Gatsby 使用的是Graphql,文檔webpack

Gatsby 是自帶 圖像調試界面的git

http://localhost:8000/___graphqles6

___graphql

🔥蕾絲 這樣的一個界面,稍後講解他的簡單使用

⚠️注意:能夠經過右邊的Query 查詢參數,方便的一批~

在Gatsby中的數據分爲2種

  1. 文件數據
  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 的倒序排序, 還吧時間格式化了如下,它能作的遠不止這些 還包括 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 的數據來建立文章詳情頁

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

兩種方式,

  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/ */

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 頁面中去

SEO-例子

每一個頁面的 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 ...... , 往上扔就能夠了

這裏鏈一個 個人 部署方式: GitHub Hooks + nodejs 實現 自動化部署:juejin.im/post/5e19d4…

About

個人Gatsby Blog 地址new.ruoduan.cn

  • 求star ⭐️ 🙏🙏🙏

倉庫地址github.com/Chad97/my-G…

相關文章
相關標籤/搜索