边写边学系列(四)—— Gatsby 搭建炫酷屌炸天的我的博客

前言

说来巧得不行,前两天正好买了本《唐诗三百首》附赠了一个电子书《了不得的盖茨比》,我心想如今淘宝卖书的都开始送编程书了咋呢?😄,结果人家是本小说,虽然我没读过,可是好像还颇有名。不过不要紧,做为一名前端 Coder,没读过《了不得的盖茨比》没关系,可是 《静态站领域 NB 的 Gatsby》仍是应该了解一下的。css

首先,我得认可有点标题党了,由于这个博客并不能算是炫酷屌炸天,可是确实是花了不少心思,从配色到布局到动画效果到适配,都还挺用心的;html

其次,若是又以为不错的,我也开源出来了,博客架子源码地址:Gatsby-Animate-Blog;前端

最后,我想说一下为啥选择 Gatsby,有两点缘由。第一,边写边学系列,我确实没用过 Gatsby,可是做为一个 Reacter,它的大名仍是如雷贯耳的,我的比较擅长使用 Next.js,其实博客彻底可使用 Next.js 搭建,不过 React.js 官网推荐静态站的开发使用 Gatsby,必定有它的道理,所以,做为开发者的门面 —— 我的博客,我决定尝试使用 Gatsby 来进行开发。由于是边写边学,因此,里面会尽量多的使用 Gatsby 特性来进行编写。node

博客效果图:react

博客地址git

本来是打算放在本身域名上的,结果备案没经过,我也很无奈😭,暂时先用 now 提供的域名吧。github

Gatsby 简介

就像上面说的,初识 Gatsby 我就是从 React 官网了解到的:web

官方正式介绍的三个快速搭建 React.js 的开源框架/脚手架:第一个,大名鼎鼎的 CRA(create-react-app);第二个,最流行的 React SSR 框架 —— Next.js;第三个,就是今天的主角,React Static Websites 的王者 —— Gatsby。npm

术业有专攻,既然官方一直标榜它转为静态展开发而生,那么今天就一块儿来看看它在静态站领域到底有多牛X~编程

First Project

  • 安装
npm install -g gatsby-cli
复制代码
  • 第一个项目
// 构建项目
# gatsby new gatsby-first-project
// 启动
# cd gatsby-first-project && yarn develop
复制代码

而后浏览器访问http://localhost:8000就能够看到项目启动,而 Gatsby 还为咱们额外提供了一个http://localhost:8000/__graphql查询界面。

目录结构

------
  | -- .cache
  | -- public
  | -- src
  | -- gatsby-browser.js    // 客户端相关配置
  | -- gatsby-config.js     // 基本配置文件    
  | -- gatsby-node.js       // node 相关配置文件
  | -- gatsby-ssr.js        // 服务端渲染相关配置文件 
  | ...                     // 其余文件
复制代码

除了基本的目录,就是路由页约定和四个配置文件比较有意义,其中,gatsby-config 基本每一个项目都有的,而其余三个若是没有使用到就能够删除,文章最后会单独介绍这几个重要的配置文件。

路由页约定

这个概念跟 Next.js 基本如出一辙,Gatsby 不须要咱们配置路由相关内容,而是将pages文件夹下的 js 文件名称映射为路由。

好比pages目录内容以下:

// pages
------
  | -- index.js     // 对应路径 /
  | -- about.js     // 对应路径 /about
  | -- pageA.js     // 对应路径 /pageA
  ...
复制代码

而后,Gatsby 还有一些默认的设置,好比一个404.js对应着 404 Not Found 页面。

html.js

// 啥都别说,先执行一下这行命令再说
cp .cache/default-html.js src/html.js
复制代码

这个文件是用来干啥的,Gatsby 的 html 结构就是经过这个 js 模板文件进行渲染的,好比咱们想要配置一些东西,或者提早加载一些脚本文件,就能够重写它。

咱们在文件里新增一行<meta name="author" content="luffyZh" />,查看一下:

能够看到,重写的内容生效了,就这么简单,其余的就看你们本身项目需求了~

GraphQL

Gatsby 官方推荐使用 GraphQL 进行查询,而且也配套了不少对应的插件~而且还提供了可视化查询页面。咱们运行项目后,web 端运行在8000端口的同时,http://localhost:8000/___graphql地址运行着 GraphiQL 服务,具体的我懂的也不是特别多,你们能够自行观看~

好比,咱们看看 gatsby-config.js 里面的内容:

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
    description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
    author: `@gatsbyjs`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/src/data`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
  ],
}
复制代码

其中配置了站点数据,以及各类插件的配置,而后咱们在 GraphiQL 服务里进行查询:

能够看到,结果出来了,而且这仍是动态更新的,好比咱们新添加一个 learnerData,再进行查询:

能够看到,也能查出来,固然,左侧列表中全部的内容都是能够进行查询的,里面包括整个项目各类资源配置详细信息,具体的你们能够去看官方文档说明,这里就很少赘述了,只讲一点,在这里查出来或者数据放在这里确定是要用的,那么应该怎么用呢?下面就来介绍,如何在组件里获取对应数据。

Query Data

咱们使用以下方式在页面进行数据的获取,使用内置的 graphql 查询 API,在页面组件定义查询,以后查询结果会经过属性data传递给组件,在组件就可使用该值,具体以下:

import React from 'react';
import { graphql } from 'gatsby'; // 这个是数据获取的核心

export const query = graphql`
  query PageData {
    site {
      siteMetadata {
        title
        description
        author
      }
    }
  }
