
ãåç¥ã®ããã«ãäžéšã®å®åæã ãã§ã¯ååã«çè§£ã§ããªãããã䟡å€ã®ããäœããæžãæ¹æ³ãåŠã¶ã«ã¯ããããããã¯ãããžãŒã«æ·±ãå
¥ã蟌ãå¿
èŠããããŸãã ãã®èšäºã§ã¯Gatsby.jsã®è©³çްã«ã€ããŠèª¬æããŸãããã®ç¥èã«ãããè€éãªWebãµã€ããããã°ãäœæããã³ç®¡çã§ããŸãã
JAM-stackã䜿çšããŠå人ããã°ãäœæããã³å
¬éããæ¹æ³ã«é¢ãã以åã®èšäº
以äžã§èª¬æãããããã¯ïŒ
æºåãã
GatsbyãPCã«ã€ã³ã¹ããŒã«ããyarn global add gatsby-cli
æå°éã®ãããžã§ã¯ãã®è€è£œ npx gatsby new gatsby-tutorial https://github.com/gatsbyjs/gatsby-starter-hello-world cd gatsby-tutorial
ãªããžããªã®åæå git init git add . git commit -m "init commit"
ãã«ã¹ãã§ã㯠yarn start
ã³ã³ãœãŒã«ã«ãšã©ãŒããªãããã©ãŠã¶ã®ãã¹httpïŒ// localhostïŒ8000ã«æ²¿ã£ãŠãšã©ãŒããªãå ŽåããHello worldïŒã ã衚瀺ãããŸã ã ãã®åŸããã¹ãŠãæ£åžžã«æ©èœããŸãã /src/pages/index.jsãã¡ã€ã«ã®å
容ã倿ŽããŠãããããªããŒãã確èªã§ããŸãã
ããŒãžæ§é ãšã«ãŒãã£ã³ã°
Gatsbyã§ããŒãžãäœæããã«ã¯ãæ°ãããã¡ã€ã«ã/ src / pagesãã©ã«ããŒã«é
眮ããã ãã§ãå¥ã®HTMLããŒãžã«ã³ã³ãã€ã«ãããŸãã ãã®ããŒãžãžã®ãã¹ã¯ãå®éã®ãã¹ãšååãäžèŽããããšã«æ³šæããããšãéèŠã§ãã ããšãã°ãããã«ããã€ãã®ããŒãžã远å ããŸãã
src âââ pages âââ about.js âââ index.js âââ tutorial âââ part-four.js âââ part-one.js âââ part-three.js âââ part-two.js âââ part-zero.js
ã³ã³ãã³ãã¯ãŸã éèŠã§ã¯ãªããããããŒãžãåºå¥ããããã«ä»»æã®ããã¹ãã䜿çšã§ããŸãã
import React from "react"; export default () => <div>Welcome to tutorial/part-one</div>;
ãã©ãŠã¶ã§ãã§ãã¯ã€ã³ããŸãã
ãã®ããã«ããŠããã¡ã€ã«ãæ§é åãããšãã«ãã«ãŒãã£ã³ã°ã®åé¡ãããã«è§£æ±ºã§ããŸãã
ããŒãžã®ãã¹ãšååãããæè»ã«å¶åŸ¡ã§ããç¹å¥ãªcreatePage APIããããŸãããããã䜿çšããã«ã¯ãGatsbyã§ã®ããŒã¿ã®åäœæ¹æ³ãçè§£ããå¿
èŠããããŸãããã®ãããèšäºã§ããå°ãæ€èšããŸãã
ãªã³ã¯ã䜿çšããŠäœæãããããŒãžãçµåããŸããããã«ã¯ãå
éšããã²ãŒã·ã§ã³å°çšã«äœæãããGatsbyããã±ãŒãžã®<Link />
ã³ã³ããŒãã³ãã䜿çšããŸãã ãã¹ãŠã®å€éšãªã³ã¯ã«ã€ããŠãéåžžã®<a>
ã¿ã°ã䜿çšããŸãã
/src/pages/index.js
import React from "react"; import { Link } from "gatsby"; export default () => ( <div> <ul> <li> <Link to="/about">about</Link> </li> <li> <Link to="/tutorial/part-zero">Part #0</Link> </li> <li> <Link to="/tutorial/part-one">Part #1</Link> </li> <li> <Link to="/tutorial/part-two">Part #2</Link> </li> <li> <Link to="/tutorial/part-three">Part #3</Link> </li> <li> <Link to="/tutorial/part-four">Part #4</Link> </li> </ul> </div> );
<Link>
ã¯ãããŒãžã®èªã¿èŸŒã¿ãæé©åããããã®éåžžã«ããªãããŒãªã¡ã«ããºã ãããããã <a>
代ããã«äœ¿çšããŠãµã€ããããã²ãŒãããŸãã 詳现ã¯ãã¡ããã芧ãã ãã ã

ããŒãžãäœæããããªã³ã¯ã远å ãããããã²ãŒã·ã§ã³ãçµäºããããšãããããŸãã
ã³ã³ããŒãã³ãããã³ãã¬ãŒããããã³ãããã®çžäºäœçš
ãåç¥ã®ããã«ãã©ã®ãããžã§ã¯ãã§ãåžžã«èŠçŽ ãç¹°ãè¿ãããŸããWebãµã€ãã®å Žåã¯ãããããŒãããã¿ãŒãããã²ãŒã·ã§ã³ããŒã§ãã ãŸããã³ã³ãã³ãã«é¢ä¿ãªããããŒãžã¯ç¹å®ã®æ§é ã«åŸã£ãŠæ§ç¯ãããŸããGatsbyã¯Reactã®ã³ã³ãã€ã©ãŒã§ããããããããã®åé¡ã解決ããããã«åãã³ã³ããŒãã³ãã¢ãããŒãã䜿çšãããŸãã
ããããŒãšããã²ãŒã·ã§ã³ããã«ã®ã³ã³ããŒãã³ããäœæããŸãã
/src/components/header.js
import React from "react"; import { Link } from "gatsby"; /** * * , React-. * , * " ". * "" GraphQL gatsby- */ import logoSrc from "../images/logo.png"; export default () => ( <header> <Link to="/"> <img src={logoSrc} alt="logo" width="60px" height="60px" /> </Link> That is header </header> );
/src/components/sidebar.js
import React from "react"; import { Link } from "gatsby"; export default () => ( <div> <ul> <li> <Link to="/about">about</Link> </li> <li> <Link to="/tutorial/part-zero">Part #0</Link> </li> <li> <Link to="/tutorial/part-one">Part #1</Link> </li> <li> <Link to="/tutorial/part-two">Part #2</Link> </li> <li> <Link to="/tutorial/part-three">Part #3</Link> </li> <li> <Link to="/tutorial/part-four">Part #4</Link> </li> </ul> </div> );
ãããã/src/pages/index.jsã«è¿œå ããŸã
import React from "react"; import Header from "../components/header"; import Sidebar from "../components/sidebar"; export default () => ( <div> <Header /> <Sidebar /> <h1>Index page</h1> </div> );
ç§ãã¡ã¯ãã§ãã¯ããŸãïŒ

ãã¹ãŠãæ©èœããŸãããåããŒãžã®ããããŒãšãµã€ãããŒãåå¥ã«ã€ã³ããŒãããå¿
èŠããããŸãããããã¯ããŸã䟿å©ã§ã¯ãªãããã®åé¡ã解決ããã«ã¯ã¬ã€ã¢ãŠãã³ã³ããŒãã³ããäœæããŠåããŒãžãã©ããããã ãã§ååã§ãã
ã®ã£ãããŒã¬ã€ã¢ãŠã==åå¿ã³ã³ãããŒ
ã¯ããããã¯ãã»ãŒãåãããšãªã®ã§ãå³å¯ãªå¹³çã§ã¯ãããŸãã
/src/components/layout.js
import React from "react"; import Header from "./header"; import Sidebar from "./sidebar"; export default ({ children }) => ( <> <Header /> <div style={{ margin: `0 auto`, maxWidth: 650, backgroundColor: `#eeeeee` }} > <Sidebar /> {children} </div> </> );
/src/pages/index.js ïŒããã³ä»ã®ãã¹ãŠã®ããŒãžïŒ
import React from "react"; import Layout from "../components/layout"; export default () => ( <Layout> <h1>Index page</h1> </Layout> );
å®äºããã©ãŠã¶ãèŠãŠãã ããïŒ

ãããžã§ã¯ãã®ãã¡ã€ã«åããã¹ãŠå°æåã§ããã®ã¯ãªãã§ããïŒ ãŸãã Reactã®ããŒã ã¹ããŒã¹ã¯ãããã¹ãŠã®ãã¡ã€ã«ãã¯ã©ã¹ã§ãããã¯ã©ã¹ã¯åžžã«å€§æåã§ããããšããäºå®ã«åºã¥ããŠãããšå€æããŸãããã Gatsbyã§ã¯ããã¡ã€ã«ã«ã¯ã¯ã©ã¹ãå«ãŸããŠããŸãããããããã1ã€ãããŸã-ãåãã¡ã€ã«ã¯æœåšçãªããŒãžã§ããããã®ååã¯ãã®ããŒãžãžã®URLã§ããã ã³ãã¥ããã£ã¯ã http://domain.com/User/Settings
//domain.com/User/Settingsã®ãããªãªã³ã¯ã¯comme-il-fautã§ã¯ãªãããã¡ã€ã«åã®kebab-caseãæ¿èªããŠãããšããçµè«ã«éããŸããã
ãã¡ã€ã«æ§é src âââ components â âââ header.js â âââ layout.js â âââ sidebar.js âââ images â âââ logo.png âââ pages âââ about.js âââ index.js âââ tutorial âââ part-eight.js âââ part-five.js âââ part-four.js âââ part-one.js âââ part-seven.js âââ part-six.js âââ part-three.js âââ part-two.js âââ part-zero.js
ããŒã¿ãæäœãã
ãµã€ãæ§é ã®æºåãã§ããã®ã§ãã³ã³ãã³ãã®å
¥åã«é²ãããšãã§ããŸãã åŸæ¥ã®ãããŒãã³ãŒããã¢ãããŒãã¯ãJAMã¹ã¿ãã¯ã®äœæè
ããAJAXãªã¯ãšã¹ãããã³ã³ãã³ããã¬ã³ããªã³ã°ãããã«ã¯é©ããªããããã³ã³ãã€ã«æã«ãµã€ããã³ã³ãã³ãã§åããããšãææ¡ããŸããã Gatsbyã®å Žåã GraphQLããããæ
åœããŸããããã«ãããä»»æã®ãœãŒã¹ããã®ããŒã¿ã¹ããªãŒã ãç°¡åã«æäœã§ããŸãã
GraphQLã«ã€ããŠç°¡åã«èª¬æããããšã¯äžå¯èœãªã®ã§ãèªåã§ç ç©¶ããããæ¬¡ã®èšäºãåŸ
ã€ããšããå§ãããŸãã GraphQLã®æäœã«ã€ããŠè©³ããã¯ã ãã¡ããã芧ãã ãã ã
GraphQLãæäœããããã«ã2çªç®ã®ããŒãžã§ã³ããã gatsby
ããã±ãŒãžã«ã¯ããŒãžãšåçŽãªã³ã³ããŒãã³ãã®äž¡æ¹ã§äœ¿çšã§ããgatsby
ã³ã³ããŒãã³ãããããŸã ãããã¯ãå
è¡ããŒãžã¯ãšãªãšã®äž»ãªéãã§ãã ãããŸã§ã®ãšãããç§ãã¡ã®ãµã€ãã¯ã©ã®ããŒã¿ãœãŒã¹ã«ãæ¥ç¶ãããŠããŸããããã®ãããããšãã°ããŒãžã®ã¡ã¿ããŒã¿ã衚瀺ããŠãããããè€éãªãã®ã«ç§»ããŸãããã
query
ãäœæããã«ã¯ã httpïŒ// localhostïŒ8000 / ___ graphqlãéã ãããã¥ã¡ã³ãã§ãµã€ãããŒã䜿çšããŠãµã€ãã«é¢ããå©çšå¯èœãªããŒã¿ãæ€çŽ¢ããå¿
èŠããããŸãããªãŒãã³ã³ããªãŒããå¿ããªãã§ãã ããã

/src/components/sidebar.js
import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; export default () => ( <StaticQuery query={graphql` { allSitePage { edges { node { id path } } } } `} render={({ allSitePage: { edges } }) => ( <ul> {edges.map(({ node: { id, path } }) => ( <li key={id}> <Link to={path}>{id}</Link> </li> ))} </ul> )} /> );
query
ã䜿çšããŠãããã²ãŒã·ã§ã³ããã«ã§ã¬ã³ããªã³ã°ããããŒãžã«é¢ããããŒã¿ãååŸããŸãããã¹ãŠã®ããŒã¿ãèªåçã«åéãããããããªã³ã¯ãååãšäžèŽããªãããšãå¿é
ããå¿
èŠã¯ãããŸããã

å®éãããã¯ãµãŒãããŒãã£ã®ãã©ã°ã€ã³ã䜿çšãããå€ãè¯ããããŒãã³ãŒããã䜿çšããã«ãµã€ãã«ä¿åã§ãããã¹ãŠã®ããŒã¿ã§ãããããèšäºã®æ¬¡ã®ãããã¯ã§ãããã©ã°ã€ã³ã«ã¹ã ãŒãºã«ç§»è¡ããŸãã
ãã©ã°ã€ã³
ã³ã¢ã®Gatsbyã¯ããã©ã°ã€ã³ã§ããããããã®æ©èœãåããã³ã³ãã€ã©ãŒã§ãã ãããã䜿çšããŠãç¹å®ã®ãã¡ã€ã«ãããŒã¿åãããã³ããŸããŸãªåœ¢åŒã®åŠçãã«ã¹ã¿ãã€ãºã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã¬ãã«ã§/gatsby-config.jsãã¡ã€ã«ãäœæããŸãã ã³ã³ãã€ã©å
šäœã®æ§æãæ
åœãããã¡ã€ã«ãæäœããããã®æåã®ãã©ã°ã€ã³ãæ§æããããšããŸãã
ãã©ã°ã€ã³ã®ã€ã³ã¹ããŒã«ïŒ
yarn add gatsby-source-filesystem
/gatsby-config.jsãã¡ã€ã«ã®èšå®ïŒ
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } } ], }
äžèšã®ãã¡ã€ã«ã«é¢ãã詳现 /** * gatsby-config.js * JS * */ module.exports = { /** * 'plugins' pipeline * , */ plugins: [ /** * , * */ `gatsby-example-plugin`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } } ], }
Gatsbyãžã®ãæ£ãããç»åã®ã€ã³ããŒãã«ã€ããŠè©±ããããšãèŠããŠããŸããïŒ
/src/components/header.js
import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; export default () => ( <StaticQuery query={graphql` { allFile(filter: { name: { eq: "logo" } }) { edges { node { publicURL } } } } `} render={({ allFile: { edges: [ { node: { publicURL } } ] } }) => ( <header> <Link to="/"> <img src={publicURL} alt="logo" width="60px" height="60px" /> </Link> That is header </header> )} /> );
ãµã€ãã§ã¯äœã倿ŽãããŠããŸããããåçŽãªwebpackã€ã³ããŒãã®ä»£ããã«ãGraphQLã䜿çšããŠç»åã眮ãæããããŸãã äžèŠããã¶ã€ã³ãè€éãããŠäžå¿
èŠãªãžã§ã¹ãã£ãŒã§ããããã«æãããããããŸããããåããã©ã°ã€ã³ã«å«ãŸããŠãããããçµè«ã«æ¥ãããªãã§ãã ããã ããšãã°ããµã€ãã«äœåæãã®åçãæçš¿ããããšã«ããå Žåããã¹ãŠã®ã³ã³ãã³ãã®èªã¿èŸŒã¿ãæé©åããããšãèããªããã°ãªããã é
å»¶èªã¿èŸŒã¿ããã»ã¹ããŒãããæ§ç¯ããªãããã«ããã¹ãŠã®èªã¿èŸŒã¿ãæé©åããgatsby-imageãã©ã°ã€ã³ã远å ããã ãã§ãquery
ã䜿çšããŠã€ã³ããŒããããç»åã
ã¹ã¿ã€ãªã³ã°çšã®ãã©ã°ã€ã³ã®ã€ã³ã¹ããŒã«ïŒ
yarn add gatsby-plugin-typography react-typography typography typography-theme-noriega node-sass gatsby-plugin-sass gatsby-plugin-styled-components styled-components babel-plugin-styled-components
gatsby-config.js
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, // add style plugins below `gatsby-plugin-typography`, `gatsby-plugin-sass`, `gatsby-plugin-styled-components` ] };
å
¬åŒWebãµã€ãã§ã¯ããããã奜ã¿ã®ãã©ã°ã€ã³ãèŠã€ããããšãã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¹ã¿ã€ãªã³ã°
ããŸããŸãªã¢ãããŒãã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã®ã¹ã¿ã€ãªã³ã°ãå§ããŸãããã åã®ã¹ãããã§ã¯ã SASS ã styled-components ãããã³typography.jsã©ã€ãã©ãªãæäœããããã®ãã©ã°ã€ã³ãæ¢ã«ã€ã³ã¹ããŒã«ããŸããããcss.modulesã¯ããã«ãµããŒããããããšã«æ³šæããããšãéèŠã§ãã
ãŸããã°ããŒãã«ã¹ã¿ã€ã«ããå§ããŸããããããã¯ããµã€ãå
šäœã«é¢é£ããä»ã®ãã®ãšåæ§ã«ã / gatsby-browser.jsãã¡ã€ã«ã§æ§æããå¿
èŠããããŸãã
import "./src/styles/global.scss";
gatsby-browser.jsã®è©³çް
/src/styles/global.scss
body { background-color: lavenderblush; }
ããŸããŸãªçç±ãããè¿å¹Žã®åŸåã¯ãCSS in JSãã¢ãããŒãã«åŸããŠãããããã°ããŒãã«ã¹ã¿ã€ã«ãä¹±çšããªãã§ãã ããããã©ã³ããšåå©çšã¯ã©ã¹ã®è¡šç€ºã«éå®ããããšããå§ãããŸãã ãã®ç¹å®ã®ãããžã§ã¯ãã§ã¯ããããã®ç®çã§Typography.jsã䜿çšããäºå®ã§ãããããã°ããŒãã«ã¹ã¿ã€ã«ã¯ç©ºã®ãŸãŸã§ãã
gatsby-plugin-typography
ãæ§æã«è¿œå ããåŸããµã€ãã®å€èгã®å€åã«æ¢ã«æ°ã¥ããŠãããããããŸãã-ããã¯ããã©ã«ãã®ããªã»ãããé©çšãããããã§ãã
/src/utils/typography.js
import Typography from "typography"; import theme from "typography-theme-noriega"; const typography = new Typography(theme); export default typography;
ãªã¹ãããä»ã®ããªã»ãããéžæããããããã±ãŒãžAPIã䜿çšããŠç¬èªã®ããªã»ãããäœæã§ããŸãïŒå
¬åŒã®Gatsby Webãµã€ãã®æ§æäŸ ïŒ
/gatsby-config.js
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography` } }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components` ] };
ãŸããéžæããããªã»ããã«å¿ããŠããµã€ãã®ã°ããŒãã«ã¹ã¿ã€ã«ã倿ŽãããŸãã ã°ããŒãã«ã¹ã¿ã€ã«ãèªåã§èšå®ããããã®ã¢ãããŒããæ±ºå®ããã®ã¯ããªã次第ã§ãããå人çãªå¥œã¿ãæè¡çãªèгç¹ããã®éãã®åé¡ã§ã¯ãªãã styled-componentsã䜿çšããã³ã³ããŒãã³ãã®ã¹ã¿ã€ã«èšå®ã«é²ã¿ãŸã
ã°ããŒãã«å€æ°/src/utils/vars.jsãå«ããã¡ã€ã«ã远å ããŸã
export const colors = { main: `#663399`, second: `#fbfafc`, main50: `rgba(102, 51, 153, 0.5)`, second50: `rgba(251, 250, 252, 0.5)`, textMain: `#000000`, textSecond: `#ffffff`, textBody: `#222222` };
/src/components/header.js import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; import styled from "styled-components"; import { colors } from "../utils/vars"; const Header = styled.header` width: 100%; height: 3em; display: flex; justify-content: space-between; align-items: center; background-color: ${colors.main}; color: ${colors.textSecond}; padding: 0.5em; `; const Logo = styled.img` border-radius: 50%; height: 100%; `; const logoLink = `height: 100%;`; export default () => ( <StaticQuery query={graphql` { allFile(filter: { name: { eq: "logo" } }) { edges { node { publicURL } } } } `} render={({ allFile: { edges: [ { node: { publicURL } } ] } }) => ( <Header> That is header <Link to="/" css={logoLink}> <Logo src={publicURL} alt="logo" /> </Link> </Header> )} /> );
/src/components/sidebar.js import React from "react" import { Link, StaticQuery, graphql } from "gatsby" import styled from "styled-components" import { colors } from "../utils/vars" const Sidebar = styled.section` position: fixed; left: 0; width: 20%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: ${colors.second}; color: ${colors.textMain}; ` const navItem = ` display: flex; align-items: center; margin: 0 1em 0 2em; padding: 0.5em 0; border-bottom: 0.05em solid ${colors.mainHalf}; postion: relative; color: ${colors.textBody}; text-decoration: none; &:before { content: ''; transition: 0.5s; width: 0.5em; height: 0.5em; position: absolute; left: 0.8em; border-radius: 50%; display: block; background-color: ${colors.main}; transform: scale(0); } &:last-child { border-bottom: none; } &:hover { &:before { transform: scale(1); } } ` export default () => ( <StaticQuery query={graphql` { allSitePage { edges { node { id, path } } } } `} render={({ allSitePage: { edges } }) => ( <Sidebar> { edges.map(({ node: { id, path } }) => ( <Link to={path} key={id} css={navItem} >{id}</Link> )) } </Sidebar> )} /> )

