用Gatsby和Strapi建立一个静态博客(翻译和本身探索过程当中的经验总结)

用Gatsby和Strapi建立一个静态博客(翻译和本身探索过程当中的经验总结)

原文参阅: Building a static blog using Gatsby and Strapihttps://blog.strapi.io/buildi.... 本篇主要是对其精华内容进行翻译, 以及实操过程当中遇到的问题解决和探索. 一些具体的操做步骤和细节, 我将忽略, 结合原文一块儿阅读效果更佳!

注: 本文操做环境是Linux VPS, CentOS 6 64bitjavascript

介绍

这是一个包含不少静态内容页面的站点, 从技术上来讲就如同一系列HTML文件, 展现给访问者. 与动态网站不一样的是, 他不须要后端开发或者数据库支撑. 发布静态站点之因此容易, 是由于文件只须要上传到服务器或者存储器. 没有额外的渲染页面的请求, 也没有数据库被黑的风险, 因此它既安全也快速.html

为了快速建站, 其实不少开源的静态页面生成框架可用, 好比前阵子我搞的Jekyll, Hugo, 好似国人偏心的Hexo等等, 他们的工做原理类似, 内容都是经过静态文件(好比Markdown)或者带有内容的API, 经过获取这些内容, 注入到开发者作好的模板, 最后生成一大堆HTML文件.前端

Progressive Web Apps (PWA)其实是网页应用, 几乎基于Javascript, 而且可靠, 快速, 有吸引力的. 这几年比较火的Angular, Vue, React都是相似的前端框架.java

静态站点碰见了PWA就产生了Gatsby

将这两点组合起来的最佳选择看起来就是Gatsby了, 可是一样须要一个内容接口, 这就是我将要展现的, 经过Strapi建立一个内容API提供给Gatsby, 而后打包发布出一个静态站点.node

Gatsby是什么

这个并非型男熟知的杰士派, 虽然我也用过这个发泥, 好像不是很好用. Gatsby是基于React的快速静态网站框架, 有了它, 你就能够感受飘飘然的开发React网站了.react

Strapi是什么

Strapi是一个基于高级的Nodejs API内容管理框架. 听起来有点绕口, 通俗来讲就是让你能简单, 安全, 高效的开发出强大API的开源的内容管理框架. 它是免费的, 人们都爱免费的, 能够随意在你的服务器上使用, 也很是具备可个性化, 可扩展性的玩意.linux

我真想不到国内几乎没有人用Gatsby和Strapi, 百度上查不到任何资料...

建立API

见证奇迹的时刻即将到来, 咱们快建立个Strapi API, 添加点内容吧!webpack

建立Strapi项目

Requirements: please make sure Node 8 (or higher) and MongoDB are installed and running on your machine.

此时, 暗喜前阵子已经琢磨出来了并装好了Node 8, 不过装MongoDB就没有了. 所以这里就要插入一段关于MongoDB的内容了. 若是已经有了请自动跳过此内容.git

MongoDB安装及相关问题

果断找到文档Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux, 这个redhat和centOS应该是通用的吧- -! 看到Configure the package management system (yum)., 发现原来还有这种操做, 建立repo文件, 来安装对应版本的软件. 闲话少说, 直接上代码:github

# cd /etc/yum.repos.d/
# touch mongodb-org-3.6.repo
# vi mongodb-org-3.6.repo

将如下内容copy进去保存

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

再进行安装

# sudo yum install -y mongodb-org
若是有特殊需求, 请参阅上文提到的官方文档, 我这里装的是MongoDB Community Edition

按以上步骤很快就装好了. 接下来启动mongod(若是没有启动的话), 以下命令:

# service mongod start

完成后, 咱们接着建立Strapi项目的主题, 推荐安装strapi@alpha版本:

# npm i strapi@alpha -g

完成后, 去到你要建立本文项目的目录, 好比我这里的路径是/home/web/, 我在这里建立一个gatsby-strapi-tutorial目录:

# mkdir gatsby-strapi-tutorial

在这里面搭一个API脚手架

# cd gatsby-strapi-tutorial
# strapi new api

进入项目目录, 并运行Node.js服务器

# cd api
# strapi start

遇到了一些小问题

这里忽然时不时卡住了, 若是你很顺利, 那么能够跳过此内容, 频繁报错以下

