[SEO실강] 3강

youngseo·2022년 7월 17일
0

FireBase

목록 보기
8/9
post-thumbnail

Vercel 배포

  • netlify폴더와 구성파일은 삭제를 해줍니다.
  • 정적 호스팅만 할거라면 넷니파이처럼 사용하면 되지만 서버리스 함수를 도입할거라면 로컬에서 충분히 테스트가 되어야 하기 떄문에 아래 패키지를 설치해줘야합니다.

설치

$ npm i -D vercel

구성설정파일 세팅

vercel.json

{}
  • 루트경로에 설정파일을 만들어줍니다.
  • 넷니파이의 경우 서버내용을 만들기위해 netlify폴더 내 functions폴더 내 파일을 추가했습니다. vercel의 경우 api라는 폴더를 하나 만들어줍니다.

api > test.ts

export default async function (req, res) {
  res.status(200).json({
    name: '0seo'
  })
}

package.json

  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview",
    "vercel": "vercel dev"
  },
  • 기존에 "netlify": "netlify dev"라고 되어 있던 부분을 지우고 "vercel": "vercel dev"를 작성해줍니다.

npm run vercel

$ npm run vercel
  • vercel의 경우 netlify와는 다르게 로컬에서만 개발을 하더라도 계정을 연결을 해줘야합니다.
    • Set up and develop ~~ Y
    • Which scope should contain your project?
    • Found project ~ Link to it? Y

버셀의 내 계정에 아래와 같이 생겼는지 확인을 합니다.

http://localhost:3000로 접근하면 아래와 같이 뜹니다.

api > test.ts 타입지정

import { VercelRequest, VercelResponse } from '@vercel/node'

export default async function (req, res) {
  res.status(200).json({
    name: '0seo'
  })
}
  • req, res의 타입을 지정하기 위해서는 import { VercelRequest, VercelResponse } from '@vercel/node'를 가져와야합니다.

포트 가로채기

vite.config.ts

  server: {
    proxy: {
      '/api' : {target: 'http://localhost:2999'}
    }
  },

package.json

  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview",
    "vercel": "vercel dev --listen 2999" //✅
  },
  • vercel에서 로컬서버를 열때 생기는 문제를 해결하기 위해 proxy를 사용합니다
    • vite.js와 vercel모두 3000번
  • vercel이 동작하는 코드를 기본 3000에서 2999으로 바꾸고 3000은 vite.js가 사용을 하는 것입니다.
  • 넷니파이도 마찬가지었지만 자동으로 해주기때문에 신경쓸 필요가 없었을 뿐입니다.

store > workspace.ts

async function request(options: RequestOptions) {
  const { id = '', method, body } = options
  
  const res = await fetch('/api/workspaces', { //✅
    method: 'POST',
    body: JSON.stringify({
      id,
      method,
      data: body
    })
  })
  return res.json()
}

주소를 api/workspaces로 바꿔줍니다.

api > workspaces.ts

import axios from 'axios'
import { VercelRequest, VercelResponse } from '@vercel/node'

const { APIKEY, USERNAME } = process.env

export default async function handler(request: VercelRequest, response: VercelResponse) {
  const { id, method, data } = JSON.parse(request.body as string)
  const { data: returnValue } = await axios({
    url: `https://asia-northeast3-heropy-api.cloudfunctions.net/api/notion/workspaces/${id}`,
    method,
    headers: {
      'content-type': 'application/json',
      'apikey': APIKEY as string,
      'username': USERNAME as string
    },
    data
  })
  response
    .status(200)
    .json(returnValue)
}

.env 파일 작성

APIKEY=FcKdtJs202204
USERNAME=ParkYoungWoong

npm run dev

  • 넷니파이에서는 netlify cli를 설치하면 npm run netlify를 통해서 netlify dev가 동작했고 netlify cli가 호스팅서버와 서버를 같이 돌려줬습니다.
  • vercel의 경우 각각 따로 열어줘야합니다.
//hosting
npm run dev
//추가
npm run vercel

이렇게 터미널 두개를 통해 두개를 동시에 돌려야 3000번 서버가 2999서버를 가로채서 쓸 수가 있습니다.

concurrently

두개 명령을 동시에 돌리는 것은 불편하기 때문에 한번에 띄울 수 있도록 수정해보도록 하겠습니다.

$ npm i -D concurrently

package.json

