Strapi의 NextJS 블로그 | Heroku 및 Vercel에 배포

Strapi는 무료 오픈소스 CMS입니다.이것은 우리가 사용하는 모든 언어를 선택할 수 있도록 API를 주었다.
본 강좌에서, 우리는 NextJS를 사용할 것이다. 왜냐하면 SEO, 이미지 최적화, 미리 렌더링된 데이터를 얻는 기능은 모두 이미 만들어진 것이기 때문이다.만약 네가 이 용어들을 얻지 못했다면 걱정하지 마라. 나는 아래에서 상세하게 설명할 것이다.
우리는 간단한 블로그를 만들 것이다. 당신은 서로 다른 유형의 다른 글을 발표할 수도 있고, 사용자가 사이트의 글을 발표할 수도 있다.마지막으로, 우리는 Heroku에strapi 프로그램을 무료로 배치하고vercel에NextJS 메인 사이트를 무료로 배치할 것이다.
이것은 우리가 이 강좌에서 개발할 마지막 블로그다.
링크: https://my-nextjs-blog-phi.vercel.app/
최종 코드: https://github.com/DibasDauliya/nextJS-blog-with-stapi-api

스텔라피부터 시작하자.


터미널에서 이 명령을 실행합니다.
$ npx create-strapi-app strapi --quickstart
npx이 아닌 npm을 사용하는 것을 권장합니다. npm은 패키지를 설치하고 npx은 패키지만 실행하기 때문입니다.너는 this free code camp’s blog에서 그것에 대한 더 많은 정보를 읽을 수 있다.
우리는 SQLite 데이터베이스를 사용하고 싶기 때문에 명령 끝에 --quickstart을 추가했다.MongoDB, SQL 또는 Postgres을 주 데이터베이스로 사용할 수도 있습니다.위 명령의strapi는 프로젝트를 저장하고 싶은 폴더 이름입니다.
위 명령을 실행하면 URL http://localhost:1337/admin이 표시됩니다.
이름, 이메일, 비밀번호를 등록하고 Strapi 관리 패널에 접근할 수 있도록 열 수 있습니다.
작성자의 게시물과 연결할 수 있는 사용자를 만듭니다.
컬렉션 유형의 사용자 를 클릭한 다음 + 새 사용자 추가 를 클릭합니다.세부내용을 작성하여 저장합니다.
다음에'내용 유형 생성기'에 들어가서'+새로운 집합 유형 만들기'를 누르면 그림과 같다.

그런 다음 디스플레이 이름을 Post(strapi는 Posts로 변환)라고 입력합니다.그런 다음 필드 추가 옵션을 클릭합니다.세 개의 텍스트 필드, 하나의 풍부한 텍스트 필드, UID를 선택한 다음 각각 제목, 분류, 설명, 내용, slug로 명명합니다.풍부한 텍스트는 가격 인하를 쓸 수 있도록 해 줍니다.NextJS의 react-markdownnpm 패키지를 사용해서 추출할 것입니다.
UID는 slug 및 URL에 유용합니다.UID의 추가 필드의 드롭다운 목록에서 제목을 선택해야 합니다.제목의 공백이 자동으로 제거되고 대시로 연결됩니다.
그런 다음 관계 필드를 선택하고 드롭다운 목록에서 사용자(사용 권한)를 선택합니다.그리고 여섯 가지 옵션 중 네 번째 옵션을 선택하십시오. 즉, 사용자가 많은 게시물을 가지고 있으며, 이를 작가로 명명합니다.
그런 다음 finish 를 클릭하고 저장(R.H.S.의 녹색 버튼)을 클릭합니다.이것은 오류가 발생했거나 비슷한 일이 발생했다고 말할 수 있습니다. 저장 단추를 눌렀는지 확인하면, 오류가 발생하면 페이지를 새로 고치십시오. strapi 로고 아래의 집합 형식에서 '댓글' 을 보아야 합니다.
예, 지금 댓글을 좀 추가합시다.'새 댓글 추가'를 클릭하세요.
필드를 작성하고 오른쪽 드롭다운 목록에서 그림과 같이 작성자를 선택합니다.

이제 저장 및 게시를 클릭합니다.
"/posts"경로에서 이 게시물을 방문할 수 있지만, 403에서 금지된 오류가 표시됩니다. 허가를 받아야 하기 때문입니다.
그러면 설정에 들어가서 '사용자와 권한 플러그인' 아래의 '역할' 으로 들어갑니다.공용을 클릭하고 사용 권한 아래의 응용 프로그램 섹션으로 이동합니다.그런 다음 찾기, 하나 찾기 및 만들기를 선택하고 저장합니다.

NextJS를 사용한 데이터 활용