`;

const QueryPage = ({ data }) => {
  const { site: { siteMetadata, learnerData } } = data;
  return <div>
    <h1>siteMetaData:</h1>
    <p>title: {siteMetadata.title}</p>
    <p>description: {siteMetadata.description}</p>
    <p>author: {siteMetadata.author}</p>
  </div>
};

export default QueryPage;
复制代码

注意,这种方式查询的 data,只有在组件内部才能进行对象取值操做,而在外部就是一个对应 id。

StaticQuery

与上面不一样,上面是将查询语句与组件分离的形式进行操做,而 StaticQuery 是 Gatsby 为咱们封装的组件,集数据查询与获取,使用以下:

import React from 'react';
import { StaticQuery, graphql } from 'gatsby';

const StaticQueryPage = () => (
  <StaticQuery
    query={graphql`
      query StaticQueryPageData {
        site {
          siteMetadata {
            title
            description
            author
          }
        }
      }
    `}
    render={
      data => {
        const { site: { siteMetadata, learnerData } } = data;
        return <div>
          <h1>StaticQueryData</h1>
          <h2>siteMetaData:</h2>
          <p>title: {siteMetadata.title}</p>
          <p>description: {siteMetadata.description}</p>
          <p>author: {siteMetadata.author}</p>
        </div>
      }
    }
  />
);

export default StaticQueryPage;
复制代码

useStaticQuery

React 自从出了 Hooks 之后,不少人趋之若鹜,都慢慢的喜欢上了,不少插件也都配套出了 useXXX hook 的 API,这里也是同样,除了上面两种方法,在页面里你还可使用useStaticQuery来进行查询,使用方式以下:

import React from "react";
import { useStaticQuery, graphql } from "gatsby";

export default () => {
  const data = useStaticQuery(graphql`
    query UseStaticQueryData {
      site {
        siteMetadata {
          title,
          description,
          author
        }
      }
    }
  `);
  const { site: { siteMetadata, learnerData } } = data;
  return (
    <div>
      <h1>UseStaticQueryData</h1>
      <h2>siteMetaData:</h2>
      <p>title: {siteMetadata.title}</p>
      <p>description: {siteMetadata.description}</p>
      <p>author: {siteMetadata.author}</p>
    </div>
  )
}
复制代码

更多

这里就只介绍上面几个页面组件级别的,若是是纯前端基本够用了,不过 Gatsby 还有更多高级用法,好比 node 端配置页面等等。关于更多内容或者 Gatsby GraphQL 相关,Gatsby 专门有一个章节,叫作 why-gatsby-uses-graphql,你们能够阅读一下。

API && 插件

简单使用下来发现,Gatsby 所谓的便捷即便由于他将本来手动作的或者本身组装的各类需求轮子都在本身的社区搞成了插件,庞大的插件系统,即插即用是它便捷的缘由,所以,就来了解一下它的一些 API 以及几个重要的插件。

Link

第一个,基本全部框架都必备的,路由部分。Gatsby 的 Link 跟通常的前端路由基本一致,没有太大区别,由于它只是对reach/router进行了包装。。

<Link to='/pageA'>Link to pageA</Link> // 前端路由
<a href='/pageA'>A tag to pageA</a>    // a 标签跳转
复制代码

固然,既然作了封装,Gatsby 的 Link 组件必定有它的独到之处,好比:activeClassNameactiveStyle,顾名思义,就是选中时的状态,若是是通常框架,这个选中状态可能须要咱们用额外的代码去控制,在 Gatsby 使用这两个类就能够了。咱们用下段代码看看效果:

// layout.css
.active {
    color: red
}

// nav.js
    <Link
      to="/"
      style={{ color: '#fff' }}
      activeClassName="active"
    >
      Home
    </Link>
    /
    <Link
      to="/about/"
      style={{ color: '#fff' }}
      activeStyle={{ color: "#000", background: '#fff' }}
    >
      About
    </Link>
复制代码

哎呀,发现activeClassName并无论用,为啥呢?仔细看了一下,原来 Link 组件使用了 style 约定了 color 样式,style 优先级要高,那么有没有其余办法呢?有,咱们看下段代码:

<Link
  to="/"
  getProps={({ isCurrent }) => {
    // the object returned here is passed to the
    // anchor element's props
    return {
      style: {
        color: isCurrent ? "red" : "#fff"
      }
    };
  }}
>
  Home
</Link>
复制代码

嗯,关于 Link 还有更多好用的功能,就不一一介绍了,能够去官方文档去看 -> Gatsby Link

gatsby-source-filesystem

这个插件是 gatsby 被引用最多的插件,通常与其余插件配合使用,好比 GraphQL 和 gatsby-node,用于设置项目的文件系统,而且还能够设置多个。

{
   resolve: `gatsby-source-filesystem`,
   options: {
     name: `images`,
     path: `${__dirname}/src/images`,
   },
   {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/src/data`,
      },
   },
 }
复制代码

好比,上面的代码,我设置了两个静态文件系统,一个是 images,一个是 data,咱们能够经过 GraphiQL 来进行查询:

既然均可以查询出来了,也就表示咱们能够在代码里使用他们。下面就简单的写个页面列出来全部的文系统静态资源文件。

import React, { Fragment } from 'react';
import { graphql, useStaticQuery } from 'gatsby';

const List = () => {
  const data = useStaticQuery(
    graphql`
      query ListQuery {
        allFile {
          edges {
            node {
              id
              name
              relativePath
              publicURL
              dir
            }
          }
        }
      }
    `
  );
  const { allFile: { edges } } = data;
  return (
    <table border='1'>
      <thead>
        <tr>
          <th>文件名</th>
          <th>所属目录</th>
          <th>预览地址</th>
        </tr>
      </thead>
      <tbody>
         渲染文件列表
      </tbody>
    </table>
  )
}

export default List;
复制代码

能够看到,确实很方便,正常来讲这都是须要后台进行大量的代码工做的,而 Gatsby 只用一个简易的插件配置再搭配上 GraphQL 语法查询就能够了,真香~其余关于插件更多能够去官网插件库查看,该插件还有其余高级功能,而且该插件也是不少插件的依赖~

Static