æ¢åã®èŠçŽ ã¯å®ååãããŠããŸã ãã³ã³ãã³ããContentfulã«é¢é£ä»ããããŒãžã³ãã©ã°ã€ã³ãæ¥ç¶ãã createPages APIã䜿çšããŠããŒãžãçæããŸã ã
GatsbyãšContentfulã®ãªã³ã¯ã®è©³çްã«ã€ããŠã¯ã åã®èšäºãã芧ãã ããã
Contentfulã䜿çšããããŒã¿ã®æ§é [ { "id": "title", "type": "Symbol" }, { "id": "content", "type": "Text", }, { "id": "link", "type": "Symbol", }, { "id": "orderNumber", "type": "Integer", } ]
ããã±ãŒãžã®ã€ã³ã¹ããŒã«ïŒ
yarn add dotenv gatsby-source-contentful gatsby-transformer-remark
/gatsby-config.js
if (process.env.NODE_ENV === "development") { require("dotenv").config(); } module.exports = { plugins: [ `gatsby-transformer-remark`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography`, }, }, { resolve: `gatsby-source-contentful`, options: { spaceId: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, }, }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components`, ], }
ãã¹ãŠã®ãã¡ã€ã«ãå«ã/ src / pagesãã©ã«ããŒãåé€ããGatsbyã®ããŒãã管çããæ°ãããã¡ã€ã«ãäœæããŸãã
/gatsby-node.js
const path = require(`path`); /** * , * */ exports.createPages = ({ graphql, actions }) => { /** * * * */ const { createPage } = actions; return graphql(` { allContentfulArticle { edges { node { title link content { childMarkdownRemark { html } } } } } } `).then(({ data: { allContentfulArticle: { edges } } }) => { /** * * createPage() * */ edges.forEach(({ node }) => { createPage({ path: node.link, component: path.resolve(`./src/templates/index.js`), context: { slug: node.link } }); }); }); };
gatsby-node.jsã®è©³çް
çæãããããŒãžã®åºç€ãšãªããã³ãã¬ãŒããã¡ã€ã«ãäœæãã
/src/templates/index.js
import React from "react"; import { graphql } from "gatsby"; import Layout from "../components/layout"; export default ({ data: { allContentfulArticle: { edges: [ { node: { content: { childMarkdownRemark: { html } } } } ] } } }) => { return ( <Layout> <div dangerouslySetInnerHTML={{ __html: html }} /> </Layout> ); }; export const query = graphql` query($slug: String!) { allContentfulArticle(filter: { link: { eq: $slug } }) { edges { node { title link content { childMarkdownRemark { html } } } } } } `;
ããã§<StaticQuery />
ã³ã³ããŒãã³ãã䜿çšãããªãã®ã¯ãªãã§ããïŒ åé¡ã¯ããªã¯ãšã¹ããæ§ç¯ããããã®å€æ°ããµããŒãããŠããªãããšã§ãããããŒãžã³ã³ããã¹ããã$slug
倿°ã䜿çšããå¿
èŠããããŸãã
ããã²ãŒã·ã§ã³ããŒã®ããžãã¯ãæŽæ°ãã import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; import styled from "styled-components"; import { colors } from "../utils/vars"; const Sidebar = styled.section` position: fixed; left: 0; width: 20%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: ${colors.second}; color: ${colors.textMain}; `; const navItem = ` display: flex; align-items: center; margin: 0 1em 0 2em; padding: 0.5em 0; border-bottom: 0.05em solid ${colors.main50}; postion: relative; color: ${colors.textBody}; text-decoration: none; &:before { content: ''; transition: 0.5s; width: 0.5em; height: 0.5em; position: absolute; left: 0.8em; border-radius: 50%; display: block; background-color: ${colors.main}; transform: scale(0); } &:last-child { border-bottom: none; } &:hover { &:before { transform: scale(1); } } `; export default () => ( <StaticQuery query={graphql` { allContentfulArticle(sort: { order: ASC, fields: orderNumber }) { edges { node { title link orderNumber } } } } `} render={({ allContentfulArticle: { edges } }) => ( <Sidebar> {edges.map(({ node: { title, link, orderNumber } }) => ( <Link to={link} key={link} css={navItem}> {orderNumber}. {title} </Link> ))} </Sidebar> )} /> );

