让我们用外部内容构建一个静态网站。
在这篇文章中,我将向您展示如何使用 GatsbyJS 静态渲染来自任何数据源的数据。
如果您喜欢 React 并且想要一个符合标准的高性能 Web,您应该看看 GatsbyJS。
它有什么作用?
它将把你的 React 代码编译成静态 HTML 文件的集合。
你为什么要关心?
GatsbyJS 将内容表示为节点树。节点可以是图像或文本块。
例如,博客文章是文本和图像节点的集合。
您可以在 gatsby-node.js 文件中手动创建节点。但还有更简单的方法。
节点是由插件创建的。您需要哪个插件,取决于您选择的 CMS。
最直接的选项是文件系统插件,它将文件变成节点。
要找到适合您的插件,请查看此处
如果您有现有插件未涵盖的数据源,让我们构建自己的数据源。
这个过程相当简单,唯一复杂的部分是图像。
在 gatsby 项目根文件夹中创建 gatsby-node.ts(或 js)文件。
添加此代码即可开始。 gatsby 项目构建时会自动调用 sourceNodes 方法。
import { GatsbyNode } from "gatsby" import { createRemoteFileNode } from "gatsby-source-filesystem" export const sourceNodes: GatsbyNode["sourceNodes"] = async ({ actions: { createNode }, createNodeId, createContentDigest, store, cache, }) => { }
现在让我们获取数据。这里我使用 https://inuko.net 应用程序平台,但任何来源的过程都是类似的。
interface IPost { id: string; title: string; content: string; image_id: string; } const fetchPosts = async () => { const postQuery = { entity: { name: "cms_content", allattrs: true, links: [{ name: "cms_site", from: "siteid", to: "id", alias: "cs", filter: { conditions: [{ attribute: "name", operator: "eq", value: "NAME_OF_MY_WEB" }] } }] } }; const posts = await fetchJson("/api/fetch", postQuery) as IPost[]; return posts; }
我们还可以获取我们需要的图像。
interface IImage { id: string; name: string; // sunset.jpg image_url: string; // https://sample.com/54565735235464322 } const fetchImages = async () { const imageQuery = { entity: { name: "cms_image", allattrs: true, links: [{ name: "cms_site", from: "siteid", to: "id", alias: "cs", filter: { conditions: [{ attribute: "name", operator: "eq", value: "NAME_OF_MY_WEB" }] } }] } }; const images = await fetchJson("/api/fetch", imageQuery) as IImage[]; return images; }
我们现在有(博客)帖子列表和图像(链接)列表。
在此示例中,我们有一个简单的结构,其中每个帖子都有一些文本内容和单个图像的 id。
下一步是将我们从服务器获取的数据转换为 gatsby 可以使用的数据。
gatsby中的数据是用*node*来表示的,所以让我们看看如何将我们的服务器数据转换为节点。
export const sourceNodes: GatsbyNode["sourceNodes"] = async ({ actions: { createNode }, createNodeId, createContentDigest, store, cache, }) => { const posts = await fetchPosts(); const images = await fetchImages(); // create an object for image by id lookup const imageDict = images.reduce((d, c) => (d[c.id] = c, d), {} as { [name: string]: IImage }); for (const post of posts) { // create a node from post const postNodeId = createNodeId(`XPost-${post.id}`) if (post.image_id && imageDict[post.image_id]) { const image = imageDict[post.image_id]; const name = image.name; const url = image.image_url; const fileNode = await createRemoteFileNode({ url: url, //store, cache, createNode, createNodeId, // !!! important !!! // If your image url does not have a valid image extension, this will tell the system what type of image we are adding ext: name.substring(name.lastIndexOf(".")), }); post.mediaFile___NODE = fileNode.id post.internalId = post.id; // copy our internal post. id is replaced by gatsbyjs const nodeMeta = { id: postNodeId, parent: null, children: [], internal: { type: `XPosts`, mediaType: `text/json`, content: JSON.stringify(post), contentDigest: createContentDigest(post), }, } createNode(Object.assign({}, post, nodeMeta)) } } }
我们迭代所有帖子并为每个帖子创建相应的节点。
如果帖子有图像 post.image_id 我们还会创建一个 RemoteFileNode 节点和
将其附加到后节点
post.mediaFile___NODE = fileNode.id
重要注意:gatsby 会自动从我们的文件节点创建图像节点,但它需要一种方法来检测它是图像。
如果您的网址包含文件扩展名或者您的服务器将回复图像内容类型,那么您就已准备就绪。
如果不是这种情况,您可以在文件节点上设置显式扩展名(png、jpg)来触发图像节点创建。
ext: name.substring(name.lastIndexOf("."))
也许您想知道为什么我们要这么麻烦地将图像加载为节点。我们可以直接使用图像网址。
例如,有时图像可能位于经过身份验证的服务后面。
但真正的原因是我们想使用 gatsby 提供的出色的图像插件。
它会自动将图像转换为适合任何浏览我们网站的设备的最佳格式和尺寸。
这意味着图像将加载得更快并且看起来更好(并且通过谷歌获得更好的分数:)。
我们现在已准备好使用我们创建的节点。
您可以通过多种方式执行此操作,在本示例中,我们将发布一些帖子并将它们呈现在 features 页面上。
首先我们需要加载我们感兴趣的数据节点。我们将使用useStaticQuery。
然后,我们将数据传递到名为“SectionGrid”的可重用组件,该组件将呈现所有加载的帖子。
const FeaturePage = (props:{}) => { const data = useStaticQuery(graphql` query featuresQueryEn { allXPosts( filter: {language: {eq: "en"}, pageid: {label: {eq: "features"}}} sort: {position: ASC} ) { edges { node { id content title mediaFile { childImageSharp { gatsbyImageData } } } } } } `); returnFeatures} /> }
渲染时间!
import { Link } from "gatsby"; import { GatsbyImage } from "gatsby-plugin-image"; import React from "react"; export const SectionGrid = (props: {data: any, title: string}) => { const edges = props.data.allXPosts.edges as any[]; return}{props.title}{edges.map(edge => { const node = edge.node; return})}{node.title}
{node.content}
该组件将迭代我们从查询中获得的所有节点。它将渲染两个 div,一个用于帖子图像,一个用于文本内容。
建立一个美观且高性能的网站从未如此简单。
像 Gatsbyjs (及其插件)这样的工具将为我们完成大部分繁重的工作。
因此我们可以将 100% 的时间投入到内容和设计上。
我希望有了这篇文章,您将能够进一步自动化您的工作流程。
现在您可以将产品目录、知识库或其他有价值的内容带到您的网站。
无需复制面食并具有全自动图像处理。
黑客快乐!
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3