当前位置: 首页 > 工具软件 > Gatsby > 使用案例 >

【Gatsby】Gatsby模式以及基本操作

孙文康
2023-12-01

前言

  • 又研究了下这玩意,终于大概理解咋回事了。
  • gatsby它自带的graphql会先收集项目的一些信息,然后做成graphql服务,包括各种文件之类,比如用插件搞得markdown或者图片文件,都是这种模式,被收集到gatsby的graphql架构中。
  • 在编写页面时,可以通过它提供的组件或者api查询graphql中存放的数据,从而渲染出来。
  • 在gatsby-node中可以做一些node上的动态渲染操作。
  • 在最后build时,graphql架构会转换成静态数据,然后生成静态网站。如果需要ssr的话,也可以同构ssr出来,这方面没去研究。
  • 在我查阅资料研究时,还发现了个吊炸天的cms serverless网站,真的太牛b了,gatsby结合这种cms网站搭建起来速度会快很多。那个网站叫contentful,配合gatsby插件,只要写个壳甚至连壳都不用写就可以轻松造网站了。
  • 安装不说了,直接看上一篇,这篇说基本使用。

Pages

  • 首先,这里路由和next以及umi类似,都是page下的文件是一个路由,可以新在pages下新增2个页面,一个index.tsx,一个page2.tsx,然后访问localhost:8000以及localhost:8000/page2,就是page下的page2.tsx可以看见页面。
  • 然后就是跳转,gatsby提供了link,我看老版本gatsby跳转还要装个插件
import { Link } from "gatsby"
...
  <Link to="/">page1</Link>
  • 这样就可以完成跳转了。使用代码跳转借助它提供的navigate
<button onClick={() => navigate("/")}>page1</button>

图片功能

  • 图片导入有3种,一种直接放到static文件夹下,一种直接进行引入,一种借助于插件进行优化,前2种没啥说的,直接说最后一种。
  • 图片我们借助于插件,插件再上一篇有。我们配置的gatsby-source-filesystem插件的图片目录为src下images,首先找个图片放到该目录下,然后试着渲染出来。
  • 我找了个test.jpg放置目录下。
  • 使用gatsby的graphql api进行查找:
const data = useStaticQuery(graphql`
  query {
    file(relativePath: { eq: "test.jpg" }) {
      childImageSharp {
        fluid {
          base64
          aspectRatio
          src
          srcSet
          sizes
        }
      }
    }
  }
`)
  • 返回这个:
{
  "data": {
    "file": {
      "childImageSharp": {
        "fluid": {
          "base64": "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEEAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAHVyMrpkAF//8QAGxAAAQQDAAAAAAAAAAAAAAAAAQADEUECEjH/2gAIAQEAAQUCcMAZwtpT/ar/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGH/8QAHBAAAgAHAAAAAAAAAAAAAAAAAAECAxESMXKR/9oACAEBAAY/Ai6LBVM4TdhH/8QAHBAAAgIDAQEAAAAAAAAAAAAAAREAIUFhcTHw/9oACAEBAAE/Ib80TfIZalCDzFM0TqfHk9fimoyEHE//2gAMAwEAAgADAAAAECcv/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EE6Q/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EE2N/8QAHRABAAICAgMAAAAAAAAAAAAAAQARITFBcVFh8P/aAAgBAQABPxC+cyXCqwfeI+IAlstrwdJBJRNdJveVD7IA2XO7aiRQK6Z//9k=",
          "aspectRatio": 2,
          "src": "/static/2a7e115bd768aad419526e39bd9f6c75/3b31f/test.jpg",
          "srcSet": "/static/2a7e115bd768aad419526e39bd9f6c75/f836f/test.jpg 200w,\n/static/2a7e115bd768aad419526e39bd9f6c75/3b31f/test.jpg 370w",
          "sizes": "(max-width: 370px) 100vw, 370px"
        }
      }
    }
  },
  "extensions": {}
}
  • 再使用gatsby-image渲染:
import Img from "gatsby-image" // to take image data and render it
 <Img
        fluid={data.file.childImageSharp.fluid}
        alt=""
      />
  • 可以发现图片已经渲染出来了,而且还有非常牛b的预渲染模糊以及延迟加载,比直接甩静态文件强多了。怪不得我看国外那些medium等网站的图片延迟渲染感觉都用的一个东西。估计就是gatsby搞的或者用Cloudinary云端服务,也是gatsby网站上推荐使用的。