Gatsby 支持咱们设置静态文件引入,新建static文件夹,里面的文件会对应/filename获取,该文件夹在编译时会拷贝一份到public文件夹里,同时看到上面代码的应该也发现了,gatsby-source-filesystem这个插件也会将文件夹下面的文件存放一份到/static文件夹里咱们能够经过publicURL字段使用 GraphQL 进行查询。

import React from 'react';

const Image = () => (
  <div>
    <img alt='image' src='/gatsby-astronaut.png' />
  </div>
);

export default Image;
复制代码

Gatsby-Image

Gatsby 官方本身说的:Gatsby 网站之因此快的部分缘由,很大程度上在于图像的处理方法。Gatsby 利用的是插件gatsby-plugin-sharp和 GraphQL 配合的模式来完成图像的加载。

官方特地强调了,gatsby-image并不能代替<img/>标签,具体使用仍是得看场合。

Gatsby-Image 须要几个官方插件一块儿使用,而本地图片的加载依靠的就是上面介绍的gatsby-source-filesystem

yarn add gatsby-image gatsby-plugin-sharp gatsby-transformer-sharp gatsby-source-filesystem
复制代码

接下来就看看相关优化的插件要怎么用:

// gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: 'images',
        path: `${__dirname}/src/images/`,
      },
    },
  ],
}
复制代码
  • gatsby-image

gatsby-image解决了大型网站构建时的以下问题:

1. 将大图像调整为设计所需的大小

2. 生成多个较小的图像,以便智能手机和平板电脑不会下载桌面尺寸的图像

3. 剥离全部没必要要的元数据并优化 JPEG 和 PNG 压缩

4. 高效延迟加载图像以加快初始页面加载速度并节省带宽

5. 使用“模糊处理”技术或“跟踪的占位符” SVG 在加载图像时显示图像预览

6. 保持图片位置,以便在加载图片时您的页面不会错乱
复制代码
  • gatsby-plugin-sharp && gatsby-transformer-sharp

这两个插件都是 gatsby 基于 sharp 图像处理工具进行扩展的。具体使用就是简单的在加载图片的时候进行宽高以及质量进行设置。

上面都稀里糊涂的安装完了,咱们来看看这些插件都作了什么:

事先声明一下,由于 Gatsby 的内置约束插件系统太多了,因此文章可能充斥着不少说明性图片,没办法,我本身并不能用语言解释清楚,只能图片来讲了。

能够看到,左侧查询列表里出现了两个带有 imageSharp 关键字的字段,他们就是上面两个 sharp 插件帮咱们作的一些关于图片的一些优化。 好比咱们查询一下全部的本地优化图片:

嗯,这里有两个关键点。

  • 第一,这里面的图片就是咱们经过gatsby-source-filesystem配置的文件夹里面的全部图片,注意,只有配置了才能够。

/static文件夹下面有三个图片,配置的/src/images文件夹下有两个图片,能查到的只有images文件夹下的两张图片。

  • 第二,通过xxx-sharp插件处理过的图片是经过 GraphQL 方法建立的, 可用的图像优化有两种类型,固定图像 - fixed 和流体图像 - fluid。

那么这两种类型图片有什么区别呢?简单点,fixed 返回的是固定尺寸的图片,而 fluid 返回的是流式图片,它会根据容器宽度进行自适应。我以为仍是直接来代码实践吧:

// /page/image.js
import React from 'react';
import { useStaticQuery, graphql } from "gatsby";
import iconImage from '../images/gatsby-icon.png'; 
import Img from 'gatsby-image';

