使用Next.js和Strapi创建一个简单的博客

作者 : IT 大叔 本文共7598个字,预计阅读时间需要19分钟 发布时间: 2020-09-7

内容

  • 在本地设置Strapi并将其部署到heroku
  • Next.js的数据获取策略
  • 创建动态路线
  • 基本的GraphQl
  • 静态SSR
  • 部署前端以进行celcel

首先需要什么

  1. Github帐户
    创建一个github帐户生成一个新的ssh密钥。然后将其添加到您的github帐户,就可以了。
  2. 代码编辑器
  3. Heroku帐户

如果您没有帐号,请创建一个帐号

  1. 安装heroku CLI
  2. 节点js
  3. PostgreSQL

II 为Arch 安装了它,但您可以通过Google搜索如何为env安装它

渲染策略

检查这个出来。

在本文中,我将重点介绍此博客的静态SSR策略。我喜欢它,因为它将适合90%的用例,并且我认为它的性能很高。

使用CLI安装Strapi

1.从您的CLI登录到Heroku

接下来,您需要从计算机登录到Heroku。

heroku login

按照说明进行操作,并返回到命令行。

2.创建一个新的Strapi项目

yarn create strapi-app strapi-blog

出现提示时,按以下顺序回答:

3. 初始化一个Git仓库并提交您的项目

初始化Git仓库

cd my-project
git init

添加heroku遥控器

heroku git:remote -a blog-strapi-app

现在,您已经设置并配置了本地开发环境以与Heroku一起使用。您有一个新的Strapi项目和一个新的Heroku应用程序,可以将它们配置为与数据库一起使用。

4. Heroku数据库设置

heroku addons:create heroku-postgresql:hobby-dev

5.数据库凭证

该加载项自动将数据库凭据公开到您的应用可访问的单个环境变量中。要检索它,请键入:

heroku config

这应该打印如下内容:DATABASE_URL: postgres://ebitxebvixeeqd:dc59b16dedb3a1eef84d4999sb4baf@ec2-50-37-231-192.compute-2.amazonaws.com: 5432/d516fp1u21ph7b

(此URL的读取方式如下:postgres:// USERNAME :PASSWORD @ HOSTPORTDATABASE_NAME

6. 设置环境变量

Strapi希望每个数据库连接配置(主机,用户名等)都有一个变量。因此,从上面的URL,您必须在Heroku配置中设置几个环境变量:

heroku config:set DATABASE_USERNAME=ebitxebvixeeqd
heroku config:set DATABASE_PASSWORD=dc59b16dedb3a1eef84d4999a0be041bd419c474cd4a0973efc7c9339afb4baf
heroku config:set DATABASE_HOST=ec2-50-37-231-192.compute-2.amazonaws.com
heroku config:set DATABASE_PORT=5432
heroku config:set DATABASE_NAME=d516fp1u21ph7b

将以上这些值替换为您的实际值。

7. 更新您的数据库配置文件

将以下内容替换为config/database.js

module.exports = ({ env }) => ({
  defaultConnection: 'default',
  connections: {
    default: {
      connector: 'bookshelf',
      settings: {
        client: 'postgres',
        host: env('DATABASE_HOST', '127.0.0.1'),
        port: env.int('DATABASE_PORT', 27017),
        database: env('DATABASE_NAME', 'my-blog-db'),
        username: env('DATABASE_USERNAME', ''),
        password: env('DATABASE_PASSWORD', ''),
      },
      options: {
        ssl: false,
      },
    },
  },
});

8. 部署

git add --all
git commit -m "update config"
git push heroku master

部署可能需要几分钟。最后,日志将显示您的项目的网址(例如https://mighty-taiga-80884.herokuapp.com)。您还可以使用命令行打开项目:

heroku open

如果看到“ Strati欢迎”页面,则说明您已在Heroku上正确设置,配置和部署了Strapi项目。您现在需要设置您的

前端

1.创建我们的Next.js应用

我们移至上级文件夹,因为我们不想混合stradi和前端文件,因此我们创建了应用程序

cd ..
yarn create next-app

2.路由

  • 我们创建一个文件pages/article/[id].js,该文件将成为文章页面:
import Head from "next/head";

export default function ArticlePage() {
  return (
    <div>
      <Head>
        <title>This is an article title</title>
      </Head>
      <main>
        This is an article body
      </main>

    </div>
  );
}
  • 我们将内容pages/index.js作为其主页清空,这将ArticleList在将来对我们有所帮助。
import styles from "../styles/Home.module.scss";

export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Our great blog</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        The article list
      </main>
    </div>
  );
}
  • 我们通过添加pages/404.js带有PageNotFound组件的来创建404自定义页面。
