构建一个react项目_如何在大约10分钟内构建一个由React和Gatsby支持的博客

构建一个react项目

by Emmanuel Yusufu

通过伊曼纽尔·尤苏夫

如何在大约10分钟内构建一个由React和Gatsby支持的博客 (How to build a React and Gatsby-powered blog in about 10 minutes)

Disclaimer: This was written for Gatsby Version 1, version 2 was just released and has some changes made. I’ll work on another tutorial for that.
免责声明:这是为Gatsby版本1编写的,版本2刚刚发布,并进行了一些更改。 我将为此编写另一个教程。

Gatsby is a blazing fast static site generator based on ReactJS.

Gatsby是基于ReactJS的出色的快速静态站点生成器。

A static site generator (SSG) is a compromise between a hard-coded HTML static site and a full blown CMS (Content Management System), like Wordpress.

静态网站生成器 (SSG)是硬编码HTML 静态网站与功能强大的CMS(内容管理系统)(如Wordpress)之间的折衷方案。

A SSG can be used to generate HTML pages for content-driven websites (such as blogs). All it requires is data for page content and the template to fill with content.

SSG可用于为内容驱动的网站(例如博客)生成HTML页面。 它仅需要页面内容的数据和填充内容的模板。

This post will be divided into five sections:

这篇文章将分为五个部分:

  1. Getting started.

    入门。

  2. Creating layout components.

    创建布局组件。

  3. Creating blog posts.

    创建博客文章。

  4. Generating new pages from blog post data.

    从博客文章数据生成新页面。

  5. Create a list of our site’s markdown files in landing page.

    在目标网页上创建我们网站的降价文件列表。

We’ll take a deep dive into Gatsby and some of its features by creating an imaginary static blog called CodeStack. Mockup is shown below. Let’s go! ✌️

我们将通过创建一个虚构的静态博客称为CodeStack深入了解Gatsby及其一些功能 样机如下所示。 我们走吧! ✌️

1.入门 (1. Getting started)

先决条件 (Prerequisites)

First, make sure you have Node.js installed on your system. If not, go to nodejs.org and install a recent version for you operating system.

首先,请确保您已在系统上安装了Node.js。 如果不是,请访问nodejs.org并为您的操作系统安装最新版本。

Also, this article assumes you have an understanding of ReactJS.

另外,本文假设您对ReactJS有所了解。

安装CLI (Install the CLI)

Gatsby has a command line tool that provides helpful commands such as:

Gatsby有一个命令行工具,可提供有用的命令,例如:

  • gatsby new: for scaffolding a new Gatsby project.

    gatsby new :用于gatsby new Gatsby项目。

  • gatsby develop: for launching a hot-reload-enabled web development server.

    gatsby develop :用于启动启用了热重加载的Web开发服务器。

  • gatsby build: for building a production-ready version of the project.

    gatsby build :用于构建项目的生产就绪版本。

To install, type the following on your terminal and hit enter:

要安装,请在终端上键入以下内容,然后按Enter键:

npm install --global gatsby-cli

Lets create a project folder codestack-blog and navigate the terminal to it.

让我们创建一个项目文件夹codestack-blog并将其导航到终端。

gatsby new codestack-blog && cd $_

If you execute gatsby develop on the project folder, the scaffolded site should look like this:

如果在项目文件夹上执行gatsby develop ,则脚手架站点应如下所示:

添加插件 (Adding plugins)

Gatsby has a large and growing set of plugins. They are essentially Node.js packages that interface with Gatsby’s APIs.

Gatsby有大量且不断增长的插件。 它们本质上是与Gatsby的API接口的Node.js软件包。

They can be installed via NPM (Node Package Manager) on the terminal, and generally have three categories: functional, source and transformer plugins.

它们可以通过终端上的NPM(节点程序包管理器)安装,通常分为三类: FunctionalSourceTransformer插件。

功能性插件 (Functional plugins)

These plugins provide extra functionality in a Gatsby site or in its development environment. For our app, we will need:

这些插件在Gatsby网站或其开发环境中提供了额外的功能。 对于我们的应用程序,我们需要:

  • gatsby-plugin-react-helmet: allows for modification of the head tags. Notice that its already installed in our scaffolded project.

    gatsby-plugin-react-helmet :允许修改head标签。 请注意,它已经安装在我们的脚手架项目中。

  • gatsby-plugin-catch-links: Intercepts local links from markdown and other non-react pages, and does a client-side pushState to avoid the browser having to refresh the page.

    gatsby-plugin-catch-links 拦截来自markdown和其他非React性页面的本地链接,并执行客户端pushState以避免浏览器必须刷新页面。

Install the plugins, or just the second plugin only.

安装插件,或者仅安装第二个插件。

npm install gatsby-plugin-react-helmet gatsby-plugin-catch-links

Anytime we add a new plugin, we need to update the gatsby-config.js file with the new plugin so Gatsby recognizes and uses it. We use back-ticks.

gatsby-config.js我们添加新插件时,我们都需要使用新插件更新gatsby-config.js文件,以便Gatsby能够识别并使用它。 我们使用反引号

module.exports = {  siteMetadata: {    title: `Gatsby Default Starter`,  },  plugins: [    `gatsby-plugin-react-helmet`,    `gatsby-plugin-catch-links`,  ],}
源插件 (Source plugins)

These plugins “source” data from remote or local locations into what Gatsby calls nodes. To write our posts in Markdown on our local disk, we need:

这些插件将数据从远程或本地“来源”到Gatsby称为node的地方 。 要将我们的帖子写在本地磁盘上的Markdown中,我们需要:

  • gatsby-source-filesystem: sources data about files from your computer’s file system.

    gatsby-source-filesystem :从计算机的文件系统中获取有关文件的数据。

npm install gatsby-source-filesystem

Update the gatsby-config.js file:

更新gatsby-config.js文件:

module.exports = {  siteMetadata: {    title: `Gatsby Default Starter`,  },  plugins: [    `gatsby-plugin-react-helmet`,    `gatsby-plugin-catch-links`,    {      resolve: `gatsby-source-filesystem`,      options: {        path: `${__dirname}/src/pages`,        name: 'pages',      },    }  ],}

What’s going on here? An options object can be passed to a plugin for more configuration. We’re passing the filesystem path (i.e. where our Markdown files will be located), and then a name for the source files, so that Gatsby knows about our source files and where to apply the transformer plugins.

这里发生了什么? 可以将options对象传递给插件以进行更多配置。 我们正在传递文件系统path (即Markdown文件将位于的位置),然后传递源文件的name ,以便Gatsby知道我们的源文件以及在何处应用转换器插件。

变形金刚插件 (Transformer plugins)

These plugins transform raw data from nodes into usable data formats. For example, we will need:

这些插件可转换节点中的原始数据 转换为可用的数据格式。 例如,我们将需要:

  • gatsby-transformer-remark: this transforms blog posts written in markdown .md files on the local disk into HTML for rendering.

    gatsby-transformer-remark :这gatsby-transformer-remark以本地磁盘上的markdown .md文件编写的博客帖子转换为HTML以进行呈现。

npm install gatsby-transformer-remark

Update the gatsby-config.js file again.

再次更新gatsby-config.js文件。

module.exports = {  siteMetadata: {    title: `Gatsby Default Starter`,  },  plugins: [    `gatsby-plugin-react-helmet`,    `gatsby-plugin-catch-links`,    {      resolve: `gatsby-source-filesystem`,      options: {        path: `${__dirname}/src/pages`,        name: 'pages',      },    },    `gatsby-transformer-remark`,  ],}

2.创建布局组件 (2. Creating Layout components)

Gatsby lets you easily create “layout components.” Layout components are sections of your site that you want to share across multiple pages. For the blog we are building, these are the header and the sidebars.

通过Gatsby,您可以轻松创建“布局组件”。 布局组件是您要在多个页面上共享的网站部分。 对于我们正在构建的博客,这些是标题侧边栏

From the root folder, take a look at src/layouts. You’ll discover an index.js file where we define layout components. index.css already came with styles.

在根文件夹中,查看src/layouts 。 您会发现一个index.js文件,其中定义了布局组件。 index.css已经带有样式。