터미널에서 이 명령을 실행합니다.
$ npx create-next-app my-blog
이 명령을 실행한 후 내 블로그 폴더로 이동하여 기본 설정 코드 편집기에서 항목을 열고 npm run dev 명령을 실행하고 이 링크(http://localhost:3000/)로 이동하여 사이트를 보십시오.
나는 기본 코드를 이렇게 편집했다. (단지 일부 텍스트를 바꾸고 기본 스타일을 추가했을 뿐이다.)😀

현재, 사전 렌더링을 위해 getStaticProps 함수를 사용합니다.서버가 구축되는 동안 Google의 모든 게시물을 구축하고 사용자에게 신속하게 제공합니다.더 많은 기본 기능: 데이터 취득 | 다음 단계.js(nextjs.org).
아래의 코드는 당신을 더욱 분명하게 할 수 있습니다.getStraticProps이 완료되면 사이트를 새로 고치거나 서버를 다시 실행해야 합니다.
export default function Home(props) {
  console.log(props.data)
  console.log('everyone can get me')

  return (
{/* ... */}
    )
}

export async function getStaticProps() {
  console.log("I'm executed by server. Browser can't get me. 😋")

  return {
    props: { data: 'Data returned by getStaticProps' }
  }
}

이 기능은 페이지 내 파일 폴더에서만 실행됩니다.
이러한 상황에서 우리는 증량 정적 재생(ISR)을 이용하여 geStaticProps 함수가 되돌아올 때 초 단위의 값의revialte 키를 추가합니다. 이것은 지정된 시간 간격 내에 우리가 필요로 하는 페이지를 재구성하는 데 도움이 되고 사이트 전체를 재구성할 필요가 없기 때문입니다.
설령 우리가 개발할 때와 리셋 후 geyStaticProps의revialte 속성을 사용하지 않더라도, 리셋 내용은 생산 과정에서 같지 않다.ISR을 사용하지 않는 경우, 업데이트를 볼 때마다 저희 사이트를 재구성해야 합니다.
그래서 루트 경로에 '.env.local' 파일을 만들고 strapi URL을 추가합니다.NEXT_PUBLIC_STRAPI_API_URL=http://localhost:1337이제 카테고리 텍스트 필드를 사용하여 게시물을 필터링하고 다양한 섹션에 데이터를 채웁니다.
export default function Home(props) {
  const { htmlCatRes, jsCatRes } = props

  return (
    <div className={styles.container}>
<Head>
        <title>My Blog</title>
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Welcome to My Blog!</h1>

       {/* ... */}

        {/* category one */}
        <div className={styles.catCard}>
          <h2>HTML and CSS Category</h2>

          {htmlCatRes.map(({ title, description, id, slug }) => (
            <a href={`/${slug}`} className={styles.card} key={id}>
              <h2>{title}</h2>
              <p>{description}</p>
            </a>
          ))}
        </div>

        {/* category two */}
        <div className={styles.catCard>...  
</main>

      <footer className={styles.footer}>My Blog</footer>
    </div>
  )
}

export async function getStaticProps() {
  const htmlCat = await fetch(
    `${process.env.NEXT_PUBLIC_STRAPI_API_URL}/posts?category=html-css`
  )
  const htmlCatRes = await htmlCat.json()

  const jsCat = await fetch(
    `${process.env.NEXT_PUBLIC_STRAPI_API_URL}/posts?category=javascript`
  )
  const jsCatRes = await jsCat.json()

  return {
    props: { htmlCatRes, jsCatRes },
    revalidate: 10 //will regenerate page when request comes at every 10      seconds
  }
}



우리는 넥스트JS의 Head 구성 요소를 사용하여 특정 페이지에 원 제목, 설명, 이미지, 오픈 아이콘을 사용하여 검색엔진의 최적화를 개선할 수 있습니다.
현재 같은 페이지 폴더 아래에 동적 페이지 [post].js을 만듭니다. 여기서 저희 게시물에 대한 더 많은 정보를 얻을 수 있습니다.[post].js의 단어post는 우리post의 slug로 대체됩니다.
이번에는 데이터를 얻기 위해 getStaticPaths 함수를 사용해야 한다. 이것은 동적 루트이기 때문에nextJS는 우리가 만든 [post][post].js이 어떤 단어로 바뀔지 모른다.우리는 반드시 사전에 넥스트JS에 이 단어들이 [post]을 대체할 것이라고 알려야 한다.따라서 구축하는 동안 가능한 모든 페이지를 사용할 수 있습니다.
가격 인하 데이터를 html로 해석하려면 react-markdownnpm 패키지를 설치합니다.
$ npm i react-markdown
현재, 우리는 링크의 href에서 전달된 slug를 가져오고, 이를 사용하여 게시물을 필터하고, 특정한 slug의 데이터를 가져옵니다.
export default function Post({ finalData }) {
  const { title, author, category, content, created_at } = finalData
  return (
    <>
      <Head>
        <title>{title}</title>
      </Head>

      <style>
        {` ...
          `}
      </style>

      <div className='container'>
        <article className='flow article'>
          <header className='header'>
            <h1>{title}</h1>
            <div className='author'>
              <span>By {author?.username}</span>
              <span>{new Date(created_at).toLocaleDateString()}</span>
              <span>{category}</span>
            </div>
          </header>
          <main className='flow-sm'>
            <ReactMarkdown>{content}</ReactMarkdown>
          </main>
        </article>
      </div>
    </>
  )
}

export async function getStaticProps({ params }) {
  const { post } = params

  const data = await fetch(
    `${process.env.NEXT_PUBLIC_STRAPI_API_URL}/posts?slug=${post}`
  )
  const resData = await data.json()

  const finalData = resData[0]

  return {
    props: { finalData },
    revalidate: 10 //will regenerate page when request comes at every 10 seconds

  }
}

export async function getStaticPaths() {
  const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_API_URL}/posts`)
  const posts = await res.json()

  const paths = posts?.map(({ slug }) => ({
    params: { post: slug }
  }))

  return {
    paths,
    fallback: 'blocking'
  }
}

웹 사이트에서 게시물 만들기


페이지 폴더에 create.js이라는 새 페이지를 만들고 홈 링크의 /create 속성 값에 href을 추가합니다.
그리고 제어된 입력 필드가 있는 간단한 폼을 만듭니다.만약 값이react 상태로 구동된다면, 우리는 입력 필드를 제어 구성 요소라고 할 수 있습니다.
이후, 나는 strapi API를 가져와서, 그것으로 우리의 내용을 발표했다.
export default function Create() {
  const [formData, setFormData] = useState({
    title: '',
    description: '',
    content: '',
    category: 'html-css',
    slug: ''
  })
  const [isLoading, setLoading] = useState(false)

  async function handleSubmit(e) {
    e.preventDefault()

    setLoading(true)

    const add = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_API_URL}/posts`, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(formData)
    })

    const addRes = await add.json()

    console.log(addRes)
    setFormData({
      title: '',
      description: '',
      content: '',
      category: 'html-css',
      slug: ''
    })

    setLoading(false)
  }

  function handleChange(e) {
    const name = e.target.name
    setFormData((prev) => {
      return { ...prev, [name]: e.target.value }
    })
  }
  return (
    <>
      <Head>
        <title>Create post</title>
      </Head>

      <style jsx>
        {` ...
        `}
      </style>

      <main className='container'>
        <Link href='/'>
          <a>
            <h1>Home</h1>
          </a>
        </Link>
        <h1>Create Post</h1>
        <form>
          <div className='form-group'>
            <label htmlFor='title'>Title</label>
            <input
              type='text'
              name='title'
              id='title'
              required
              placeholder='Enter title'
              value={formData.title}
              onChange={(e) => handleChange(e)}
            />
          </div>
          <div className='form-group'>
            <label htmlFor='category'>Choose category</label>
            <select
              name='category'
              id='category'
              onChange={(e) => handleChange(e)}
            >
              <option value='html-css'>HTML and CSS</option>
              <option value='javascript'>Javascript </option>
            </select>
          </div>
          <div className='form-group'>
            <label htmlFor='slug'>Slug</label>
            <input
              type='text'
              name='slug'
              id='slug'
              onChange={(e) => handleChange(e)}
              value={formData.slug}
              placeholder='Enter a slug'
            />
          </div>
          <div className='form-group'>
            <label htmlFor='description'>Description</label>
            <input
              type='text'
              name='description'
              id='description'
              required
              placeholder='Enter description'
              value={formData.description}
              onChange={(e) => handleChange(e)}
            />
          </div>
          <div className='form-group'>
            <label htmlFor='content'>Content (Markdown is supported)</label>
            <textarea
              rows={5}
              type='text'
              name='content'
              id='content'
              required
              placeholder='Enter content'
              value={formData.content}
              onChange={(e) => handleChange(e)}
            ></textarea>
          </div>
          <div className='form-group'>
            <button onClick={(e) => handleSubmit(e)}>
              {isLoading ? 'Loading...' : 'Submit'}
            </button>
          </div>
        </form>
      </main>
    </>
  )
}