[root@whidy api]# strapi start
DEBUG (24910 on whidy): Server wasn't able to start properly.
ERROR (24910 on whidy): (hook:mongoose) takes too long to load

大概是网络缘由, 我联通网络出问题, 换了电信几番尝试就行了.

操做过程当中频繁出现刚才的问题, 我以为不是网络问题那么简单, 我打算从数据库方面着手完善一下试试, 固然后来证实, 一切问题都与MongoDB无关, 因此下面缩进内容能够选择性阅读

大多数状况下我是不肯意理睬WARNING信息的, 只要不是ERROR就好, 可是此次我有点不爽, 后来折腾了半天发现有的很难处理, 好吧我错了, 我想我仍是不死磕了吧?.

  • soft rlimits too low

    WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.

    参阅:

  • versions of RHEL older than RHEL6

    WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

    服务器硬件限制? 能够安全忽略.

    参阅: WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

  • Access Control
    觉得要搞帐户什么的, 而后运行mongo命令, 建立了一个admin帐户:

    # mango
    > use admin
    > db.createUser(
        {
          user: "username",
          pwd: "userpassword",
          roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
      )
    # mongo --port 27017 -u "username" -p "userpassword" --authenticationDatabase "admin"

    其实我本身当时也不知道是搞啥, 其实彻底不要紧的操做. 不少人甚至官方文档Start MongoDB without access control.也提到:

    mongod --port 27017 --dbpath /data/db1

    但是我一直报错, 要么说不存在, 搞半天才明白, 要手动建立, 建立好了, 又说服务被占用, service mongod stop停了服务, 连上去了, show dbs发现跟以前的又不同, 没有找到我以前看到的strapi库, 才恍然大悟, 原来其实我建立了一个跟以前无关的库...

    事实上, 启动mongod服务的时候, 它链接了一个默认配置库, 这个库的路径时早就建立好的, 经过查看/etc/mongod.conf这个文件就知道了. 所以删了那个没用的db目录. 接着操做.

    后来次日早上, 再次执行strapi start很顺利. 我也没办法再研究昨天到底是为何老是连不上了. 反正就是渣渣网络常常会带来各类坑!?, 这段没什么做用的内容就过去了.

回到刚才strapi start, 成功以后, 咱们若是是本地操做的, 带有界面的操做系统的话就能够直接访问http://localhost:1337/admin了, 若是也是远程操做, 就改为IP就行了.

接下来的操做是建立用户, 原文已经图文并茂, 傻子都能看懂的步骤了, 因为篇幅过大, 我就简单翻译一下, 不详细复述了嘿嘿~

按照原文操做:

  1. 建立管理员帐号(Create your first User)
  2. 建立内容类型(Create a Content Type)
    名为article的内容类型有三个字段: title(字符串), content(文本), author(关系, 多文章对应一个用户).
  3. 添加几项内容到数据库

    1. 访问文章列表页
    2. 点击Add New Article
    3. 插入值, 链接对应的做者并保存
    4. 重复以上操做, 建立额外两篇文章
  4. 容许API权限, 依原文对应勾选保存

完成后, 就能够访问http://localhost:1337/article了.

建立静态站

到目前, 你的API搞定了, 咱们要搞静态网站啦

安装Gatsby

首先, 全局安装Gatsby CLI:

# npm install --global gatsby-cli

生成Gatsby项目

回到以前提到的gatsby-strapi-tutorial目录, 建立一个新博客:

# gatsby new blog
事情老是不是那么顺利.

报错, 须要git. 然而个人这台崭新的服务器还没装, 那就装一个吧.

若是你的git已经部署OK, 而且上面这个操做没有问题, 如下内容可忽略:

参考Download for Linux and Unix执行:

# yum install git

再次执行后依旧报错(当前git版本1.7.1)

error Command failed: git clone git://github.com/gatsbyjs/gatsby-starter-default.git blog --single-branch

推测是版本问题. 只好手动安装了. 因而又找到这个安装 Git

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# wget https://www.kernel.org/pub/software/scm/git/git-2.16.1.tar.gz
# tar -zxf git-2.16.1.tar.gz
# cd git-2.16.1
# make prefix=/usr/local all
# sudo make prefix=/usr/local install

漫长的make prefix=/usr/local all以后, 提示:

SUBDIR perl
/usr/bin/perl Makefile.PL PREFIX=\'/usr/local\' INSTALL_BASE=\'\' --localedir=\'/usr/local/share/locale\'
Can\'t locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.
BEGIN failed--compilation aborted at Makefile.PL line 3.
make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2

蛋疼, 等了半天, 又要解决这个问题, 好在看起来比较容易处理, 参考git fails to build in Fedora 14, 而后继续执行最后两条make命令, 虽然最后出来不少看起来很奇怪的内容, 不过彷佛是成功了. 执行:

# git --version
git version 2.16.1

接下来咱们再一次执行gatsby new blog, 我擦还提示刚才的...single-branch的error, 这就坑爹了- -. 通过简短的排查. 原来彷佛他仍是跑的旧版git, 须要删掉以前yum自动安装的git 1.7.1, 我单纯的觉得直接自动升级了. 因而:

# yum remove git

按照提示删除成功后, 再次检测git仍是ok的, 此次我第三次执行gatsby new blog, 终于成功了!

我这小白也不知道linux软件管理是咋整的. 反正能继续执行卡了我半天的gatsby就行了吧...

每次建立速度很慢, 执行gatsby new blog完成的时候提示added 1398 packages in 137.652s, 大概就是2分钟多, 多是安装依赖包费时吧

启动开发模式

建立成功后, 接着操做, 进入博客目录

# cd blog

启动服务器

# gatsby develop

理论上你就能够经过http://localhost:8000访问到默认的效果博客站点了.

然而又一次出现小插曲, 若是你是和我同样远程访问, 也许如下内容对你有用

每次执行gatsby develop的时间甚至更长, 完成时提示以下:

info bootstrap finished - 334.876 s

DONE  Compiled successfully in 90373ms 21:15:06


You can now view gatsby-starter-default in the browser.

http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema

http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use gatsby build

大概用了6分钟左右, 糟糕的是并不能经过远程IP来访问! 查看了目录下的配置文件和官方文档, 也没查到. 绝望之时, 忽然在大量资料中看到webpack也有这样的问题, 想起来以前webpack的server默认配置也是没法经过ip访问, 可是webpack的devServer配置host: "0.0.0.0"便可, 试了下:

# gatsby develop --host 0.0.0.0

又通过4分钟左右漫长等待, 此次成功了! 不过我尝试搜索Gatsby究竟用的什么服务器启动, 为什么不能像webpack那样加一段配置呢, 却没有找到. 后来凑巧找到了一篇webpack下的issue, Server can't be accessed via IP, 有人提到过这条命令.

所以, 从小插曲中来看, 远程访问控制的开发者, 须要加个参数, 具体命令:

# gatsby develop --host 0.0.0.0

这样, 至此开发模式服务器搞定.

安装Strapi插件(Install the Strapi source plugin)

Gatsby understands this pretty well. So its creators decided to build a specific and independent layer: the data layer. This entire system is strongly powered by GraphQL.

前面有一些插件介绍很少说了, 执行安装:

# npm install --save gatsby-source-strapi

完成后, 须要作些配置, 修改gatsby-config.js文件, 替换成如下内容:

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-strapi`,
      options: {
        apiURL: `http://localhost:1337`,
        contentTypes: [ // List of the Content Types you want to be able to request from Gatsby.
          `article`,
          `user`
        ]
      },
    },
  ],
}