SEOã®æé©å
æè¡çãªé¢ã§ã¯ããµã€ãã¯æºåãã§ããŠãããšèŠãªãããšãã§ããŸãããã®ãããã¡ã¿ããŒã¿ãæäœããŸãããã ãããè¡ãã«ã¯ã次ã®ãã©ã°ã€ã³ãå¿
èŠã§ãã
yarn add gatsby-plugin-react-helmet react-helmet
react-helmetã¯HTMLããŒãžçšã«<head>...</head>
ãçæããGatsbyã¬ã³ããªã³ã°ãšé£æºããŠãSEOãæäœããããã®åŒ·åã§äŸ¿å©ãªããŒã«ã§ãã
/src/templates/index.js
import React from "react"; import { graphql } from "gatsby"; import { Helmet } from "react-helmet"; import Layout from "../components/layout"; export default ({ data: { allContentfulArticle: { edges: [ { node: { title, content: { childMarkdownRemark: { html } } } } ] } } }) => { return ( <Layout> <Helmet> <meta charSet="utf-8" /> <title>{title}</title> </Helmet> <div dangerouslySetInnerHTML={{ __html: html }} /> </Layout> ); }; export const query = graphql` query($slug: String!) { allContentfulArticle(filter: { link: { eq: $slug } }) { edges { node { title link content { childMarkdownRemark { html } } } } } } `;
ããtitle
ãµã€ãã®title
ã¯åžžã«èšäºã®ã¿ã€ãã«ãšäžèŽããŸããããã¯ããã®åé¡ã«ç¹åããæ€çŽ¢çµæã§ã®ãµã€ãã®çºè¡ã«å€§ããªåœ±é¿ãäžããŸãã ããã§ç°¡åã«<meta name="description" content=" ">
ã«åèšäºã®èª¬æãåå¥ã«è¿œå ã§ããããããŠãŒã¶ãŒã¯æ€çŽ¢ããŒãžã§èšäºã®å
容ãçè§£ã§ããŸããäžè¬ã«ããã¹ãŠã®SEOæ©èœãå©çšå¯èœã«ãªãã管çå¯èœã«ãªããŸããäžã€ã®å Žæã