const Image = () => {
  const data = useStaticQuery(graphql`
    query {
      fixedIconImage: file(relativePath: { eq: "gatsby-icon.png" }) {
        childImageSharp {
          fixed(width: 200) {
            ...GatsbyImageSharpFixed
          }
        }
      }
      fluidIconImage: file(relativePath: { eq: "gatsby-icon.png" }) {
        childImageSharp {
          fluid {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)
  return (
    <div>
      <h1>静态引入文件</h1>
      <img alt='static-image' src='/gatsby-icon.png' />
      <h1>import 引入文件</h1>
      <img alt='import-image' src={iconImage} />
      <h1>fixed 文件</h1>
      <Img alt='fixed-image' fixed={data.fixedIconImage.childImageSharp.fixed} />
      <h1>fluid 文件</h1>
      <Img alt='fluid-image' fluid={data.fluidIconImage.childImageSharp.fluid} />
    </div>
  );
}

export default Image;

复制代码

最高级的功能,先来看看如何使用,须要经过引入gatsby-image插件,而且参数和正常的<img />标签也不同,它不接收 src 属性,而是接收对应的 fixed 或 fluid 属性,该属性就是经过 GraphQL 查询出来的:

嗯,看到了吧,fluid 类型的文件会撑满容器宽度。简要的关键点说完了,接下来得了解一下 Gatsby-Image 吹了这么半天,到底作了哪些优化,仍是用两张图片来讲明一下:

第一张图片,以 fluid 为例,查询图片的 src,第二张图片是编译过的项目会将配置事后的图片资源生成多种分辨率不一样形式(src/base64...),而且在实际运行中按需加载最优的方案。固然,这个最优是 Gatsby 帮咱们判断的。

上面这张图说得很清楚了也颇有说服力,gatsby-image经过<picture>标签来加载图片,里面有<source>标签,里面放置的是连接地址也就是上面咱们截图的内容。而下方用来显示图片的就是<img>标签,它会根据不一样设备不一样分辨率进行图片的优化加载,而且图片的加载方式是懒加载loading='lazy'

gatsby-transformer-remark

上面几个基本是 Gatsby 必用插件,讲完也就差很少了,这里由于是要搭建博客站,所以额外再介绍一个插件,由于下面也会用到,怕你们不知道就在这里介绍了。这个插件很简单,就是解析项目里的.md文件,而后咱们就能够经过 graphql 进行查询了,这样也便于进行文章内容的动态配置生成。

// In your gatsby-config.js
plugins: [
  {
    resolve: `gatsby-transformer-remark`,
    options: {
      // CommonMark mode (default: true)
      commonmark: true,
      // Footnotes mode (default: true)
      footnotes: true,
      // Pedantic mode (default: true)
      pedantic: true,
      // GitHub Flavored Markdown mode (default: true)
      gfm: true,
      // Plugins configs
      plugins: [],
    },
  },
],
复制代码

使用方式就是配置进去就行,而后咱们就会发现,Graphiql 多了两个字段:

上面咱们项目里新增了/posts文件夹,里面存放了两个.md文件,正好被查询出来了。除此以外,还能够为 Markdown 文件配置相关头部内容供使用,具体约定的格式以下:

// posts/first.md

---
title: "第一篇文章"
author: "luffyZh"
tag: "React,HTML"
date: "2020-01-12"
---

## 我是第一篇文章

> 第一篇文章
复制代码

经过插件,就会解析头部内容为frontmatter字段,里面是咱们配置好的字段属性。

Gatsby 配置文件介绍

gatsby-config.js

这个文件很好说了,任何框架任何项目都有本身的配置文件,而gatsby-config.js就是整个 Gatsby 站点的配置文件。咱们能够在里面配置网站的相关基本信息:

  • siteMetadata (object) - 站点基本信息
module.exports = {
 siteMetadata: {
   title: `Gatsby`,
   siteUrl: `https://www.gatsbyjs.org`,
   description: `Blazing fast modern site generator for React`,
 },
}
复制代码
  • plugins (array) - 插件配置
module.exports = {
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `docs`,
        path: `${__dirname}/../docs/`,
      },
    },
  ],
}
复制代码
  • pathPrefix (string) - 能够配置网站路径前缀
module.exports = {
  pathPrefix: `/blog`,
}
复制代码

这个配置场景也颇有用,那就是 Github Pages 部署项目的时候的路径问题,更多详细能够去看文档

  • polyfill (boolean) - polyfill 相关

  • mapping (object) - 比较高级,不知道怎么用。。。😄

  • proxy (object) - 代理