"scripts": {
  "dev": "concurrently npm:watch-*", 
  "watch-dev": "vite",
  "watch-vercel": "vercel dev --listen 2999",
}

concurrently패키지가 watch가 붙어있는 dev와 vercel을 동시에 돌립니다. 꼭 watch가 아니라 원하는 이름으로 해도 괜찮습니다.

버셀 배포

현재의 저장소를 버셀에 바로 올릴 수도 있지만, 이런 경우 프로젝트가 날아가는 순간 날아가버리기 떄문에 원격저장소에 올린후 배포를 해보도록 하겠습니다.

$ rm -rf .git
$ git init
$ git add *
$ git commit -m ""
$ 원격저장소 연결
...
  • 배포가 다 된 후에는 현재의 vercel홈페이지에서 현재 프로젝트를 확인해봅니다.
    setting로 가서 Git - github를 연결해줍니다.
  • 프로젝트가 나오면 connect을 시킨 후 환경변수(setting에 environment variables)를 설정해줍니다.

리전 변경

  • 서버리수 함수 리전을 서울리전으로 변경할 수 있습니다. 따라서 넷니파이보다 빠릅니다.

배포

$ npm run vercel:depoly
  • 그냥 프로젝트에서 간단하게 띄어쓰기 등을 수정한 후 다시 git에 업로드를 해도 괜찮습니다. (자동배포)

2. SEO작업

  • 버셀의 경우에도 엣지함수가 도입은 되었지만 아직 레퍼런스가 많이 부족합니다. 따라서 일반 함수로 작업을 해보도록 하겠습니다.

api > edge.ts

api폴더 내에 edge.ts파일을 만들어줍니다.

import axios from 'axios'
import isbot from 'isbot'
import { VercelRequest, VercelResponse } from '@vercel/node' //1. 타입을 가져옵니다.

// Check .env file!
const { APIKEY, USERNAME, MODE } = process.env

export default async function handler(request: VercelRequest, response: VercelResponse) {
  const userAgent = request.headers['user-agent'] //2. ✅
  const id = (request.url as string).split('/').filter(p => p).reverse()[0].split('?')[0]

  let data = { 
    title: 'Heropy가 운영하는 노션', 
    content: '안녕하세요! 반갑습니다! Heropy가 운영하는 노션 클론 예제입니다!', 
    poster: 'https://heropy.blog/css/images/logo.png' 
  }

  if (isbot(userAgent) && id) {
    console.log('Bot!!')

    const res = await axios({
      url: `https://asia-northeast3-heropy-api.cloudfunctions.net/api/notion/workspaces/${id}`,
      method: 'GET',
      headers: {
        'content-type': 'application/json',
        'apikey': APIKEY as string,
        'username': USERNAME as string
      }
    })
    data = res.data
  }
  const { title, content, poster } = data

  response
    .setHeader('content-type', 'text/html')
    .status(200)
    .send(/* html */ `
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>Heropy's Notion</title>

          <meta property="og:type" content="website" />
          <meta property="og:site_name" content="Notion Clone!" />
          <meta property="og:title" content="${title}" />
          <meta property="og:description" content="${content}" />
          <meta property="og:image" content="${poster}" />
          <meta property="og:url" content="https://notion-vite-vue3-ts.vercel.app/workspaces/${id}" />

          <meta property="twitter:card" content="summary" />
          <meta property="twitter:site" content="Notion Clone!" />
          <meta property="twitter:title" content="${title}" />
          <meta property="twitter:description" content="${content}" />
          <meta property="twitter:image" content="${poster}" />
          <meta property="twitter:url" content="https://notion-vite-vue3-ts.vercel.app/workspaces/${id}" />

          <link rel="icon" href="https://heropy.blog/css/images/logo.png">
          <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css">
          <link rel="preconnect" href="https://fonts.googleapis.com">
          <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
          <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap" rel="stylesheet">
          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
          ${
            MODE === 'development' 
              ? '<script defer type="module" src="/src/main.ts"></script>'
              : '<script type="module" crossorigin src="/assets/index.js"></script><link rel="stylesheet" href="/assets/index.css">'
          }
        </head>
        <body>
          <div id="app"></div>
        </body>
      </html>`)
}

vercel.json

{
  "rewrites": [
    { "source": "/:path*", "destination": "/api/edge" }
  ]
}

배포

  • 깃허브에 업로드를 하면 자동으로 배포가 진행됩니다.

0개의 댓글