export default function PageNotFound() {
    return <div>oh oh...</div>
}

3.创建一些结构

  • modules在Next.js项目的根目录下创建一个文件夹
  • 创建一个modules/core包含两个子文件夹components和的模块services
  • 在内部modules/core/components创建Header.jsFooter.js文件,例如:
import Link from "next/link";

export default function Header() {
  return (
    <header>
      <Link href="/">
        <a>Our awesome blog</a>
      </Link>
    </header>
  );
}
export default function Footer() {
  return <footer>® Awesome friends company</footer>;
}
  • 消费您的组件 app.js
import "../styles/globals.scss";
import Header from "../modules/core/components/Header";
import Footer from "../modules/core/components/Footer";

function MyApp({ Component, pageProps }) {
  return (
    <div>
      <Header></Header>
      <div className="route">
        <Component {...pageProps} />
      </div>
      <Footer></Footer>
    </div>
  );
}

export default MyApp;

  • 删除该文件夹,routes/api因为我们的示例未使用微服务,因此该文件夹是完全静态的。
  • 安装SASS(可选)
    我们正在使用sass,因为我们希望能够重用颜色变量。
yarn add sass
  • 将所有.css文件更改为.scss(如果未添加sass,则省略)
  • 在global.scss旁边创建一个reset.scss文件,其中包含您喜欢的CSS reset。(如果未添加sass,请使用.css)
  • 清空global.scss的内容并导入reset.scss,如下所示:
@import 'reset'
  • variables.scss旁边创建一个文件,global.scss并定义您的颜色,断点或您需要在此处共享的任何变量。对于我们的情况,我从这里选择了一个随机调色板

variables.scss

$charcoal: #264653;
$persianGreen: #2A9D8F;
$orangeYellowCrayola: #E9C46A;
$sandyBrown: #F4A261;
$burntSienna: #E76F51;
  • 清空其中的内容,Home.module.scss使其像
.container {
  display: block;
}

.main {
  display: block;
}

您将来可以在这里为它设置样式。

资料撷取

在本地启动您的手鼓。为此,请转到安装stridi的文件夹,然后键入:

yarn develop
  • 登录到您的管理员帐户 http://localhost:1337/admin

创建article内容类型并添加以下字段:

  • 规范的(将是我们的永久链接或路径名)
  • 说明(长文本)
  • 标题(短文字)
  • 正文(富文本)

保存所有内容,然后在文本编辑器中打开trapi文件夹。

  • api/article/config使用以下内容创建一个schema.graphql.js :
const { sanitizeEntity } = require('strapi-utils');

module.exports = {
  query: `
    articleByCanonical(canonical: ID): Article
  `,
  resolver: {
    Query: {
      articleByCanonical: {
        resolverOf: 'Article.findOne',
        async resolver(_, { canonical }) {
          const entity = await strapi.services.article.findOne({ canonical });
          return sanitizeEntity(entity, { model: strapi.models.article });
        },
      },
    },
  },
};

并保存一切。

  • 现在,在您的前端项目上添加apollo客户端依赖项(记住要cd frontend dir在前端package.json中安装依赖项)
yarn add @apollo/client
  • 使用以下命令创建一个.env.local文件:
STRAPI_HOST="http://localhost:1337"
  • core/services/apolloClient.service.js在我们将导出我们的阿波罗客户端实例的内部创建服务。
