如果你熟悉Gatsby,你可能知道它有多快,以及它是如何改善整个开发过程和性能的。根据其官方文档,Gatsby是 "一个基于React的开源框架,用于创建网站和应用程序。无论你是建立一个投资组合网站或博客,还是建立一个高流量的电子商务商店或公司主页,它都很好"。
Gatsby的确很适合建造很多东西。它可以帮助我们快速创建网站和应用程序,没有任何延迟。此外,它还提供各种工具,帮助你尽快开始,无论你想建立什么。你也可以从头开始构建,正如我们将在本教程中演示的那样。
对于风格设计,我们将使用Tailwind CSS。对于那些喜欢写CSS但又不想为自己的样式创建单独文件的人来说,Tailwind是完美的。此外,有了Tailwind CSS,就可以为你创建实用类。你所要做的就是在你的项目中使用它们。
为了展示Gatsby和Tailwind CSS如何一起工作,我们将创建一个简单的健康和健身博客。完成后的产品应该是这样的。
本演示中使用的图片都来自Unsplash;你可以在我的Github资源库中访问它们。在本教程结束时,你应该能够使用Tailwind CSS来设计你的Gatsby项目。
设置一个Gatsby项目
在你的终端,运行npm init gatsby 。这将产生一个提示,其中包含帮助你设置Gatsby项目的说明。
按照指示,为你的项目选择一个名称和文件夹。当它询问你是否将使用一个CMS时,选择 "不,或者我以后再添加它"。当被问及造型系统时,也要这样做。当它问及安装额外功能时,选择 "在Gatsby Cloud上免费建立和托管"。然后选择 "完成"。如果一切顺利,将为你生成一个Gatsby模板。
正如介绍中所指出的,我们将使用Tailwind CSS进行样式设计,所以让我们把它设置好。
(注意:使用Tailwind CSS需要你安装Node.js 12.113.0或更高版本。)
输入以下内容。
npm install -D gatsby-plugin-postcss tailwindcss@latest postcss@latest autoprefixer@latest.
你会注意到,我们还安装了gatsby-plugin-postcss 。这是因为Tailwind CSS是一个PostCSS插件,该插件可以帮助我们完成一些繁重的工作。
当它完成安装后,通过输入npx tailwindcss init -p ,创建一个Tailwind配置文件。这将在你的项目文件夹中创建tailwind.config 和postcss.config 文件。配置文件允许你为你的风格设计创建配置。
让我们来配置一下Tailwind的CSS,以删除所有我们最终在生产中不使用的样式。这将在tailwind.config 文件中完成。在清除阵列中,键入'./src/**/*.{js,jsx,ts,tsx}'. 你的Tailwind CSS配置文件现在应该是这样的。
在gatsby-.config.js ,通过在插件阵列中添加gatsby-plugin-postcss ,启用PostCSS。Gatsby的配置文件现在应该是这样的。
在你的src文件夹中创建一个style文件夹,并在其中创建一个.css文件。你可以随心所欲地命名它;我把我的命名为global.css ,因为我的全局样式将被写入其中。
在CSS文件中,我们将通过使用@tailwind 指令来添加Tailwind的基础、实用工具和组件样式。
将以下内容添加到你的CSS文件中。
现在,对于我们的Tailwind CSS设置的最后一部分,在你的项目文件夹的根部创建一个gatsby-browser.js 文件,并通过以下方式导入你的CSS文件import "./src/styles/global.css".
现在,我们可以开始在我们的项目中使用Tailwind CSS了!
用插件使用Gatsby
Gatsby提供了各种插件,使开发过程更加容易。我们将在我们的项目中使用以下插件。
Gatsby-source-filesystem帮助我们从不同的来源读取文件。这些来源可以包括我们项目文件夹中的各种目录、WordPress、contentful,以及更多。gatsby-transformer-remark帮助我们处理Markdown文件gatsby-plugin-image和gatsby-plugin-sharp使我们能够在Gatsby中处理图片。gatsby-transformer-sharp让我们能够处理动态图像
要安装它们,请输入以下内容。
npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp gatsby-transformer-remark
你的gatsby-config.js 应该看起来像这样。
现在,让我们开始构建。
开始使用Tailwind CSS
在我们的src 文件夹中,创建一个名为blog-posts 的新文件夹。在src 文件夹的索引文件中,删除所有现有内容,并创建一个新的React组件。
在你的终端中运行gatsby develop ,以便在我们工作时看到实时变化。现在你应该能够看到你的变化在 [http://localhost:8000/](http://localhost:8000/).
我将使用谷歌字体中的Montserrat和Rammetto字体。有不同的使用方法,但我将在我的global.css 文件的顶部导入它。
在你的tailwind.config 文件中,在主题对象中添加fontFamily 。这让你可以命名和使用多种字体。
下面是我的Tailwind CSS配置文件的样子。
如果你给一个字体家族命名为Cabin,当你想在你的样式中应用它时,你可以简单地写上font-cabin ,Cabin字体就会被应用到你的文本中。
创建博客内容
我们将使用Markdown来创建我们的页面内容。在我的Github资源库中,src/blog-posts 包含了一些我们可以用于这个演示的内容。
blog-post Markdown文件看起来像这样。
顶端的键/值对是页面的前言,包含有关该页面的额外信息。
当我们完成了Markdown文件的创建,是时候创建一些组件了。
创建布局组件
我们将从布局组件开始,我们将用它来创建将在各页中重复出现的部分。像导航条和页脚这样的部分都包含在布局中。我们可以用创建React组件的同样方式来创建布局,并将其导入我们希望它出现的所有页面中。
让我们来创建一个布局文件。
Gatsby生成的模板为我们创建了一个起始文件夹结构。我们可以根据自己的喜好来修改它。
在src 文件夹中,创建一个组件文件夹。在components 文件夹中,创建一个Layout.js 文件。
在该文件中,创建一个名为Layout 的React组件。我们将在这个组件中创建我们的导航和页脚。
该布局接受一个children 的道具。如果没有这个道具,使用该布局组件的页面将无法正常运行。子项道具作为任何将被包含在页面的布局中的东西。
这就是我的Layout.js 的样子。
import React from 'react'
import {Link} from 'gatsby'
const Layout = ({children}) => {
const linkStyle = `
Hover:opacity-70
text-sm
sm:text-lg
`
const logoStyle=`
text-white
font-rammetto
sm:text-base
text-sm
`
return (
<div>
<nav className="flex sm:justify-between justify-around items-center bg-green-900 lg:px-20 sm:px-6 py-8 text-gray-100">
<h3 className={logoStyle}>HealthRoom</h3>
<ul className="flex">
<li className={linkStyle}><Link to="/">Home</Link></li>
<li className={linkStyle}><Link to="/contact">Contact</Link></li>
<li className={linkStyle}><Link to="/about">About</Link></li>
</ul>
</nav>
<main>{children}</main>
<footer className="text-center py-8 bg-green-900 text-gray-100">
<p>Copyright 2030 <span className={logoStyle}>HealthRoom</span></p>
</footer>
</div>
)
}
export default Layout
设置导航条和页脚
你会注意到,我们在页面的顶部导入了一个Link 组件。我们使用Link 组件从一个Gatsby页面到另一个。这个链接不用于外部页面;为此,我们可以简单地使用锚标签。
我们还使用Tailwind的CSS实用类为页面添加了一些样式。这些实用类可以作为内联样式应用,也可以以变量形式应用。当一个或多个特定的样式将在多个地方使用时,我更喜欢创建变量。
在导航样式中,我们添加了背景和文本颜色。Tailwind CSS提供了一些开箱即用的颜色。你也可以通过将它们添加到Tailwind配置文件中来定制颜色。我们可以用添加字体系列的同样方法来添加它们。
现在,我们的导航条和页脚已经创建,让我们继续讨论我们博客的其他部分。
建立一个标题部分
接下来,我们将创建页眉部分。在组件文件夹中,创建一个Header.js 文件。创建一个React组件,并向其添加以下内容。
import React from 'react'
const Header = () => {
return (
<header className="bg-green-900 text-gray-100 pt-16 pb-10 text-center">
<h1 className="font-semibold font-rammetto lg:text-5xl sm:text-4xl text-2xl pb-4">
Welcome to the Health Room
</h1>
<p className=" lg:text-2xl sm:text-lg text-sm font-light">Your one stop blog for health and fitness information</p>
</header>
)
}
export default Header
在这个组件中,我们有一个包含H1标签和P标签的标题部分。我们还向它添加了一些Tailwind类。你会注意到,我们在H1的造型中使用了font-rammetto 。我们之前在向我们的tailwind.config.js 添加字体家族时提到了这一点。font-semibold 将font-weight 设置为600,text-5xl 使字体大小为3rem 。我们还给它一个1rem 的padding-bottom 。
这就是页眉组件的全部内容。让我们来处理页面的博客部分。
创建博客内容
在组件文件夹中,创建一个子文件夹,并将其命名为blog 。在blog 文件夹中,创建一个index.js 文件和一个BlogItem.js 文件。BlogItem 组件将是每个博客文章的图片和标题的容器。让我们来创建它。
import React from 'react'
import {Link} from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image";
const BlogItem = ({alt, image, slug, title}) => {
return (
<div className="hover:opacity-50">
<Link to={`/${slug}`}>
<GatsbyImage image={image}
alt={alt} className="max-h-[200px]"
/>
<h3 className="font-semibold text-black max-w-4/5 text-center mt-2 capitalize sm:text-base text-sm">{title}</h3>
</Link>
</div>
)
}
export default BlogItem
在我们文件的顶部,我们从gatsby-plugin-image ,导入了GatsbyImage 组件。我们不使用img 标签,而是使用这个组件作为我们的图像包装器。
GatbsyImage 组件是在我们想使用动态图像时使用的。如果我们想使用静态图像,StaticImage 组件就会派上用场。BlogItem 组件接受一些道具;我们很快就会看到原因。
在我们的博客文件夹中创建的index.js 文件中,让我们添加以下几行代码。
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import BlogItem from "./BlogItem"
const Blog = () => {
const articles = useStaticQuery(graphql`
{
allMarkdownRemark {
nodes {
frontmatter {
title
tag
slug
image {
childImageSharp {
gatsbyImageData(layout: FULL_WIDTH, placeholder: BLURRED)
}
}
}
html
}
}
}
`)
const allArticles = articles.allMarkdownRemark.nodes.map((item, index) => (
<BlogItem
key={index}
image={item.frontmatter.image.childImageSharp.gatsbyImageData}
slug={item.frontmatter.slug}
alt={item.frontmatter.title}
title={item.frontmatter.title}
/>
))
return (
<div className="px-10 py-12">
<h3 className="text-2xl font-rammetto">Health Tips For You</h3>
<div className="grid md:grid-cols-3 grid-cols-2 gap-x-4 gap-y-10 mt-8">
{allArticles}
</div>
</div>
)
}
export default Blog
在页面的顶部,我们从Gatsby导入了GraphQL和useStaticQuery 。通过Gatsby,我们用GraphQL访问我们的数据。useStaticQuery ,当我们在一个不是Gatsby页面的文件中进行查询时,就会用到它。
现在,我们正在查询我们组件文件夹中的数据,所以我们需要使用useStaticQuery 。如果我们是在pages文件夹中进行查询,就不需要使用useStaticQuery 。
在本教程的早些时候,我们添加了gatsby-source-filesystem 插件,它帮助我们从本地文件中获取数据。transformer-remark 插件将我们的Markdown文件转换为我们可以查询的MarkdownRemark 节点。
在我们的文件中,我们正在对我们创建的所有Markdown文件进行GraphQL查询,并从中获取一些信息。我们也在对所有的Markdown节点进行映射,并为每个节点渲染一个BlogItem 。要探索你的项目的GraphQL,请查看 [http://localhost:8000/___graphql](http://localhost:8000/___graphql).
我们还为博客项目部分添加了一些样式。我们做了显示网格,并将列设置为:大屏幕上有三个,小屏幕上有两个。
我们的导航菜单中的链接都链接到不存在的页面,所以现在让我们为它们创建组件。
在组件文件夹中,创建一个AboutPage.js 文件并添加以下内容
import React from 'react'
const AboutPage = () => {
return (
<div className="text-center py-24 w-4/5 mx-auto">
<h3 className="font-rammetto text-2xl pb-4">HealthRoom has always been about the readers</h3>
<p>We created HealthRoom to ensure that every person has an opportunity to keep up with health and fitness tips.
We hope to stay around for many years and continue offering our service to readers worldwide.
</p>
</div>
)
}
export default AboutPage
在div的样式中,你会看到使用了w-4/5 类。这意味着该div的内容应该只占页面的80%。
让我们创建一个联系人组件。在组件文件夹中,创建一个ContactPage.js文件和以下所有内容
import React from 'react'
const ContactPage = () => {
return (
<div className="text-center py-48">
<h2 className="font-rammetto text-3xl pb-4">Thanks for checking out HealthRoom.</h2>
<p className="font-semibold w-3/6 mx-auto">To contact us, send an email to healthroom@hmail.org or call us on +724 9097245718 </p>
</div>
)
}
export default ContactPage
我们创建了一个简单的带有网站联系信息的组件。你可以通过添加一个表单或按你认为合适的方式定制,使你的组件变得花哨。
这将是我们需要的所有组件。让我们在我们的页面中使用这些组件。
创建页面
起步模板在页面文件夹中为我们生成了一些文件。我们有404.js和index.js文件。我们可以随心所欲地添加和修改这些页面。
在我们的index.js 文件中,添加以下内容。
import React from "react"
import Layout from "../components/Layout"
import Header from "../components/Header"
import Blog from "../components/blog"
const Home = () => {
return(
<Layout>
<Header/>
<Blog/>
</Layout>
)
}
export default Home
我们从组件文件夹中导入了Layout,Header 和Blog 组件,并在我们的主页中渲染了它们。
现在当我们检查localhost:8000 ,我们应该看到像这样的东西。
让我们来创建我们的其他页面。在pages 文件夹中,创建一个名为about.js 的新文件并添加以下内容。
import React from 'react'
import Layout from "../components/Layout"
import AboutPage from "../components/AboutPage"
const About = () => {
return (
<Layout>
<AboutPage/>
</Layout>
)
}
export default About
在这里,我们从组件文件夹中导入我们的Layout.js 和AboutPage.js 文件。如果你点击导航中的 "**关于 "**链接,你应该看到像这样的东西。
为了创建我们的联系页面,让我们在pages文件夹中创建一个contact.js 文件,并添加以下内容。
import React from 'react'
import Layout from "../components/Layout"
import ContactPage from "../components/ContactPage"
const Contact = () => {
return (
<Layout>
<ContactPage/>
</Layout>
)
}
export default Contact
就像我们在 "关于 "页面上所做的那样,我们从组件文件夹中导入了布局和contactPage 组件,并在页面上渲染了它们。现在的联系页面应该是这样的。
这就是页面文件夹的全部内容。在我们的主页上,如果你点击任何其他的博客项目,我们的屏幕上就会显示一个404页面。这是因为我们还没有为它们创建页面。我们将需要创建动态页面,当任何一个博客项目被点击时,这些页面将被生成。
创建动态页面
要在Gatsby中创建动态页面,我们需要为页面创建一个模板。模板是我们希望生成的任何页面看起来像什么。我们可以创建任意多的模板。
在src 文件夹中,创建一个子文件夹,并将其命名为templates 。在templates 文件夹中,创建一个名为article.js 的文件。在article.js ,添加以下内容。
import React from "react"
import {graphql} from "gatsby"
import Layout from "../components/Layout"
import { GatsbyImage } from "gatsby-plugin-image"
const Article = ({data}) => {
const { html } = data.markdownRemark
const { title, tag, image } = data.markdownRemark.frontmatter
return(
<Layout>
<div className="w-4/5 mx-auto mt-9 article">
<GatsbyImage image={image.childImageSharp.gatsbyImageData} className=" md:h-96 h-60"/>
<section className="py-10">
<span className="bg-gray-200 py-1 px-2 font-semibold">{tag}</span>
<h2 className="font-semibold md:text-3xl text-xl
py-4 capitalize">{title}</h2>
<div dangerouslySetInnerHTML={{ __html: html }}></div>
<p className="pt-8">Published in the {tag} category</p>
</section>
</div>
</Layout>
)
}
export default Article
export const query = graphql`
query ArticleQuery($slug: String) {
markdownRemark(frontmatter: {slug: {eq: $slug}}) {
html
frontmatter {
title
tag
image {
childImageSharp {
gatsbyImageData(layout: FULL_WIDTH, placeholder: BLURRED)
}
}
}
}
}
`
在这里,我们为页面上的文章创建了一个模板页面,我们做了一个查询来获得将在页面上显示的数据。请注意,我们在这里没有使用useStaticQuery 。这是因为这是一个由Gatsby生成的页面,所以我们可以在没有useStaticQuery 的情况下进行GraphQL查询。
除了模板之外,我们还需要在我们的项目文件夹的根部有一个名为gatsby-node.js 的文件。让我们来创建它,并在其中添加以下内容。
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const {data} = await graphql(`
query AllArticles {
allMarkdownRemark {
nodes{
frontmatter {
slug
}
}
}
}
`)
data.allMarkdownRemark.nodes.forEach(item => {
actions.createPage({
path: item.frontmatter.slug,
component: path.resolve(`src/templates/article.js`),
context: {slug: item.frontmatter.slug}
})
})
}
这个文件在节点环境下的构建时间运行。我们可以在构建时使用创建的模板文件进行查询以获得数据,并使用这些数据来生成页面。
我们创建了一个异步函数,因为我们将进行查询来获取所需的数据,以便向模板添加有意义的内容。
我们向我们的函数传递两个参数,GraphQL和行动。GraphQL让我们获取我们所需的数据,而行动包含一些方法,包括一个用于生成页面的方法。
然后,我们做一个查询,以获得所有Markdown文件的slug。在我们的例子中,lug是包含在我们的Markdown文件的前言中的。值得注意的是,在这里,GraphQL是一个函数,所以我们不只是在它后面添加反斜线。相反,我们以通常的方式使用括号,这是为函数所做的。
我们遍历所有的Markdown文件,并为每一个文件使用行动中的createPage 方法动态地创建一个页面。在这个方法中,我们传递一个对象,告诉Gatsby如何创建页面。对于每个Markdown文件,它告诉Gatsby在创建页面时要使用的路径,页面的模板,以及将在创建页面时使用的数据。
请注意,路径的值是我们的Markdown文件中来自frontmatter的lug,这就是将显示在地址栏上的东西。slug将是生成页面的路径。我们还设置了组件的路径,该组件将被用作博客项目的模板。
在上下文部分,我们传入lug作为我们在创建页面时需要的变量。你可以在那里添加多个项目。slug变量在我们的模板页面中进行查询时使用。
如果一切如常,当你运行gatsby develop ,当你点击主页上的博客项目时,你将能够查看每篇博客文章。
现在我们应该看到像这样的东西。
结论
我们已经走到了这个Gatsby和Tailwind CSS教程的尽头。在这一点上,你应该能够设置和使用Gatsby与Tailwind CSS来创建你自己的项目。
你可以在这里看到一个完成的博客演示。