热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Gatsby学习03Gatsby插件

Gatsby插件Gatsby框架内置插件系统,插件是为应用添加功能的最好的方式。在Gatsby中有三种类型的插件:数据源插件(sou
Gatsby 插件

Gatsby 框架内置插件系统,插件是为应用添加功能的最好的方式。

在 Gatsby 中有三种类型的插件:

  • 数据源插件(source):负责从应用外部获取数据,将数据统一放在 Gatsby 的数据层中
  • 数据转换插件(transformer):负责转换特定类型的数据的格式,比如将 Markdown 文件中的内容转化成对象形式
  • 功能插件(plugin):为应用提供功能,比如通过插件让应用支持 Less 或 TypeScript

Gatsby 官方提供了非常多且非常有用的插件,开发者也可以自己编写插件,以及发布供他人使用。

Gatsby 对插件的命名规范有要求:

  • 数据源插件名称中必须包含 source
  • 数据转换插件名称中必须包含 transformer
  • 功能插件名称中必须包含 plugin

将本地 JSON 文件数据添加到数据层

添加示例文件

在根目录下创建 json 文件夹,在里面添加 products.json 文件。

json\products.json:

[{"title": "Vans范斯 男子短袖T恤 Work Weird新款运动休闲TEE迷彩官方正品","price": 208,"url": "/images/product-1.jpg","address": "上海","id": "1"},{"title": "小ck女包包2020新款潮真皮斜挎包女百搭ins2019单肩包时尚手提包","price": 239,"url": "/images/product-2.webp","address": "北京","id": "2"},{"title": "潮牌羊毛开衫男川久爱心毛衣保桃心play外套玲","price": 118,"url": "/images/product-3.webp","address": "深圳","id": "3"},{"title": "太平鸟男装 2020秋季pupu熊联名时尚大图案毛套衫圆领帅气针织衫","price": 379,"url": "/images/product-4.webp","address": "广州","id": "4"}
]

JSON 中使用的图片放置在根目录的 static 文件夹中。

static 文件夹是静态资源文件夹,里面的资源在浏览器中可以直接访问,例如 http://localhost:8000/images/product-1.jpg 可以访问 static/images/product-1.jpg 文件。

安装插件

将本地 JSON 文件中的数据放入数据层需要安装两个插件:

  • gatsby-source-filesystem:用于将本地文件中的数据添加至数据层
  • gatsby-transformer-json:将原始 JSON 字符串转换成 Javascript 对象

安装完成后,需要将插件配置到 gatsby-config.js 中:

// gatsby-config.js
/*** Configure your Gatsby site with this file.** See: https://www.gatsbyjs.com/docs/gatsby-config/*/module.exports &#61; {// siteMetadata 对象用于配置网站元数据siteMetadata: {title: "Hello Gatsby",author: "Jone",},/* Your site config here */plugins: [{resolve: "gatsby-source-filesystem", // 插件名options: {// 分类名称&#xff0c;用于区分不同数据&#xff0c;可以不设置name: "json",// 插件将转化 path 文件夹下的 json 文件// 最终以<文件名Json>为数据名存储到数据层path: &#96;${__dirname}/json/&#96;,},},// 不需要特殊配置的可以直接放到 plugin 数组中"gatsby-transformer-json",],
}

GraphQL 查询