import { ApolloClient, InMemoryCache } from '@apollo/client'

export default new ApolloClient({
    uri: `${process.env.STRAPI_HOST}/graphql`,
    cache: new InMemoryCache()
})
  • 与core一样,article使用componentsservices文件夹创建一个新模块。

创建ArticleListArticle内部组件article/components/ArticleList.jsarticle/components/Article.js下列要求:

export default function Article({ title, body }) {
  return <div>
    <h1>{title}</h1>
    <div>{body}</div>
  </div>;
}

import Link from "next/link";

export default function ArticleList({ articles }) {
  return articles.length ? (
    <ol>
      {articles.map((article) => (
        <li key={article.id}>
          <Link href={`article/${article.canonical}`}>
            <h2>{article.title}</h2>
          </Link>
          <p>{article.description}...</p>
        </li>
      ))}
    </ol>
  ) : (
    <div>There are no articles</div>
  );
}
  • 在中创建商品服务 article/services/article.service.js
import { gql } from "@apollo/client";
import apolloClient from "../../core/services/apolloClient.service";

export async function getAll() {
  return apolloClient
    .query({
      query: gql`
        {
          articles {
            canonical
            description
            id
            created_at
            title
          }
        }
      `,
    })
    .then((result) => result.data.articles);
}

export async function getByCanonical(canonical) {
  return apolloClient
    .query({
      query: gql`
        {
          articleByCanonical(canonical: "${canonical}") {
            title
            body
          }
        }
      `,
    })
    .then((result) => {
      console.log(result.data)
      return result.data.articleByCanonical;
    });
}
  • 最后,我们在路由内部添加获取逻辑,并使用以下组件:

pages/index.js

import Head from "next/head";
import ArticleList from "../modules/article/components/ArticleList";
import { getAll } from "../modules/article/services/article.service";

export default function HomePage({ articles }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Our great blog</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <ArticleList articles={articles}></ArticleList>
      </main>
    </div>
  );
}

export async function getStaticProps(context) {
  return {
    props: { articles: await getAll() },
  };
}

并改变 pages/article/[id].js

import marked from "marked";

import Article from "../../modules/article/components/Article";
import {
  getAll,
  getByCanonical,
} from "../../modules/article/services/article.service";
import Head from "next/head";

export default function ArticlePage({ article }) {
  return (
    <div>
      <Head>
        <title>{article.title}</title>
      </Head>
      <main>
        <Article {...article}></Article>
      </main>

    </div>
  );
}

export async function getStaticPaths() {
  const articles = await getAll();

  const paths = articles.map((article) => ({
    params: { id: article.canonical },
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const article = await getByCanonical(params.id);

  return { props: { article } };
}

添加样式

  • 您可以在组件旁边创建任何文件.module.scss,并且您的CSS类将映射到可以导入的对象,例如
// foo.module.scss
.container {
  display: block;
}

// foo.js
import styles from './foo.module.scss'

function Foo() {
  return <div className={styles.container}>My Foo styled component</div>
}

部署

  • 对于trapi部署,只需在终端中转到您的trapi项目,然后提交并推送所有内容:
git add --all
git commit -m "my changes"
git push heroku master
  • 对于前端:前端路径并推送您的更改。
  • package.json更改构建命令next build && next export。这将在/out文件夹中生成静态构建。这就是我们为网站服务所需要的。要在本地测试,只需运行npx serve out/
  • 然后创建一个github仓库添加你的遥控器
  • 然后转到vercel.com并导入您的github项目
  • 请记住在Vercel中添加您的STRAPI_HOST env变量以指向您的heroku数据库
  • 遵循向导,您的应用将被部署

更新

  • 创建一个网络钩子,将为您提供一个URL
  • 登录生产生产环境,然后在设置> webhooks中使用提供的网址创建一个新的webhook。
  • 现在,每次更新生产数据库时,都会重新构建和重新部署博客。

演示代码

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用Next.js和Strapi创建一个简单的博客

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论