保存后, 重启Gatsby服务器

文章列表

为了在首页显示文章列表, 咱们须要修改首页代码以下:

路径: src/pages/index.js

import React from 'react'
import Link from 'gatsby-link'
const IndexPage = ({ data }) => (
  <div>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <ul>
      {data.allStrapiArticle.edges.map(document => (
        <li key={document.node.id}>
          <h2>
            <Link to={`/${document.node.id}`}>{document.node.title}</Link>
          </h2>
          <p>{document.node.content}</p>
        </li>
      ))}
    </ul>
    <Link to="/page-2/">Go to page 2</Link>
  </div>
)
export default IndexPage
export const pageQuery = graphql`
  query IndexQuery {
    allStrapiArticle {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`

这里就应用到了GraphQL啦, 好激动呢. 咱们导出pageQuery, 一个GraphQL查询会请求文章列表, 咱们只须要将须要查询的字段添加进去就行了~

而后咱们传递{ data }这个结构对象做为IndexPage参数, 遍历它的allStrapiArticles对象, 来展现数据.

GraphQL查询能够快速生成, 你能够尝试在 http://localhost:8000/___graphql修改, 并测试.

文章页

首页有了列表以后, 咱们还要访问文章页面呢, 接下来写一个模板:

路径: src/templates/article.js