query MyQuery {allFile {nodes { # 转化的文件absolutePath # 文件的绝对路径publicURL # 转化后的文件所在路径ext # 文件的扩展名}}productsJson { # 转化的数据&#xff08;查询单个数据&#xff1a;只查询第一条&#xff09;titleurlpriceaddress}allProductsJson { # 转化的数据&#xff08;查询全部数据&#xff09;nodes {titleurl # 取的 JSON 数据的 url 字段的值priceaddress}}
}

图像优化

存在的问题


  1. 图像文件和数据文件不在源代码中的同一个位置
    • 图像文件存储在 static
    • 数据文件存储在 json
  2. 图像路径基于构建站点的绝对路径&#xff0c;而不是相对于数据(.json 文件)的路径&#xff0c;难以分析出图片的真实存储位置
  3. 图像没有经过任何优化操作
    • 压缩、生成响应式图片等

安装插件


  • gatsby-source-filesystem&#xff1a;用于将本地文件信息添加到数据层
  • gatsby-plugin-sharp&#xff1a;提供本地图像的处理功能&#xff08;调整图像尺寸、压缩体积等&#xff09;
    • 依赖的 sharp 模块可能受国外访问限制&#xff0c;可以配置镜像
    • 依赖的 mozjpeg 模块从 github 下载安装包&#xff0c;如果 github 访问受限&#xff0c;可以配置 hosts
    • PS&#xff1a;配置 VPN 一劳永逸
  • gatsby-transformer-sharp&#xff1a;将 gatsby-plugin-sharp插件处理后的图像信息添加到数据层
    • 该插件会识别数据中的图片地址&#xff0c;如果定位的图片文件被 gatsby-source-filesystem 添加到数据层&#xff0c;则会将 url 的 GraphQL 查询结果替换为图片信息对象
  • gatsby-image&#xff1a;React 组件&#xff0c;优化图像显示&#xff0c;基于gatsby-transformer-sharp插件转化后的数据。

优化内容


  1. 生成多个具有不同宽度的响应式图像版本&#xff0c;为图像设置 srcsetsizes 属性&#xff0c;不同宽度的设备加载合适大小的图片
  2. 使用“模糊处理”技术&#xff0c;加载图片时&#xff0c;使用一个 20px 宽的小图像显示为占位符&#xff0c;直到实际图像下载完成为止

配置插件

// gatsby-config.js
/*** Configure your Gatsby site with this file.** See: https://www.gatsbyjs.com/docs/gatsby-config/*/module.exports &#61; {// siteMetadata 对象用于配置网站元数据siteMetadata: {title: "Hello Gatsby",author: "Jone",},/* Your site config here */plugins: [{resolve: "gatsby-source-filesystem", // 插件名options: {// 分类名称&#xff0c;用于区分不同数据&#xff0c;可以不设置name: "json",// 插件将转化 path 文件夹下的 json 文件// 最终以<文件名Json>为数据名存储到数据层path: &#96;${__dirname}/json/&#96;,},},// 不需要特殊配置的可以直接放到 plugin 数组中"gatsby-transformer-json","gatsby-plugin-sharp","gatsby-transformer-sharp",],
}

改动图像资源

将图像文件夹 imagesstatic 移动到数据文件所在的 json 文件夹下。

修改数据中的图像路径&#xff1a;"/images/xxxx" -> "./images/xxxx"

查看 GraphQL

重启项目 gatsby develop&#xff0c;打开 GraphQL 调试页面。

查询数据多了 allImageSharpimageSharp 节点&#xff0c;而 JSON 数据项的 url 节点也增加了相应节点&#xff1a;

query MyQuery {allImageSharp {nodes {fixed { # 固定大小的图片&#xff08;可以生成指定宽高的图片&#xff09;src}fluid { # 响应大小的图片src}}}allProductsJson {nodes {titlepriceaddressurl {childImageSharp {fluid {# 响应图片相关属性srcsrcSetsizesaspectRatio # 像素比}fixed(width:200,height:200) { # 指定宽高srcsrcSetwidthheight}}}}}
}

显示图片

响应式图片&#xff1a;

// src\pages\product.js
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"export default function Product({ data }) {return (<div>{data.allProductsJson.nodes.map((node, index) &#61;> (<div key&#61;{index}><p>{node.title}</p><p>{node.address}</p><p>{node.price}</p><div style&#61;{{ width: 400 }}>{/* fluid 接收响应式图片 图片的宽以父元素为准 */}<Img fluid&#61;{node.url.childImageSharp.fluid} /></div></div>))}</div>)
}// 响应式图片
export const query &#61; graphql&#96;query {allProductsJson {nodes {titleurl {childImageSharp {fluid {srcsrcSetsizesaspectRatio}}}priceaddress}}}
&#96;

固定大小图片&#xff1a;

// src\pages\product.js
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"export default function Product({ data }) {return (<div>{data.allProductsJson.nodes.map((node, index) &#61;> (<div key&#61;{index}><p>{node.title}</p><p>{node.address}</p><p>{node.price}</p><div style&#61;{{ width: 400 }}>{/* fixed 接收固定大小图片 图片的宽高固定 */}<Img fixed&#61;{node.url.childImageSharp.fixed} /></div></div>))}</div>)
}// 固定大小图片
export const query &#61; graphql&#96;query {allProductsJson {nodes {titleurl {childImageSharp {fixed(width: 200, height: 200) {srcsrcSetheightwidth}}}priceaddress}}}
&#96;

将本地 Markdown 数据添加到数据层

需求描述


  • 在本地有多个 Markdown 文件&#xff0c;一个文件代表一篇文章
  • 将本地 Markdown 文件的数据添加到数据层&#xff0c;构建文章列表页和详情页。

示例文件

添加文件 /posts/gatsby.md&#xff1a;

---
title: "Hello Gatsby"
date: "2048-01-05"
---Hello Gatsby, this is a post.

添加文件 /posts/react.md&#xff1a;

---
title: "Hello React"
date: "9012-12-23"
---This is a test markdown file![](./images/1.jpg)

添加图片 /posts/images/1.jpg

安装插件


  • gatsby-source-filesystem&#xff1a;将 Markdown 文件数据放入数据层
    • 仅使用此插件&#xff0c;放入的只是原始 Markdown 数据&#xff0c;无法使用
  • gatsby-transformer-remark&#xff1a;将数据层中的原始 Markdown 数据转化成可用的对象形式

配置插件

// gatsby-config.js
/*** Configure your Gatsby site with this file.** See: https://www.gatsbyjs.com/docs/gatsby-config/*/module.exports &#61; {// siteMetadata 对象用于配置网站元数据siteMetadata: {title: "Hello Gatsby",author: "Jone",},/* Your site config here */plugins: [{resolve: "gatsby-source-filesystem", // 插件名options: {// 分类名称&#xff0c;用于区分不同数据&#xff0c;可以不设置name: "json",// 插件将转化 path 文件夹下的 json 文件// 最终以<文件名Json>为数据名存储到数据层path: &#96;${__dirname}/json/&#96;,},},{resolve: "gatsby-source-filesystem",options: {name: "markdown",path: &#96;${__dirname}/posts/&#96;,},},// 不需要特殊配置的可以直接放到 plugin 数组中"gatsby-transformer-json","gatsby-plugin-sharp","gatsby-transformer-sharp","gatsby-transformer-remark",],
}

重新启动 gatsby develop

查看 GraphQL

GraphQL 调试页面的查询数据中多了 allMarkdownRemarkmarkDownRemark 节点&#xff1a;

query MyQuery {allMarkdownRemark {nodes {html # 解析的内容部分frontmatter {date # 解析的 date 字段title # 解析的 title 字段}fileAbsolutePath # markdown 文件的绝对路径internal { # 内部属性type # 标识文件内部得一个类型&#xff0c;用于区分文件类型&#xff0c;如 markdown 文件、json 文件、页面文件等}}}
}

构建列表页面

// src\pages\list.js
import React from "react"
import Header from "../components/Header"
import { graphql } from "gatsby"export default function List({ data }) {return (<div>List Page<Header /><hr />{data.allMarkdownRemark.nodes.map(post &#61;> (<div key&#61;{post.id}><p>{post.frontmatter.title}</p><p>{post.frontmatter.date}</p><div dangerouslySetInnerHTML&#61;{{ __html: post.html }}></div></div>))}</div>)
}export const query &#61; graphql&#96;query {allMarkdownRemark {nodes {idhtmlfrontmatter {datetitle}}}}
&#96;

构建文章详情页

重新构建查询数据

为每篇文章的数据添加 slug &#xff08;访问路径&#xff09;作为请求标识&#xff0c;slug 值为文件名称。

  • gatsby.md -> /posts/gatsby
  • react.md -> /posts/react

添加方式有两种&#xff1a;

  1. 手动在每个 Markdown 文件中添加 slug 属性
  2. 【推荐】使用编程方式一次性为数据层中的每篇 Markdown 文章添加 slug 属性

编程方式添加 slugn 属性

gatsby-node.js 文件中导出一个 onCreateNode 方法&#xff0c;该方法在创建每个节点&#xff08;Node&#xff09;后被调用。

Gatsby 应用启动时&#xff0c;会先启动插件&#xff0c;通过插件从外部数据源获取数据&#xff0c;然后将获取到的数据添加到数据层中&#xff0c;向数据层中每添加一条数据实际上就是创建一个数据节点&#xff0c;每创建完一个数据节点&#xff0c;Gatsby 都会调用一次 onCreateNode 方法。

onCreateNode 是框架为开发者提供的用于修改节点信息的方法。

onCreateNode 接收的参数中可以解构出 node 对象&#xff0c;就是 Gatsby 创建的数据节点&#xff1a;

  • 通过数据节点的内部 type 属性&#xff0c;可以获取当前节点的内部类型&#xff0c;区分 Markdown 文件。
  • 通过数据节点的 fileAbsolutePath 文件绝对路径属性&#xff0c;获取文件名作为 slug 的值。

最后使用从 actions 对象中解构的 createNodeField 方法为数据添加属性&#xff0c;方法接受三个参数&#xff1a;

  • node&#xff1a;要添加属性的数据节点对象
  • name&#xff1a;要添加的属性的名字
  • value&#xff1a;要添加的属性的值

// gatsby-node.js
const path &#61; require("path")// 为数据节点添加属性
function onCreateNode({ node, actions }) {const { createNodeField } &#61; actionsif (node.internal.type &#61;&#61;&#61; "MarkdownRemark") {const slug &#61; path.basename(node.fileAbsolutePath, ".md")createNodeField({node,name: "slug",value: slug,})}
}module.exports &#61; { createPages, onCreateNode }

重启 gatsby develop

查看 GraphQL

createNodeField 添加的属性&#xff0c;会添加到 nodes 节点下的 fields 属性下。

query MyQuery {allMarkdownRemark {nodes {htmlfrontmatter {datetitle}fields {slug}}}
}

根据 slug 构建文章详情页


创建页面

使用 createPages 编程式创建页面&#xff1a;

  • 从参数中解构 graphql 方法&#xff0c;用于查询数据
    • gatsby 模块中的 graphql 方法不同
    • 它接收一个查询命令的字符串
    • 返回 Promise&#xff0c;值是查询结果
  • 通过 context 传递给页面的数据&#xff0c;可以在页面中使用的查询命令中作为参数接收 $<参数名>

// gatsby-node.js
const path &#61; require("path")// 创建文章详情页
async function createPages({ graphql, actions }) {// 获取模板绝对路径const template &#61; require.resolve("./src/templates/post.js")// 获取组件所需数据// 注意此处的 graphq 和 组件中使用的 graphql 传参方式不一样const { data } &#61; await graphql(&#96;query {allMarkdownRemark {nodes {fields {slug}}}}&#96;)// 根据模板和数据创建页面const { createPage } &#61; actionsdata.allMarkdownRemark.nodes.forEach(node &#61;> {createPage({path: &#96;/posts/${node.fields.slug}&#96;, // 页面访问地址component: template, // 模板绝对路径// 组件中使用的查询命令可以通过 &#96;$slug&#96; 接收传递给页面的参数context: {slug: node.fields.slug,},})})
}// 为数据节点添加属性
function onCreateNode({ node, actions }) {const { createNodeField } &#61; actionsif (node.internal.type &#61;&#61;&#61; "MarkdownRemark") {const slug &#61; path.basename(node.fileAbsolutePath, ".md")createNodeField({node,name: "slug",value: slug,})}
}module.exports &#61; { createPages, onCreateNode }

查询命令

在这里插入图片描述

文章详情页模板

// src\templates\person.js
import React from "react"
import { graphql } from "gatsby"export default function Post({ data }) {return (<div><p>{data.markdownRemark.frontmatter.title}</p><p>{data.markdownRemark.frontmatter.date}</p><div dangerouslySetInnerHTML&#61;{{ __html: data.markdownRemark.html }}></div></div>)
}export const query &#61; graphql&#96;query ($slug: String) {markdownRemark(fields: { slug: { eq: $slug } }) {htmlfrontmatter {datetitle}id}}
&#96;

处理 Markdown 文件中的图片

react.md 中插入了一个图片 ./images/1.jpg&#xff0c;在转化数据时&#xff0c;并没有将 Markdown 数据中的图片地址替换为这个图片资源文件转化后的路径。

gatsby-remark-images 插件用于处理 Markdown 中的图片&#xff0c;将图片路径替换为转化后的资源路径&#xff0c;以及一些其它优化。

安装 npm i gatsby-remark-images

该插件要作为 gatsby-transformer-remark 的插件去配置&#xff1a;

// gatsby-config.js
/*** Configure your Gatsby site with this file.** See: https://www.gatsbyjs.com/docs/gatsby-config/*/module.exports &#61; {// siteMetadata 对象用于配置网站元数据siteMetadata: {title: "Hello Gatsby",author: "Jone",},/* Your site config here */plugins: [{resolve: "gatsby-source-filesystem", // 插件名options: {// 分类名称&#xff0c;用于区分不同数据&#xff0c;可以不设置name: "json",// 插件将转化 path 文件夹下的 json 文件// 最终以<文件名Json>为数据名存储到数据层path: &#96;${__dirname}/json/&#96;,},},{resolve: "gatsby-source-filesystem",options: {name: "markdown",path: &#96;${__dirname}/posts/&#96;,},},// 不需要特殊配置的可以直接放到 plugin 数组中"gatsby-transformer-json","gatsby-plugin-sharp","gatsby-transformer-sharp",{resolve: "gatsby-transformer-remark",options: {plugins: [{resolve: "gatsby-remark-images",options: {maxWidth: 600, // 生成图片的最大宽度&#xff0c;默认 650linkImagesToOriginal: false, // 是否将图片包裹在 a 标签中},},],},},],
}


推荐阅读
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
  • 负载均衡_Nginx反向代理动静分离负载均衡及rewrite隐藏路径详解(Nginx Apache MySQL Redis)–第二部分
    nginx反向代理、动静分离、负载均衡及rewrite隐藏路径详解 ... [详细]
  • vuepress是Vue驱动的静态站点生成工具本文仅介绍,搭建静态博客的过程,具体教程及文档请点击进入vuepress中文网点击查看项目代码vuepress初始化下面初始化#将github新创建的仓库克隆到本地 ... [详细]
  • ubuntu软件商店加载不出来_这款年度最爱的效率软件,其实我不太舍得分享出来...
    文章来源:工具狂人今天的这篇文章,想给大家介绍一个我近半年来一直在用的软件——滴答清单,相信不少朋友可能也用过或听过这个软件。滴答清单&# ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了一些好用的搜索引擎的替代品,包括网盘搜索工具、百度网盘搜索引擎等。同时还介绍了一些笑话大全、GIF笑话图片、动态图等资源的搜索引擎。此外,还推荐了一些迅雷快传搜索和360云盘资源搜索的网盘搜索引擎。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • HTML学习02 图像标签的使用和属性
    本文介绍了HTML中图像标签的使用和属性,包括定义图像、定义图像地图、使用源属性和替换文本属性。同时提供了相关实例和注意事项,帮助读者更好地理解和应用图像标签。 ... [详细]
  • 《从零构建前后星散的web项目》:前端相识过关了吗?
    #前端基本架构和硬核引见手艺栈的挑选起首我们构建前端架构须要对前端生态圈有统统相识,而且最好带有肯定的手艺前瞻性,好的手艺架构能够日后会轻易的扩大,削减重构的次数,纵然重构也不须要 ... [详细]
  • 业务:Payments&Risk大数据/AI/数据可视化时间要求:至少实习6个月,每周5天,入职时间4-5月 ... [详细]
author-avatar
laomeng爱家人_465
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有