그렇습니다.😀

배포


Heroku에 Strapi 응용 프로그램 배포


heroku 계정을 만들지 않았으면 this link부터 만들 수 있습니다.그것은 취미 항목에 대해 무료이며 신용카드에 대한 상세한 정보를 요구하지 않는다.
그런 다음 https://dashboard.heroku.com/apps으로 이동하여 R.H.S.의 [새로 만들기] 버튼을 클릭한 다음 [새 응용 프로그램 만들기]를 클릭합니다.응용 프로그램의 이름을 기입하면 배치 부분으로 안내합니다.
그런 다음 개요 탭에 들어가서 플러그 인 구성을 클릭하고 Heroku Postgres를 검색하여 프로젝트에 추가합니다.
현재 코드 편집기에서strapi 프로젝트를 열고 pgpg-connection-stringnpm 패키지를 설치합니다.
npm i pg pg-connection-string
그런 다음 구성에 환경 폴더를 만들고 환경에 생산 폴더를 만듭니다.운영 폴더에 database.jsserver.js이라는 두 개의 파일을 생성합니다.database.js
const { parse } = require("pg-connection-string");

module.exports = ({ env }) => {
  const { host, port, database, user, password } = parse(env("DATABASE_URL"));

  return {
    defaultConnection: "default",
    connections: {
      default: {
        connector: "bookshelf",
        settings: {
          client: "postgres",
          host,
          port,
          database,
          username: user,
          password,
          ssl: { rejectUnauthorized: false },
        },
        options: {
          ssl: false,
        },
      },
    },
  };
};
server.js
module.exports = ({ env }) => ({
  url: env("HEROKU_URL"),
});
Heroku는 다양한 응용 프로그램 배치 옵션을 제공합니다.이 자습서에서는 Heroku CLI 메소드를 사용합니다.너는 download Heroku CLI달러를 지불해야 한다.
설치 후 시스템을 다시 시작해야 할 수도 있고 터미널에서 이 명령을 실행해서 검사할 수도 있습니다.
$ heroku --version
설치가 끝난 후 터미널을 열고 우리가 구축한strapi 프로젝트를 찾으며heroku에 로그인합니다.
$ heroku login
그리고 CTRL + C을 누르면 종료하고git 저장소를 만듭니다.
$ git init
$ heroku git:remote -a your-app-name-in-heroku
이제 코드를 커밋하여 Heroku 주 분기로 밀어넣습니다.
$ git add .
$ git commit -m "first commit"
$ git push heroku main
이것은 몇 분 정도 걸릴 수 있으며, 완성되면 배치된 URL을 보여 줍니다.
heroku 계기판의 설정 옵션 카드에 들어가서 "설정 변수 보이기"를 누르십시오.키로 HEROKU URL을 추가하고 값을 입력합니다.그런 다음 키로 NODE ENV를, 값으로 production을 추가합니다.
그런 다음 URL을 열고/admin 경로로 이동하여 대시보드에 액세스합니다.
그런 다음 데이터를 추가하고 로컬 호스트 URL을 바꿉니다.환경배포된 URL이 있는 nextJS 로컬 파일입니다.
또한 사용자 및 권한 플러그 인의 역할 섹션에서 게시물의 찾기, 찾기, 만들기를 볼 수 있는지 확인합니다.
주: 보안상의 이유로 Strapi는 생산 과정에서 '내용 형식 생성기' 플러그인을 취소했습니다.새로운 내용 형식을 추가하거나 업데이트하려면 로컬에서 설정하고 Heroku로 밀어넣어야 합니다.

Vercel에 nextJS 응용 프로그램을 배치합니다.


NextJS 응용 프로그램은 nodeJS를 지원하는 호스트를 사용하여 배치할 수 있지만, 이 강좌에서는 취미 항목에 대해서도 무료이며, Vercel에서 제작한 NextJS 맞춤형 응용 프로그램이기 때문에 Vercel에서 배치할 것입니다.등록하지 않은 경우 this link을 통해 등록할 수 있습니다.
그 다음에 우리 프로젝트를github에 업로드합시다.github에 새 프로젝트를 만들고 터미널을 열고nextJS 프로그램을 찾은 다음 명령을 실행합니다.
$ git add .
$ git commit -m “first commit”
$ git remote add origin your-url
$ git push origin main
gitHub에 업로드한 후 this link을 통해 Vercel로 돌아갑니다.
그리고 R.H.S의 '새 항목' 단추를 누르고vercel과github를 연결해서github에서 항목을 선택하십시오
"NEXT PUBLIC STRAPI API URL"이라는 환경 변수를 추가하고 이 값이 heroku에서 제공하는 URL인지 확인합니다.
그리고 deploy를 누르면 경축이 있는 실시간 URL을 줍니다.🎉
감사합니다.😊

좋은 웹페이지 즐겨찾기