After exploring the index.js file, you’ll see that two components have already been created: Header and TemplateWrapper. In TemplateWrapper, we wrap the contents of our site with layout components that we want to be present across multiple pages.

浏览index.js文件之后,您将看到已经创建了两个组件: HeaderTemplateWrapper 。 在TemplateWrapper ,我们使用要在多个页面中呈现的布局组件包装网站内容。

This is made possible by the children() props. It will render all non-layout components of our site where it is placed. Notice that unlike React children props, the children prop passed to layout components is a function and needs to be executed.

这是通过children()道具实现的。 它将呈现放置它的我们网站的所有非布局组件。 请注意,与React子道具不同,传递给布局组件的子道具是一个函数,需要执行。

First of all, create a new folder and CSS file at src/styles/layout-overide.css. Add to the list of imports in the index.js file. We need to Import it after index.css to override some existing style rules.

首先,在src/styles/layout-overide.css创建一个新的文件夹和CSS文件。 添加到index.js文件中的导入列表。 我们需要index.css之后导入它,以覆盖一些现有的样式规则。

import React from 'react'import PropTypes from 'prop-types'import Link from 'gatsby-link'import Helmet from 'react-helmet'
import './index.css'import "../styles/layout-overide.css";

Open layout-overide.css and paste the following styles rules. No need to figure these out.

打开layout-overide.css并粘贴以下样式规则。 无需弄清楚这些。