module.exports = {
  proxy: [
    {
      prefix: "/api",
      url: "http://dev-mysite.com",
    },
    {
      prefix: "/api2",
      url: "http://dev2-mysite.com",
    },
  ],
}
复制代码

更多查看文档

  • developMiddleware (function) 开发中间件,相似于 redux/node 中间件系统,这里我也没用过,因此不过多介绍。

gatsby-browser.js

一些浏览器相关的 API 经过在这个文件里去实现,好比一些监听路由变化,注册 serviceWorker 等等。

  • 监听路由变化
// 监听路由变化
exports.onRouteUpdate = ({ location, prevLocation }) => {
  console.log('new pathname', location.pathname)
  console.log('old pathname', prevLocation ? prevLocation.pathname : null)
};
复制代码

  • wrapPageComponent - 全局Layout 包裹页面组件,在前面代码里看到了,咱们有一个 Layout 组件,可是若是要使用,由于咱们每个页面对应一个js,也就是每个页面都要引入一下才行,这不是明智之举,一点都不优雅,诸如 Next.js 解决方案是 _app.js。Gatsby 也有解决方案,就是 gatsby-browser.js 的 wrapPageComponent。
// 由于是 Node.js,所以引入方式不是 import 
const React = require("react");
const Layout = require("./src/components/layout").default;

exports.wrapPageElement = ({ element, props }) => {
  // props provide same data to Layout as Page element will get
  // including location, data, etc - you don't need to pass it return <Layout {...props}>{element}</Layout> } 复制代码

能够看到,已经将咱们全部页面都使用 Layout 组件包裹上了。里面出现重复是由于我没有把原来代码里的 Layout 删除掉,由于只是使用方法,这么看更直观。

  • wrapRootComponent - Provider 相关

这个跟上面组件是同样的场景,只不过是用来包装根组件的,好比 redux 的 Provider,好比 ant-design 的国际化等。

// 引入 redux
const React = require("react")
const { Provider } = require("react-redux")

const createStore = require("./src/state/createStore")
const store = createStore()

exports.wrapRootElement = ({ element }) => {
  return (
    <Provider store={store}>
      {element}
    </Provider>
  )
}
复制代码

具体更多的详见browser-api

gatsby-node.js

这个配置文件里面的代码顾名思义是 node 层相关的,所以它只会在 build 期间运行一次,好比动态建立一些页面。这里有个场景能够想一下,通常 Gatsby 用来作静态站,咱们熟知的也就是我的博客,那么庞大的文章列表难道要手动维护?确定不合理,所以就适合在 node 层动态生成文章列表文章内容页等等。

前面说过了,Gatsby会把src/pages目录下的文件所有渲染成路由,这是一个约定,可是不免会这么一种场景,就是页面是带参数动态生成的,这种时候pages的定义方式就捉襟见肘了,此时就须要利用gatsby-node.js来进行配置了。先来简单写一个后端建立页面的示例:

// gatsby-node.js

const path = require('path');

exports.createPages = ({ actions }) => {
  const { createPage } = actions;
  const staticTemplate = path.resolve(`src/templates/static.js`)
  // Query for markdown nodes to use in creating pages.
  // You can query for whatever data you want to create pages for e.g.
  // products, portfolio items, landing pages, etc.
  // Variables can be added as the second function parameter
  createPage({
    // Path for this page — required
    path: `node-static`,
    component: staticTemplate,
    context: {
      title: '我是静态页面',
      content: '静态页内容'
    },
  });
};
复制代码

上面代码在 gatsby-node.js 的 createPages API 建立一个路由,模板是/src/templates/static.js,对应路径是/node-static,而建立页面以及传递属性使用的是actions.createPage,它的context属性能够配置一些属性做为 props 传递给组件,而在组件内部咱们能够经过几种方式来获取:

// 第一种 - 经过 pageContext 获取 context
import React from 'react';

export default (props) => {
  const { pageContext: { title, content } } = props;
  return (
    <>
      <h1>{title}</h1>
      <p>{content}</p>
    </>
  )
};

// 第二种 - 经过 GraphQL 获取
export const data = graphql`
  query {
    sitePage(path: {eq: "/node-static"}) {
      id
      context {
        title
        content
      }
    }
  }
`;

const { sitePage: { context: { title, content } } } = data;
复制代码

上面只是一个简单的演示 node 层如何建立页面,不过呢,若是是这种页面,确定是放在src/pages目录下更合理,经过 node 建立的页面必定是更复杂的页面。我说过了想使用 Gatsby 搭建一个我的博客,所以就使用 gatsby-node.js 来动态建立博客文章页吧。

上图,我新建了一个 posts 文件夹,里面存放博客文章(.md 文件)。在 gatsby-node.js 编写代码动态生成每一个文章的页面。

// gatsby-node.js
exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions;  
  ...
  /* 建立一个复杂的动态页面 */
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)
  return graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            id,
            html
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      throw result.errors
    }

    // Create blog post pages.
    result.data.allMarkdownRemark.edges.forEach(edge => {
      createPage({
        // Path for this page — required
        path: `posts/${edge.node.id}`,
        component: blogPostTemplate,
        context: {
          html: edge.node.html
        },
      })
    })
  });
  ...
}
复制代码