MARKDOWN

  • 处理markdown文件需要安装gatsby-transformer-remark插件。还有个mdx插件,有需要自己研究,本篇不写了。
  • 这个markdown的处理模式是这样:
  • 先造个template做模板,然后md文件上标注meta信息,最后通过gatsby-node完成转换。
  • 首先安装完毕后再插件里把这玩意加上。
  • 同时还需要配置filesystem存放markdown的文件夹:
    {
      resolve: "gatsby-source-filesystem",
      options: {
        name: "content",
        path: `${__dirname}/src/docs`,
      },
    },
  • 我们在docs下建立个md文件:
---
title: yehuozhili
date: 2020-09-08
path: /markdownpage
---

This is my first Gatsby post written in Markdown!

## h1

hello 

- this is test
  • 前面这个是固定语法,然后制作template:
  • 在src下建立templates,然后做个markdown的壳:
import React from "react"
import { graphql } from "gatsby"
export default function Template({ data }: { data: any }) {
  const { markdownRemark } = data // data.markdownRemark holds your post data
  const { frontmatter, html } = markdownRemark
  return (
    <div className="blog-post">
      <h1>{frontmatter.title}</h1>
      <h2>{frontmatter.date}</h2>
      <div
        className="blog-post-content"
        dangerouslySetInnerHTML={{ __html: html }}
      />
    </div>
  )
}
export const pageQuery = graphql`
  query($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
      }
    }
  }
`
  • 其中pageQuery会导出给node模块使用,拿到的md元数据直接在template壳里渲染。
  • 下面编写node部分:
const path = require(`path`)

exports.createPages = async ({ actions, graphql }) => {
  const { createPage } = actions

  const result = await graphql(`
    {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              path
            }
          }
        }
      }
    }
  `)
  if (result.errors) {
    console.error(result.errors)
  }
  //这个查询为了拿到文件系统中提供的所有markdown匹配路径,然后通过createPage传递path渲染模板
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.frontmatter.path,
     component: path.resolve(`src/templates/index.tsx`),
    })
  })
}
  • 然后去访问http://localhost:8000/markdownpage
  • 可以看见Markdown文件已经完美渲染了。
  • 下面看一下markdown怎么渲染图片。一般那种src直接写地址就不说了,渲染图片分为模板渲染和markdown内部渲染。
  • 模板渲染需要markdown上添加字段:
---
title: yehuozhili
date: 2020-09-08
path: /markdownpage
featuredImage: ../images/test.jpg
---
  • 然后修改template的查询方法以及模板渲染:
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image" // to take image data and render it

export default function Template({ data }: { data: any }) {
  const { markdownRemark } = data // data.markdownRemark holds your post data
  const { frontmatter, html } = markdownRemark
  let featuredImgFluid = frontmatter.featuredImage.childImageSharp.fluid
  return (
    <div className="blog-post">
      <h1>{frontmatter.title}</h1>
      <h2>{frontmatter.date}</h2>
      <Img fluid={featuredImgFluid} />
      <div
        className="blog-post-content"
        dangerouslySetInnerHTML={{ __html: html }}
      />
    </div>
  )
}
export const pageQuery = graphql`
  query($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 800) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    }
  }
`
  • 这样就渲染出来了。这个适合每个markdown搞个背景图片什么的。
  • 下面看一下行内如何渲染,行内需要安装gatsby-remark-images,然后配置插件。
  • 需要配置为transformer的子插件:
 {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 800,
            },
          },
        ],
      },
    },
  • 在markdown内,即可使用正常的markdown引入图片方式引入资源:
![YEHUOZHILItest](../images/test.jpg)

404页面

  • 只要pages下搞个404.tsx就可以作为404页面。
  • 默认情况下,开发模式会用它的404代替你的自定义404,不过可以上面有个按钮可以点击预览你的404,打包后就是以你的404为准。

Layout

  • 基本上数据都打通了,其实只要我们搭个壳就行了,gatsby有个好用的插件叫gatsby-plugin-layout,这玩意相当于给匹配到路由的组件外套了层。
  • 写在layout的组件会在满足条件时总是显示。
  • layouts index.tsx:
import React, { PropsWithChildren } from "react"
function App(props: PropsWithChildren<{}>) {
  console.log(props)
  return (
    <div>
      layout
      {props.children}
    </div>
  )
}

export default (props: PropsWithChildren<{}>) => <App {...props}></App>
  • 可以访问不同页面看一下,每个页面都会显示这个。
  • 对于不同路由显示不同的壳,可以在props中进行判断,props中可以拿到路由信息,甚至可以使用gatsby-node来控制layout的context。

代码

 类似资料: