React

 

 

 

 

 

소스 : https://github.com/braverokmc79/react-next-practice

 

 

https://nextjs.org/

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://vercel.com/

 

 

 

 

 

 

 

 

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 이란

Vercel 은 Next.js 에서 제공하는 배포플랫폼으로 [빌드 + 배포 + 호스팅] 서비스를 제공한다.
Next.js 공식문서에서는 Vercel를 통한 Front Project 배포를 권장하고 있으며, github의 레파지토리를 통해 쉽게 배포 할 수 있다.

 

 

 

1️⃣ deploy 추가

Vercel 에서의 배포를 위해 pakage.json 에 deploy를 추가한다.

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

 

 

 

2️⃣ repository 등록

https://vercel.com/new 에서 github 계정으로 로그인 후 배포 할 repository를 등록하고 import project 를 클릭한다

 

 

 


 

 

 

3️⃣ Configure Project 설정

프로젝트 빌드를 위한 설정을 하는 단계이다.
BUILD COMMAND 에 pakage.json 에서 추가한 Build 명령어를 입력한다.
OUTPUT DIRECTORY 은 배포시 디렉토리의 경로이다. Vercel이 프로젝트가 출력되면 자동으로 디렉토리가 구성된다.
INSTALL COMMAND 는 빌드단계에서 package-lock.json 이 있으면 Vercel이 install 명령어를 실행하여 dependencies를 설치해준다.

환경변수가 필요하다면 Environment Variables에서 설정할 수 있고  Deploy 를  실행한다.

 

 

 

 


4️⃣ Deploy

배포를 성공하면 아래와 같이 나온다.

또한, 단순한 배포 외에도 Deployment Status를 확인하거나, Analytics 등 많은 기능을 이용할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

※ 참고문서

https://nextjs.org/docs/deployment#managed-nextjs-with-vercel

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

react

 

about author

PHRASE

Level 60  라이트

미련한 자는 당장 분노를 터뜨리지만, 슬기로운 자는 모욕을 당해도 참는다. -성경

댓글 ( 4)

댓글 남기기

작성