当前位置: 首页 > news >正文

Gatsby精粹,面向未来的blog

缘起

我原先是使用的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

___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 实现 自动化部署:https://juejin.im/post/5e19d47e6fb9a0300c54ce09

About

我的Gatsby Blog 地址 : http://new.ruocuan.cn

  • 求star ⭐️ 🙏🙏🙏

仓库地址: https://github.com/Chad97/my-Gatsby-Blog

相关文章:

  • shell基本指南
  • create-react-app 没有[src] 文件夹(记一次问题)
  • antdv4 升级指北
  • [助力job]React-mode[进阶] (React模式梳理 )
  • 记-vue vue.config.js 配置webpack全局变量
  • 浅谈前端架构自动化-cdn刷新预热自动化脚本
  • 了不起的certbot申请免费SSL证书
  • 记-react-connect中使用forwardRef 问题。
  • ES2020(ES11)新特性
  • 新版 Chrome浏览器在 http协议下无法获取到摄像头、麦克风权限
  • Monorepo[单一代码库] 与MicroService[微服务] 架构
  • 搭建私有npm构建JSSDK
  • Docker 部署 Flask
  • Informix 索引禁用期间数据变化,重启启用后索引的变化情况
  • informix数据库自动备份脚本
  • .pyc 想到的一些问题
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 【前端学习】-粗谈选择器
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • Bootstrap JS插件Alert源码分析
  • CentOS6 编译安装 redis-3.2.3
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • emacs初体验
  • express.js的介绍及使用
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • java 多线程基础, 我觉得还是有必要看看的
  • JavaScript 基本功--面试宝典
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JavaScript函数式编程(一)
  • Mac转Windows的拯救指南
  • magento 货币换算
  • Sequelize 中文文档 v4 - Getting started - 入门
  • swift基础之_对象 实例方法 对象方法。
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • 汉诺塔算法
  • 简单易用的leetcode开发测试工具(npm)
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 容器服务kubernetes弹性伸缩高级用法
  • 什么软件可以剪辑音乐?
  • 数据可视化之 Sankey 桑基图的实现
  • 双管齐下,VMware的容器新战略
  • 学习笔记:对象,原型和继承(1)
  • 一道闭包题引发的思考
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 阿里云ACE认证学习知识点梳理
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​人工智能书单(数学基础篇)
  • # Panda3d 碰撞检测系统介绍
  • #define用法
  • #stm32驱动外设模块总结w5500模块
  • (04)odoo视图操作
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (Git) gitignore基础使用
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像