PWAã»ããã¢ãã
Gatsby㯠ãããã«æé«ã®ããã©ãŒãã³ã¹ãæäŸããããã«èšèšãããŠããŸãã 圌ã¯ãã³ãŒãã®åé¢ãšæå°åãããã¯ã°ã©ãŠã³ãã§ã®ããªããŒããç»ååŠçãªã©ã®æé©åã®åé¡ãåŠçããäœæãããµã€ããæåèšå®ãªãã§é«ãããã©ãŒãã³ã¹ãçºæ®ã§ããããã«ããŸãã ãããã®ããã©ãŒãã³ã¹æ©èœã¯ãããã°ã¬ãã·ãWebã¢ããªã±ãŒã·ã§ã³ã¢ãããŒãããµããŒãããéèŠãªéšåã§ãã
ãã ããäžèšã®ãã¹ãŠã«å ããŠããµã€ããPWAãšããŠå®çŸ©ãã3ã€ã®åºæ¬çãªåºæºããããŸãã
ãã¡ã€ã³ ã ãã¹ãã£ã³ã° ã ãããã³ã«ã¯ãããã€ã¡ã³ãã®åé¡ã§ãããéçºã§ã¯ãªããããæåã®ç¹ã¯Gatsbyã§è§£æ±ºã§ããŸããããããã©ã«ãã§httpsã®åé¡ã解決ããNetlifyããå§ãããŸãã
æ®ãã®é
ç®ã«é²ã¿ãŸããããã®ããã«ã2ã€ã®ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ããŸãã
yarn add gatsby-plugin-manifest gatsby-plugin-offline
/src/gatsby-config.jsãèšå®ããŸã
if (process.env.NODE_ENV === "development") { require("dotenv").config(); } module.exports = { plugins: [ { resolve: `gatsby-plugin-manifest`, options: { name: `GatsbyJS translated tutorial`, short_name: `GatsbyJS tutorial`, start_url: `/`, background_color: `#f7f0eb`, theme_color: `#a2466c`, display: `standalone`, icon: `public/favicon.ico`, include_favicon: true } }, `gatsby-plugin-offline`, `gatsby-transformer-remark`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography` } }, { resolve: `gatsby-source-contentful`, options: { spaceId: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_TOKEN } }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components`, `gatsby-plugin-react-helmet` ] };
ããã¥ã¡ã³ãã䜿çšããŠãããã§ã¹ããã«ã¹ã¿ãã€ãºãããããã©ã°ã€ã³èšå®ãäžæžãããŠãµãŒãã¹ã¯ãŒã«ãŒã®æŠç¥ãã«ã¹ã¿ãã€ãºãããã§ããŸã ã
éçºã¢ãŒãã®å€æŽã«æ°ä»ãããšã¯ãããŸãããããµã€ãã¯ãã§ã«Webã¯ãŒã«ãã®ææ°ã®èŠä»¶ãæºãããŠãããhttpsïŒ//ãã¡ã€ã³ã§ãã¹ããããŠããå Žåã¯åçã§ã¯ãããŸããã
ãããã«
æ°å¹ŽåãReactã¢ããªã±ãŒã·ã§ã³ãã€ã³ã¿ãŒãããã«æã¡èŸŒãéã®åé¡ããã®ãµããŒãããã³ã³ã³ãã³ãã®æŽæ°ã«æåã«ééãããšããããããã¹ãŠã®ããã»ã¹ãç°¡çŽ åããJAMã¹ã¿ãã¯ã¢ãããŒãããã§ã«åžå Žã«ååšããŠããããšãæ³åã§ããŸããã§ããããä»ã§ã¯é©ããŸããã·ã³ãã«ã Gatsbyã¯ããµã€ãã®ããã©ãŒãã³ã¹ã«åœ±é¿ããã»ãšãã©ã®åé¡ããããã«äœ¿ãããç¶æ
ã§è§£æ±ºããŸããããŒãºã«åãããŠã«ã¹ã¿ãã€ãºããããšã®è€éãã«ã€ããŠããå°ãçè§£ããã°ã Lighthouseã®ãã¹ãŠã®ã¢ã€ãã ã«å¯ŸããŠ100ïŒ
ã®ã€ã³ãžã±ãŒã¿ãŒãååŸã§ããæ€çŽ¢ãšã³ãžã³ã§ã®ãµã€ãã®é
ä¿¡ã«å€§ãã圱é¿ããŸãïŒbyå°ãªããšãGoogleã§ïŒã
ãããžã§ã¯ãã®ãããªããžããª