import React from 'react'
import Link from 'gatsby-link'
const ArticleTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiArticle.title}</h1>
    <p>by <Link to={`/authors/${data.strapiArticle.author.id}`}>{data.strapiArticle.author.username}</Link></p>
    <p>{data.strapiArticle.content}</p>
  </div>
)
export default ArticleTemplate
export const query = graphql`
  query ArticleTemplate($id: String!) {
    strapiArticle(id: {eq: $id}) {
      title
      content
      author {
        id
        username
      }
    }
  }
`

你须要手动建立这个目录和文件, 固然Gatsby并不知道模板什么时候展现. 每篇文章都须要一个特别的URL, 感谢Gatsby提供的createPage函数.

首先, 咱们写个makeRequest函数来处理GraphQL请求. 而后经过createPage函数使咱们在获取的文章列表后为它们建立一个页面, 路径为文章id的URL, 回到blog目录, 修改gatsby-node.js文件

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Query for articles nodes to use in creating pages.
  return getArticles;
};

再次重启Gatsby服务器.

如今你就能经过点击首页的文章进入到文章内容页面了.

做者页

虽然这个彷佛并不重要, 不过仍是加上学习一下吧?

添加做者页和建立文章页很类似, 咱们仍是先建立个模板:

路径: src/templates/user.js

import React from 'react'
import Link from 'gatsby-link'
const UserTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiUser.username}</h1>
    <ul>
      {data.strapiUser.articles.map(article => (
        <li key={article.id}>
          <h2>
            <Link to={`/${article.id}`}>{article.title}</Link>
          </h2>
          <p>{article.content}</p>
        </li>
      ))}
    </ul>
  </div>
)
export default UserTemplate
export const query = graphql`
  query UserTemplate($id: String!) {
    strapiUser(id: { eq: $id }) {
      id
      username
      articles {
        id
        title
        content
      }
    }
  }
`

而后再次修改gatsby-node.js来建立做者URLs:

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for article nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});

// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  const getAuthors = makeRequest(graphql, `
    {
      allStrapiUser {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each user.
    result.data.allStrapiUser.edges.forEach(({ node }) => {
      createPage({
        path: `/authors/${node.id}`,
        component: path.resolve(`src/templates/user.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Queries for articles and authors nodes to use in creating pages.
  return Promise.all([
    getArticles,
    getAuthors,
  ])
};

重启服务器, 刷新页面, Wow! 大功告成! 时不时很酷!!!

原文总结

恭喜, 你成功的建立了一个超快的很好维护的博客! 而后各类夸奖Blabla

接下来作什么呢? 你能够去更多的挖掘Gatsby和Strapi的各类优势, 你能够试着增长这些功能:

  • 做者列表
  • 文章分类
  • 用Strapi API建立评论系统, 或者直接用Disqus
  • 固然你也能够试着搞其余站点, 例如电商站, 企业站等等

固然为了进一步方便开发, 你可能须要一个方便的发布在网上的存储载体, Blablabla...

本教程GitHub源码地址, 你能够clone下来, 运行npm run setup, blablabla... 我是个爱研究的人, 我要一步步操做, 才不要clone.

我的总结

此次经过Gatsby和Strapi搭建一个简单的博客站点, 仍是挺不容易的, 总共花了将近两天的时间. 不过我的感受仍是值得的! 其中有不少地方是能够更加深刻的学习和了解的, 这也算初步接触了react, mongodb, graphQL等相关知识实操, 同时也能够在后期完善更多的功能, 了解并学习一些ES6, 模板的写法技巧等等. 也但愿经过这次研究之后能更进一步熟悉其余框架, 数据库, 后端等思想~

相关参阅汇总

最后打个小广告, 我有个GitHub项目, 用于记录我天天学习或者瞎折腾的技术, 范围不限, 有兴趣能够star个人whidy daily

相关文章
相关标签/搜索