* {    background: #f5f5f5;    color: black;}html {    height: 100%;}
body {    height: 100%;    border: 5px solid #ffdb3a;}
h1 {    font-size: 1.5rem;    line-height: 0.5rem;}
p, div {    font-size: 16px;}

Update the header component.

更新标题组件。

const Header = () => (  <div    style={{      background: '#f5f5f5',      marginBottom: '3rem',      borderBottom: '2px solid #e6e6e6',    }}  >    <div      style={{        margin: '0 auto',        maxWidth: 980,        padding: '1.45rem 1.0875rem',      }}   >     <h1 style={{margin: 0, textAlign: 'center',fontSize: '18px'}}>        <Link to="/"          style={{            color: 'black',            textDecoration: 'none',          }}        >          CodeStack        </Link>      </h1>    </div>  </div>);

Also, create a Sidebar component.

另外,创建一个Sidebar组件。

const Sidebar = (props) => (
<div    style={{      border: '2px solid #e6e6e6',      maxWidth: 960,      padding: '0.5rem',      marginBottom: '25px'    }}    >    <strong>{props.title}.</strong> {props.description}</div>
);

We desire the Sidebar and rendered {children()} components to behave in a responsive way like this:

我们希望Sidebar和渲染的{children()}组件以如下响应方式运行:

Since there’s no easy way to define media queries in React, I found a library called react-media, a CSS media query component for React. Install it.

由于在React中没有简单的方法来定义媒体查询,因此我找到了一个名为react-media的库, 这是ReactCSS媒体查询组件。 安装它。

npm install --save react-media

It provides a <Media> component that listens for matches to a CSS media query and renders stuff based on whether the query matches or not.

它提供了一个<Med ia>组件,该组件侦听与CSS媒体查询匹配的内容,并根据查询是否匹配来呈现内容

Add it to the list of imports in our file.

将其添加到文件中的导入列表中。

import Media from 'react-media'

Lets layout everything in ( Header, Sidebar, and children() components) the way we wish in TemplateWrapper. Make the following changes (pardon the shameless plug of my name):

让我们按照我们希望在TemplateWrapper的方式在( HeaderSidebarchildren()组件)中布局所有内容。 进行以下更改(请原谅我的名字):

const TemplateWrapper = ({ children }) => (  <div>    <Helmet      title="Gatsby Default Starter"      meta={[        { name: "description", content: "Sample" },        { name: "keywords", content: "sample, something" }      ]}    />    <Header />    <div      style={{        margin: "0 auto",        maxWidth: 980,        display: "flex",        flexDirection: "row",        justifyContent: "space-between",        height: "100%"      }}    >      <Media query={{ maxWidth: 848 }}>        {matches =>          matches ? (            <div              style={{                margin: "0 auto",                maxWidth: 980,                display: "flex",                flexDirection: "row",                justifyContent: "space-between",                height: "100%",                padding: "25px"              }}            >              <div style={{ flex: 1 }}>{children()}</div>            </div>          ) : (            <div              style={{                margin: "0 auto",                maxWidth: 980,                display: "flex",                flexDirection: "row",                justifyContent: "space-between",                height: "100%",                padding: "25px"              }}            >              <div style={{ flex: 2.5, paddingRight: "30px" }}>                {children()}              </div>
<div style={{ flex: 1 }}>                <Sidebar                  title="Codestack"                  description="Articles on React and Node.js. All articles are written by Me. Fullstack Web Development."                />                <Sidebar                  title="About author"                  description="I am a Full-stack Web Developer specializing in React and Node.js based in Nigeria."                />              </div>            </div>          )        }      </Media>    </div>  </div>);

Whats happening in that monolithic block of code? React media is using a Ternary operation to determine what to render based on a maxWidth of 848px . When the screen matches the width, only Header and children() components are rendered.

那块整体代码中发生了什么? React媒体正在使用三元运算基于848pxmaxWidth确定要呈现的内容 。 当屏幕与宽度匹配时,仅呈现Headerchildren()组件。

<Media query={{ maxWidth: 848 }}>        {matches =>          matches ? (            ...stuff to render...          ) : (            ...stuff to render...          )        }      </Media>

If you noticed, we also used Flexbox to layout the positions of the children() and Sidebar components.

如果您注意到了,我们还使用Flexbox布局children()Sidebar组件的位置。

Run gatsby develop on the terminal and our static blog should look this way now:

在终端上运行gatsby develop ,我们的静态博客现在应该看起来像这样:

3. 创建博客文章 (3. Creating Blog posts)

Now lets get into creating actual blog posts. Gatsby utilizes GraphQL to fetch data from one or many sources such as your local disk, Wordpress API, and so on.

现在开始创建实际的博客文章。 Gatsby利用GraphQL从一个或多个源(例如本地磁盘,Wordpress API等)中获取数据。

Personally, I like the fact that I can create a static blog and fetch content from a WordPress API. My client has access to the Wordpress Editor where he creates posts, and I avoid dealing with all the hassles of developing a Wordpress site.

就个人而言,我喜欢可以创建静态博客并从WordPress API获取内容的事实。 我的客户可以访问他在其中创建帖子的Wordpress编辑器,并且我避免了开发Wordpress网站的所有麻烦。

In this post, we will load the data from Markdown files we will create on our local disk. The gatsby-source-filesystem plugin we configured earlier expects our content to be in src/pages, so that’s exactly where we’ll put it!

在这篇文章中,我们将从本地磁盘上创建的Markdown文件中加载数据。 我们之前配置的gatsby-source-filesystem插件期望我们的内容在src/pages ,所以这正是我们要放的地方!

A typical practice for blog posts is to name the folder something like MM-DD-YYYY-title. You can name it whatever you like or just place a markdown file inside the /pages folder.

博客帖子的典型做法是将文件夹命名为MM-DD-YYYY-title。 您可以随意命名,也可以将markdown文件放在/pages文件夹中。

Let’s create a folder src/pages/12–22–2017-first-post, and place an index.md inside. Write:

让我们创建一个文件夹src/pages/12–22–2017-first-post ,然后在其中放置一个index.md 。 写:

---path: "/hello-world"date: "2017-07-12T17:12:33.962Z"title: "My First Gatsby Post"---
Oooooh-weeee, my first blog post!
First post Ipsum is a major key to success. Congratulations, you played yourself. Surround yourself with angels. Celebrate success right, the only way, apple.  The key is to drink coconut, fresh coconut, trust me. Egg whites, turkey sausage, wheat toast, water. Of course they don’t want us to eat our breakfast, so we are going to enjoy our breakfast.

The block surrounded in dashes is referred to as frontmatter. The data we specify here, as well as other Markdown files, will be recognized by the gatsby-transformer-remark plugin.

短划线包围的块称为前frontmatter 。 我们在此处指定的数据以及其他Markdown文件将被gatsby-transformer-remark插件识别。

The plugin will convert the frontmatter metadata part of your markdown file to frontmatter and the content part (Yippeeee, my first blog post!) to HTML.

该插件会将markdown文件的frontmatter元数据部分转换为frontmatter ,并将内容部分(Yippeeee,我的第一篇博客文章!)转换为HTML。

When we begin generating blog pages directly from markdown files in section 4 (next section), path will be used to specify the URL path to render the file. For instance, the markdown file above will be rendered at localhost:8000/hello-world.

当我们直接从第4节 (下一部分)的markdown文件直接生成博客页面时, path将用于指定呈现文件的URL路径。 例如,上面的markdown文件将在localhost:8000/hello-world呈现。

Before that, lets create a template that will render any markdown file into its own blog page. Create the file src/templates/blog-post.js (please create thesrc/templates folder).

在此之前,让我们创建一个模板,以将任何markdown文件呈现到其自己的博客页面中。 创建文件src/templates/blog-post.js (请创建src/templates文件夹)。

import React from "react";import Helmet from "react-helmet";
export default function Template({  data }) {  const post = data.markdownRemark;   return (    <div className="blog-post-container">     <Helmet title={`CodeStack - ${post.frontmatter.title}`} />      <div className="blog-post">        <h1>{post.frontmatter.title}</h1>        <div          className="blog-post-content"          dangerouslySetInnerHTML={{ __html: post.html }}        />      </div>    </div>  );}

We’ve set up the Template component to receive a data object which will come from the GraphQL query we are about to write.

我们已经设置了Template组件来接收data对象,该data对象将来自我们将要编写的GraphQL查询。

Once again, the GraphQL query is needed to fetch data into the component. The result of the query is injected by Gatsby into the Template component as data and markdownRemark.

再一次,需要GraphQL查询才能将数据提取到组件中。 Gatsby将查询结果作为datamarkdownRemark注入到Template组件中。

We will find that the markdownRemark property contains all the details of the Markdown file.

我们将发现markdownRemark属性包含Markdown文件的所有详细信息。

Lets now actually make the query. It should be placed below the Template component:

现在让我们实际进行查询。 它应该放置在Template组件下面:

export const pageQuery = graphql`  query BlogPostByPath($path: String!) {    markdownRemark(frontmatter: { path: { eq: $path } }) {      html      frontmatter {        date(formatString: "MMMM DD, YYYY")        path        title      }    }  }`;

If you’re not familiar with GraphQL, I’ll try to break down what’s going on here. To learn more about GraphQL, consider this excellent resource.

如果您不熟悉GraphQL,我将尝试分解这里发生的事情。 要了解有关GraphQL的更多信息,请考虑使用此优秀资源

GraphQL is just Facebook’s idea of a certain type of server. They’ve written a specification on the kind of requests that can be sent to that server and how the server should respond. GraphQL’s API is better than REST, because you describe the exact data the client-side needs so there’s no more under-fetching or over-fetching of data.

GraphQL只是Facebook对某种类型服务器的想法。 他们编写了关于可以发送到该服务器的请求的种类以及服务器应如何响应的规范。 GraphQL的API比REST更好,因为您描述了客户端所需的确切数据,因此不会再出现数据提取不足或提取过多的情况。

This means you have to create your own GraphQL server. Fortunately for us, GatsbyJS comes with its own GraphQL server out of the box.

这意味着您必须创建自己的GraphQL服务器。 对我们来说幸运的是,GatsbyJS开箱即用地带有自己的GraphQL服务器。

In the code above, BlogPostByPath is the underlying query which will result in a blog post being returned. It will be returned as data for injection into the Template component.

在上面的代码中, BlogPostByPath是基础查询,它将导致返回博客文章。 它将作为data返回以注入到Template组件中。

We pass BlogPostByPath the $path argument to return a blog post related to the path we are currently viewing.

我们向BlogPostByPath传递$path参数,以返回与当前正在查看的路径相关的博客文章。

Furthermore, recall markdownRemark transformed our markdown files. It will be treated as a property whose contents will be available via data.markdownRemark.

此外,回忆markdownRemark转换了我们的markdown文件。 它将被视为属性,其内容可通过data.markdownRemark

We could access the HTML via data.markdownRemark.html. Also, the frontmatter content we created with a block of dahes can be accessed via data.markdownRemark.title etc.

我们可以通过data.markdownRemark.html访问HTML。 另外,我们可以通过data.markdownRemark.title等访问使用data.markdownRemark.title创建的前frontmatter内容。

The entire blog-template.js should look like this:

整个blog-template.js应该如下所示:

import React from "react";import Helmet from "react-helmet";
export default function Template({  data }) {  const post = data.markdownRemark;   return (    <div className="blog-post-container">     <Helmet title={`CodeStack - ${post.frontmatter.title}`} />      <div className="blog-post">        <h1>{post.frontmatter.title}</h1>        <div          className="blog-post-content"          dangerouslySetInnerHTML={{ __html: post.html }}        />      </div>    </div>  );}
export const pageQuery = graphql`  query BlogPostByPath($path: String!) {    markdownRemark(frontmatter: { path: { eq: $path } }) {      html      frontmatter {        date(formatString: "MMMM DD, YYYY")        path        title      }    }  }`;

At this point:

这一点:

  • We have a bunch of plugins installed to perform some utilities as well as load files off of disk and transform Markdown to HTML.

    我们安装了许多插件来执行一些实用程序,以及从磁盘上加载文件并将Markdown转换为HTML。
  • We have a single, lonely Markdown file that will be rendered as a blog post.

    我们有一个孤独的Markdown文件,它将作为博客文章呈现。
  • We have a React template for rendering blog posts in a layout, as well as a wired up GraphQL to query for blog post data and inject the React template with the queried data.

    我们有一个用于在布局中呈现博客文章的React模板,还有一个连接GraphQL的QueryQL,用于查询博客文章数据并将查询的数据注入React模板。

Sweet!

甜!

4.从博客文章数据生成新页面。 (4. Generating new pages from blog post data.)

Gatsby provides a Node API, which provides functionality for creating dynamic pages from blog posts. This API is exposed in thegatsby-node.js file in the root directory of your project. This file could export several Node APIs but we are interested in the createPages API.

Gatsby提供了Node API,该API提供了从博客文章创建动态页面的功能。 该API在项目根目录下的gatsby-node.js文件中公开。 该文件可以导出多个Node API,但是我们对createPages API感兴趣。

Utilize the following block of code snippet as provided in the official docs (Note that blogPostTemplate path was set to reflect ours):

利用官方文档中提供的以下代码段( 请注意,blogPostTemplate路径已设置为反映我们的 ):

const path = require('path');
exports.createPages = ({ boundActionCreators, graphql }) => {  const { createPage } = boundActionCreators;
const blogPostTemplate = path.resolve(`src/templates/blog-post.js`);
return graphql(`{    allMarkdownRemark(      sort: { order: DESC, fields: [frontmatter___date] }      limit: 1000    ) {      edges {        node {          excerpt(pruneLength: 250)          html          id          frontmatter {            date            path            title          }        }      }    }  }`)    .then(result => {      if (result.errors) {        return Promise.reject(result.errors);      }
result.data.allMarkdownRemark.edges        .forEach(({ node }) => {          createPage({            path: node.frontmatter.path,            component: blogPostTemplate,            context: {} // additional data can be passed via context          });        });    });}

Check if it works. I recommend closing your broswer window, stoppingthe gatsby develop server from the terminal using ctrl c. Now run gatsby develop again and open http://localhost:8000/hello-world.

检查是否有效。 我建议关闭浏览窗口,使用ctrl c从终端停止gatsby develop服务器。 现在gatsby develop again运行gatsby develop again并打开http://localhost:8000/hello-world

Create another file src/pages/24–12–2017-learning-grid/index.md

创建另一个文件src/pages/24–12–2017-learning-grid/index.md

---path: "/another-one"date: "2017-07-12T17:12:33.962Z"title: "My Second Gatsby Post"---
In life there will be road blocks but we will over come it. Special cloth alert. Don’t ever play yourself. The key to more success is to get a massage once a week, very important, major key, cloth talk.
<pre><code>// some css grid code </code></pre>

Again, close your broswer window, stop gatsby develop server. Run gatsby develop again and open http://localhost:8000/another-one. This is shown:

再次,关闭浏览窗口,停止gatsby develop服务器。 gatsby develop again运行gatsby develop again并打开http://localhost:8000/another- one 。 显示如下:

Go on if you wish and create your own pages. ✌

如果愿意,请继续并创建自己的页面。 ✌

5.在登录页面中创建我们网站的降价文件列表。 (5. Create a list of our site’s markdown files in the landing page.)

The default landing page that comes with the scaffolded Gatsby site is located at src/pages/index.js. This is where we would define a template, and make a query to inject it with data for the list of .md files. Do this:

脚手架的Gatsby网站随附的默认登录页面位于src/pages/index.js 。 这是我们定义模板的地方,并进行查询以向其中注入.md文件列表的数据。 做这个:

import React from "react";import Link from "gatsby-link";import Helmet from "react-helmet";
import '../styles/blog-listing.css';
export default function Index({ data }) {  const { edges: posts } = data.allMarkdownRemark;  return (    <div className="blog-posts">      {posts        .filter(post => post.node.frontmatter.title.length > 0)        .map(({ node: post }) => {          return (            <div className="blog-post-preview" key={post.id}>              <h1>                <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>              </h1>              <h2>{post.frontmatter.date}</h2>              <p>{post.excerpt}</p>            </div>          );        })}    </div>  );}
export const pageQuery = graphql`  query IndexQuery {    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {      edges {        node {          excerpt(pruneLength: 250)          id          frontmatter {            title            date(formatString: "MMMM DD, YYYY")            path          }        }      }    }  }`;

I trust you are badass at this point and already familiar with whats going on. Note that we wrote an import above that does not exist. Now create the file /styles/blog-listing.css:

我相信您在这一点上很糟糕,并且已经熟悉了发生的事情。 请注意,我们在上面编写了一个不存在的import 。 现在创建文件/styles/blog-listing.css

div.blog-post-preview {    border-bottom: 2px solid #e6e6e6;    padding-top: 1rem;    padding-bottom: 1rem;    margin-bottom: 1rem;}
h1 > * {    font-size: 1.2rem;    text-decoration-line: none;}
h2 {    font-size: 0.8rem !important;    font-weight: 100 !important;}

Restart the server, visit the landing page, and you should see the listing at work:

重新启动服务器,访问登录页面,您将看到正在运行的清单:

结论 (Conclusion)

We have come to the end of this tutorial. Thank you for reading thus far.

我们到了本教程的结尾。 谢谢您到目前为止的阅读。

This post is just the tip of the iceberg considering the amount of things you could do with Gatsby. Feel free to explore how you could implement:

考虑到您可以使用盖茨比做的事,这篇文章只是冰山一角。 随意探索如何实现:

  • Search functionality

    搜索功能
  • The use of tags to categorize blog posts

    使用标签对博客文章进行分类
  • Deploying your Gatsby site

    部署您的Gatsby网站

You can grab the final source code here. Feel free to support me (devapparel.co) and look good while at it. Also, Comment or Share this post. Thanks for reading!

您可以在此处获取最终的源代码。 随时支持我( devapparel.co ),并在此过程中表现出色。 另外,评论或分享此帖子。 谢谢阅读!

P.S I am working on a React book with Ohans Emmanuel that would have you master React by building 30 small projects in 30 days. If you want to stay updated on this, join the mailing list. Thanks!

PS:我正在与Ohans Emmanuel合作编写一本React书,希望您通过在30天内构建30个小型项目来精通React。 如果您想保持最新状态,请加入邮件列表 。 谢谢!

翻译自: https://www.freecodecamp.org/news/how-to-build-a-react-and-gatsby-powered-blog-in-about-10-minutes-625c35c06481/

构建一个react项目

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值