소스 : https://github.com/braverokmc79/react-next-practice
next 프로젝트 생성
npx create-next-app next-practice
Quick source viewer
https://chrome.google.com/webstore/detail/quick-source-viewer/cfmcghennfbpmhemnnfjhkdmnbidpanb?hl=ko
json 더미 데이터 사이트
https://jsonplaceholder.typicode.com/
next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: false, //swcMinify: false, images: { domains: ["via.placeholder.com"], path: '' } } module.exports = nextConfig
1.pages
1) _app.js
import Layout from '../components/Layout' import '../styles/globals.css' function MyApp({ Component, pageProps }) { return ( <Layout> <Component {...pageProps} /> </Layout> ) } export default MyApp
2)index.js
export default function Home({ posts }) { return ( <div> <h1>Welcome to My Home </h1> <ul> {posts.map(post => ( <li key={post.id}>{post.title}</li> ))} </ul> </div > ) } let URL = "https://jsonplaceholder.typicode.com/posts?_start=0&_end=10"; //URL = "http://localhost:8080/api/post"; //SSR : Server Side Rendering : 요청이 올 때 마다 해당하는 HTML 문서를 그때 그때 생성하여 반환한다. // export const getServerSideProps = async () => { // const posts = await fetch(URL).then(res => res.json()).then(data => data) // return { // props: { // posts // } // } // } export const getStaticProps = async () => { const posts = await fetch(URL).then(res => res.json()).then(data => data) return { props: { posts }, //처음 접속한 후 20초지난 시점부터 언제든지 접속이 일어나면 파일을 새롭게 생성 revalidate: 20 } }
3)photos.js
/* eslint-disable @next/next/no-img-element */ import React from 'react' import { Head } from 'next/head'; import HeadInfo from './../components/HeadInfo'; import Image from 'next/image'; import photosStyles from "../styles/Photos.module.css" import Link from 'next/link'; function photos({ photos }) { console.log("photos : ", photos); return ( <> <HeadInfo title="my Blog Pohtos" /> <div> <h1>Welcome to My photos </h1> <ul className={photosStyles.photos}> {photos.map(photo => ( <li key={photo.id}> <Link href={`/photos/${photo.id}`} > <a> <img src={photo.thumbnailUrl} width={100} height={100} alt={photo.title} /> <span>{photo.title}</span> </a> </Link> </li> ))} </ul> </div> </> ) } let URL = "https://jsonplaceholder.typicode.com/photos?_start=0&_end=10"; export const getStaticProps = async () => { const photos = await fetch(URL).then(res => res.json()).then(data => data); return { props: { photos }, revalidate: 20 } } export default photos;
4)pages/photos/[id]/index.js
import Link from 'next/link' import React from 'react' import { Image } from 'next/image'; import { useRouter } from 'next/router'; const index = ({ photo }) => { // eslint-disable-next-line react-hooks/rules-of-hooks const router = useRouter(); const id = router.query; console.log("router : ", router, id); console.log("id : ", id); const { title, url } = photo; return ( <div> <h2>{title}</h2> <img src={url} widht={500} height={500} /> <Link href="/photos" > <a>go back</a> </Link> </div> ) } export const getStaticProps = async (context) => { const { id } = context.params; const photo = await fetch(`https://jsonplaceholder.typicode.com/photos/${id}`).then(res => res.json()).then(data => data); return { props: { photo }, revalidate: 10 } } export const getStaticPaths = async () => { const photos = await fetch("https://jsonplaceholder.typicode.com/photos?_start=0&_end=10").then(res => res.json()).then(data => data); const ids = photos.map(photo => photo.id); const paths = ids.map(id => { return { params: { id: id.toString() } } }) return { paths, fallback: false } // return { // paths: [ // { // params: { id: '1' } // }, // { // params: { id: '2' } // }, // { // params: { id: '3' } // } // ], // fallback: false // } } export default index
2.components
1)HeadInfo.js
import Head from 'next/head' import React from 'react' const HeadInfo = ({ title, keyword, contents }) => { return ( <Head> <title>{title}</title> <meta keyword={keyword} /> <meta content={contents} /> </Head> ) } HeadInfo.defaultProps = { title: 'My Blog', keyword: 'Blog powered by Next js', content: 'practice next js' } export default HeadInfo
2)Nav.js
import Link from 'next/link' import React from 'react' import navStyles from '../styles/Nav.module.css' const Nav = () => { return ( <nav className={navStyles.nav}> <ul> <li> <Link href="/"> Home </Link> </li> <li> <Link href="/photos"> photos </Link> </li> </ul> </nav> ) } export default Nav
3)Layout.js
import Head from 'next/head' import React from 'react' import HeadInfo from './HeadInfo' import Nav from './Nav' const Layout = ({ children }) => { return ( <> <HeadInfo /> <Nav /> <div> {children} </div> </> ) } export default Layout
3.styles
1)Nav.module.css
.nav{ padding: 0.5rem 1rem; background: #2c82c9; } .nav ul{ display: flex; } .nav li{ margin-left: 1rem; color:#fff; }
2)Photos.module.css
.photos{ display: grid; grid-template-columns:repeat(4, 1fr) ; grid-gap: 1rem; } .photos li{ display: flex; flex-direction: column; }
■ vercel 배포
https://react-next-practice-ten.vercel.app/
Node
app.js
const express = require('express'); const cors = require('cors'); const app = express(); const PORT = 8080; const { posts } = require('./data.js') app.use(cors()); app.get('/api/post', (req, res) => { console.log("cors no"); res.json(posts); }) app.listen(PORT, () => console.log(`server running on ${PORT}`));
express , cors , nodemon 설치
$ yarn add express cors
$ npm install --save-dev nodemon
scripts "backend": "nodemon app.js", nodemon 설정
package.json
{ "dependencies": { "cors": "^2.8.5", "express": "^4.18.1" }, "devDependencies": { "nodemon": "^2.0.20" }, "scripts": { "start": "node app.js", "backend": "nodemon app.js", "test": "echo \"Error: no test specified\" && exit 1" } }
[Next.js] Vercel로 프론트 배포하기
2022. 1. 8. 20:56
Vercel 은 Next.js 에서 제공하는 배포플랫폼으로 [빌드 + 배포 + 호스팅] 서비스를 제공한다.
Next.js 공식문서에서는 Vercel를 통한 Front Project 배포를 권장하고 있으며, github의 레파지토리를 통해 쉽게 배포 할 수 있다.
Vercel 에서의 배포를 위해 pakage.json 에 deploy를 추가한다.
{ "scripts": { "dev": "next dev", "build": "next build", "start": "next start" } }
https://vercel.com/new 에서 github 계정으로 로그인 후 배포 할 repository를 등록하고 import project 를 클릭한다
프로젝트 빌드를 위한 설정을 하는 단계이다.
BUILD COMMAND 에 pakage.json 에서 추가한 Build 명령어를 입력한다.
OUTPUT DIRECTORY 은 배포시 디렉토리의 경로이다. Vercel이 프로젝트가 출력되면 자동으로 디렉토리가 구성된다.
INSTALL COMMAND 는 빌드단계에서 package-lock.json 이 있으면 Vercel이 install 명령어를 실행하여 dependencies를 설치해준다.
환경변수가 필요하다면 Environment Variables에서 설정할 수 있고 Deploy 를 실행한다.
배포를 성공하면 아래와 같이 나온다.
또한, 단순한 배포 외에도 Deployment Status를 확인하거나, Analytics 등 많은 기능을 이용할 수 있다.
※ 참고문서
https://nextjs.org/docs/deployment#managed-nextjs-with-vercel
댓글 ( 4)
댓글 남기기