약 10 분 안에 React 및 Gatsby 기반 블로그를 구축하는 방법

면책 조항 : 이것은 Gatsby 버전 1 용으로 작성되었으며 버전 2는 방금 출시되었으며 일부 변경 사항이 있습니다. 다른 튜토리얼에서 작업하겠습니다.

Gatsby 는 ReactJS를 기반으로 한 초고속 정적 사이트 생성기입니다.

정적 사이트 발생기 (SSG)는 하드 코딩 된 HTML의 사이에 타협 정적 사이트 와 워드 프레스 같은 만발한 CMS (콘텐츠 관리 시스템).

SSG는 콘텐츠 기반 웹 사이트 (예 : 블로그)에 대한 HTML 페이지를 생성하는 데 사용할 수 있습니다. 필요한 것은 페이지 콘텐츠에 대한 데이터와 콘텐츠를 채울 템플릿입니다.

이 게시물은 5 개의 섹션으로 나뉩니다.

  1. 시작하기.
  2. 레이아웃 구성 요소 생성.
  3. 블로그 게시물 작성.
  4. 블로그 게시물 데이터에서 새 페이지 생성.
  5. 랜딩 페이지에서 당사 사이트의 마크 다운 파일 목록을 생성하십시오.

CodeStack 이라는 가상의 정적 블로그를 만들어 Gatsby와 일부 기능에 대해 자세히 살펴 보겠습니다. 모형은 아래와 같습니다. 가자! ✌️

1. 시작하기

전제 조건

먼저 시스템에 Node.js가 설치되어 있는지 확인하십시오. 그렇지 않은 경우 nodejs.org 로 이동하여 운영 체제에 맞는 최신 버전을 설치하십시오.

또한이 기사는 여러분이 ReactJS를 이해하고 있다고 가정합니다.

CLI 설치

Gatsby에는 다음과 같은 유용한 명령을 제공하는 명령 줄 도구가 있습니다.

  • gatsby new: 새 Gatsby 프로젝트를 스캐 폴딩합니다.
  • gatsby develop: 핫 리로드 지원 웹 개발 서버를 시작합니다.
  • gatsby build: 프로젝트의 프로덕션 준비 버전을 빌드합니다.

설치하려면 터미널에 다음을 입력하고 Enter 키를 누르십시오.

npm install --global gatsby-cli

프로젝트 폴더를 만들고 codestack-blog터미널을 탐색 해 보겠습니다 .

gatsby new codestack-blog && cd $_

gatsby develop프로젝트 폴더에서 실행 하면 스캐 폴딩 된 사이트는 다음과 같아야합니다.

플러그인 추가

Gatsby에는 크고 성장하는 플러그인 세트가 있습니다. 본질적으로 Gatsby의 API와 인터페이스하는 Node.js 패키지입니다.

터미널의 NPM (노드 패키지 관리자)을 통해 설치할 수 있으며 일반적으로 기능 , 소스변환기 플러그인의 세 가지 범주가 있습니다.

기능성 플러그인

이러한 플러그인은 Gatsby 사이트 또는 개발 환경에서 추가 기능을 제공합니다. 앱의 경우 다음이 필요합니다.

  • gatsby-plugin-react-helmet: head태그 를 수정할 수 있습니다 . 스캐 폴딩 된 프로젝트에 이미 설치되어 있습니다.
  • gatsby-plugin-catch-links: 마크 다운 및 기타 비 반응 페이지에서 로컬 링크를 가로 채고 브라우저가 페이지를 새로 고칠 필요가 없도록 클라이언트 측 pushState를 수행합니다.

플러그인을 설치하거나 두 번째 플러그인 만 설치하십시오.

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

새 플러그인을 추가 할 때마다 새 플러그인으로 gatsby-config.js파일 을 업데이트해야 Gatsby가 인식하고 사용할 수 있습니다. 우리는 사용 백 틱 .

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

소스 플러그인

이 플러그인은 원격 또는 로컬 위치의 데이터를 Gatsby가 노드 라고 부르는 위치로 "소스"합니다 . 로컬 디스크의 Markdown에 게시물을 작성하려면 다음이 필요합니다.

  • gatsby-source-filesystem: 컴퓨터의 파일 시스템에서 파일에 대한 데이터를 가져옵니다.
npm install gatsby-source-filesystem

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', }, } ],}

여기서 무슨 일이 일어나고 있습니까? options목적은 더 많은 구성을위한 플러그인에 전달 될 수 있습니다. 파일 시스템 path(즉, Markdown 파일이 위치 할 위치)과 name소스 파일을 전달하여 Gatsby가 소스 파일과 변환기 플러그인을 적용 할 위치를 알 수 있도록합니다.

Transformer 플러그인

이 플러그인은 노드 에서 원시 데이터를 변환합니다.사용 가능한 데이터 형식으로. 예를 들어 다음이 필요합니다.

  • gatsby-transformer-remark: .md로컬 디스크의 마크 다운 파일로 작성된 블로그 게시물 을 렌더링을 위해 HTML로 변환합니다.
npm install gatsby-transformer-remark

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. 레이아웃 구성 요소 만들기

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.

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.

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.

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.

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.

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.

* { 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 = () => ( 

CodeStack

);

Also, create a Sidebar component.

const Sidebar = (props) => (
{props.title}. {props.description} 
);

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

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.

npm install --save react-media

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

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):

const TemplateWrapper = ({ children }) => ( {matches => matches ? ( {children()} ) : ( {children()} 
 ) } );

Original text


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.

 {matches => matches ? ( ...stuff to render... ) : ( ...stuff to render... ) } 

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

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

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.

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.

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!

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.

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

---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.

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.

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.

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).

import React from "react";import Helmet from "react-helmet";
export default function Template({ data }) { const post = data.markdownRemark; return ( 

{post.frontmatter.title}

);}

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

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.

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

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

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 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.

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

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.

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

Furthermore, recall markdownRemark transformed our markdown files. It will be treated as a property whose contents will be available via 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.

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

import React from "react";import Helmet from "react-helmet";
export default function Template({ data }) { const post = data.markdownRemark; return ( 

{post.frontmatter.title}

);}
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.
  • We have a single, lonely Markdown file that will be rendered as a blog post.
  • 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.

Sweet!

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.

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

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 //localhost:8000/hello-world.

Create another file 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.
// some css grid code 

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

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

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:

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 ( {posts .filter(post => post.node.frontmatter.title.length > 0) .map(({ node: post }) => { return ( 

{post.frontmatter.title}

{post.frontmatter.date}

{post.excerpt}

); })} );}
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:

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

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!

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!