最近咱们组在作项目的重构工做,重构的时候采用了全新的技术方案, 最大的变化就是技术选型的时候server端使用的是 GraphQL + apollo,用GraphQL代替了传统的restful风格的先后端数据处理前端
GATSBY是一款友好支持gql 的前端页面生成器node
看一下对于Gatsby的基本解释:mysql
Gatsby is a free and open source framework based on React that helps developers build blazing fast websites and apps
能够理解Gatsby 是一个静态页面生成工具,它容许使用React做为渲染引擎来搭建一个静态站点react
目前比较知名的使用GatsbyJS 的站点就是 react官网ios
经过Gatsby-cli 脚手架能够直接生产一个静态站点,git
测试的时候发现,必需要求本地node版本号 12+github
一个基本的框架生成以后是这个样子web
GATSBY 拥有不少的插件 sql
能够帮助咱们实现很是丰富的功能,好比以后的demo,编译markdown文件,还有在别人的文章中看到能够在页面中添加离线地图应用等等axios
这里讲一个op中有使用的插件
gatsby-plugin-page-creator
gatsby中默认将 pages 做为路由映射文件,只要在pages中的文件均可以被映射为一个路由页面
那若是想要变动这个规则,就能够借助这个插件来处理
后面这个参数能够用来规避这种映射规则,若是你的组件不想做为路由展现,那么就能够在这里配置一下
Gatsby 天然是支持咱们经常使用的 RESTful API 风格
经过例子能够看到,也可使用咱们经常使用的这种数据请求,拿到数据作后续处理
const axios = require("axios") const get = endpoint => axios.get(`https://pokeapi.co/api/v2${endpoint}`) const getPokemonData = names => Promise.all(names.map(async name => { const {data: pokemon} = await get(`/pokemon/${name}`) return { ...pokemon } }))
可是Gatsby 更推荐咱们使用 gql 去处理数据,甚至是静态资源的读取,好比咱们看一下关于站点内静态图片的展现 【 gatsby-blog 】
去展现一个图片都是经过gql访问的方式
const Image = () => { const data = useStaticQuery(graphql` query { placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) { childImageSharp { fluid(maxWidth: 300) { ...GatsbyImageSharpFluid } } } } `) return <Img fluid={data.placeholderImage.childImageSharp.fluid} /> }
这种图片的处理咱们也能够按照以往的require方式去实现
src={fixUrl(item.avatar)}
可是gatsby是建议咱们去遵循同一套开发风格
这种理念能够说是一种开发规范或者说约定吧,但愿能够统一开发者的风格
那这种方案对于团队开发来讲比较好,统一的风格有利于以后项目的管理与开发,若是是我的站定的搭建就怎么简单怎么实现了
Gatsby支持2种页面生成的方式
经过这里例子能够看到咱们能够拿到数据后动态生成页面
createPage({ path: `/pokemon`, component: require.resolve("./src/templates/pokemon.js"), context: { allPokemon } })
而后咱们来写一个demo来感觉一下 gatsby 的实际开发
demo的目标能够看作是博客内容展现
Demo :文章列表页面 + 详情页面
基本逻辑:读取markdown 数据,展现页面
过程很是简单:
1 首先咱们中配置两个插件
gatsby-source-filesystem gatsby-transformer-remark
Filesystem 是读取文件资源
remark帮助解析markdown数据
2 template中建立模块文件
3 而后咱们在gatsby-node.js 中配置动态页面的渲染
// 生成一个markdown 目录文件 const markdownData = result.data.allMarkdownRemark.edges const articles = markdownData.map(({ node }) => node.frontmatter) // 首页列表渲染 - 备注因为 GATSBY 首先读取配置 在走默认设置 因此page文件夹须要调整 否则就会读取pages下的文件做为首页了 createPage({ path: '/', component: path.resolve(`src/templates/index.js`), context: { articles } }) // markdown 遍历生成单独的文章页面 result .data .allMarkdownRemark .edges .forEach(({node}) => { createPage({ path: node.frontmatter.path, component: path.resolve(`src/templates/post.js`) }) })
createPage 函数 中path 是指定到页面展现的路由,component 是你使用的模板引擎,context 是须要传递给模板须要渲染的数据
列表页面所需的,头像、时间等参数都是在markdown文件中写入的
--- title: 画个龙 date: 2019-08-10 path: /rainbow author: mk cover: https://www.lxybaike.com/uploads/201907/1562575542zU2C2i60.jpg --- 我是mk文件 我是mk文件 我是mk文件
以上就完成了一个简单的列表展现功能
按照以前的restful风格。接口分为get与post类型,对应gql中可理解为
get -> Query
post -》 Mutation
const { loading, error, data } = useQuery(GET_TODOS) const [updateTodo] = useMutation(UPDATE_TODO)
1 接口中返回变动的结果,根据id会查询到缓存,会自动更识符,用来做为从新获取对象或者缓存的key —- 因此返回的数据列表中不能够有重复id出现
说到这个想起以前,因为mysql表中使用id + order 做为了联合主键,请求返回的数据有相同的id,致使写入缓存数据出错
2 在 update 中 主动重写 cache ( 这个是目前比较经常使用的一个, readquery && writequery ) 【 mutation 】
3 使用 refetch 直接从新发起一次请求 【 query 】
4 文档中还有一种, fetchmore 在举例分页操做的时候可使用,不过尝试了下这种方法,这个要配合 updatequery 函数操做
,不如使用 setxxx 去变动 variables 【 query 】