这里是用了 graphql 查询,注意这个graphql来自 createPages 的 API,咱们查询到全部的 markdown 文章内容,而后逐个遍历生成路由页面,定义是 posts/${articleId},重启服务访问一下:

能够看到,两篇文章在 graphql 是能够查询到的,而且咱们前端组件也正常渲染了对应文章页面。这只是牛刀小试,还有不少更方便的功能,具体更多的详见browser-api

gatsby-ssr.js

这个文件,看名字意思是服务端渲染相关处理,给的示例是这样的,你能够将服务端渲染的 HTML 代码在此文件里进行二次加工处理。

// gatsby-ssr.js 

const React = require("react")
// 给 body 标签添加一个类名字为 my-body-class
exports.onRenderBody = ({ setBodyAttributes }, pluginOptions) => {
  setBodyAttributes({
    className: "my-body-class",
  })
};
复制代码

可是这里须要注意一点,wrapPageElementwrapRootElement这两个 API 是 gatsby-browser.js 和 gatsby-ssr.js 共享的。最好保证只在其中一个文件使用它们,否则可能会出现渲染不一致的场景。

其他还有不少 API,不过 gatsby-ssr.js 更多的是与/src/html.js文件一块儿讨论,它修改的内容会覆盖html.js的内容。

具体更多的详见browser-api

部署

关于部署,由于我是 Next.js 爱好者,所以这里选择使用 now 来进行部署,固然也有其余的方式,好比 surge。

now
复制代码

嗯,完事了,固然,前提是你安装了now-cli,具体的能够去 now 官网去安装,反正安装完你直接运行命令 now 就完事了~

咱们来看看部署后的网站:

总结

一篇文章想把 Gatsby 全部内容尽量的讲到确实太难了,文章架构组织了很久,最后决定是上面那样,可能不能算完美,可是我以为已是新手可以接受的按部就班了。由于 Gatsby 技术耦合很严重,你若是想使用它,就必须前置掌握太多的东西了(node/react/graphql...)。

上面基本把我用到的学到的经过本身的理解都解释给你们了,Gatsby 使用下来发现本身真的挺无力,哈哈,为啥呢?由于你能作的只是写页面代码,其余的就是按照 Gatsby 的约束安装插件直接使用就行,怎么说呢?写下来毫无成就感~固然了也侧面印证了 Gatsby 确实适合快速建站,啥都不须要你管你就能够有一个各方面都比较完美的静态站,由于他将不少性能优化点都集成在了项目以及插件系统,咱们拿来主义直接使用就 OK 了。

学习项目地址

开源博客地址

相关文章
相关标签/搜索