nextJS 14 - sitemap, robot CICD

seonik kim·2024년 6월 7일

root에 script 폴더 생성 후 6개 파일 생성

  • robots.js
  • sitemap-common.js
  • sitemap-post.js // 업데이트 예정
  • sitemap-compress.js
  • sitemap.s
  • generate-sitemap.sh

  1. script/robots.js
const fs = require('fs');

const generatedRobotTxt = `
User-agent: *
Disallow: /admin*/
Disallow: /cgi-bin/
sitemap: https://fidaworldcup.com/sitemap.xml
`;

fs.writeFileSync('../src/app/robots.txt', generatedRobotTxt, 'utf8');
  1. script/sitemap-common.js
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const readdir = promisify(fs.readdir);

// 도메인 설정
const DOMAIN = '<DOMAIN>';

// 오늘 날짜 가져오기
const getDate = new Date().toISOString();

// 페이지 디렉토리 경로
const pagesDir = path.join(__dirname, '../src/app');

// Sitemap 생성 함수
async function generateSitemap() {
  try {
    // Sitemap XML 시작 부분
    let sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`;

    // 모든 페이지 경로 가져오기
    const pages = await getAllPages(pagesDir);

    // 각 페이지 경로에 대해 Sitemap에 추가
    for (const page of pages) {
      // 페이지 경로를 URL 형식으로 변환
      let url = page.replace(pagesDir, '').replace(/\\/g, '/');

      // Special case for home page
      if (url.includes('(home)')) {
        url = url.replace('(home)/page.tsx', '');
      } else {
        url = url.replace('/page.tsx', '');
      }

      // Construct the full URL
      url = `${DOMAIN}${url}`;

      // URL을 Sitemap에 추가
      sitemap += `
  <url>
    <loc>${url}</loc>
    <lastmod>${getDate}</lastmod>
  </url>`;
    }

    // Sitemap XML 끝 부분
    sitemap += `
</urlset>`;

    // Sitemap 파일 경로
    const sitemapPath = path.join(__dirname, '../public/sitemap/sitemap_index.xml');

    // Sitemap 파일 쓰기
    fs.writeFileSync(sitemapPath, sitemap, 'utf8');

    console.log('Sitemap 생성 완료!');
  } catch (error) {
    console.error('Error generating sitemap:', error);
  }
}

// 모든 페이지 경로를 가져오는 함수
async function getAllPages(dir) {
  const dirents = await readdir(dir, { withFileTypes: true });
  const files = await Promise.all(
    dirents.map(dirent => {
      const res = path.resolve(dir, dirent.name);
      return dirent.isDirectory() ? getAllPages(res) : res;
    }),
  );

  // 페이지 필터링: page.tsx로 끝나는 파일만 포함
  return Array.prototype.concat(...files).filter(file => {
    const fileName = path.basename(file);
    return fileName === 'page.tsx';
  });
}

// Sitemap 생성 함수 호출
generateSitemap();

3.script/sitemap-compress.js

const zlib = require('zlib');
// public/sitemap 디렉토리 내부에 sitemap들이 있으므로, 해당 폴더에서 실행합니다.
const dirs = ['../public/sitemap'];
const fs = require('fs');

// 경로에서 xml파일을 찾아 .gz파일로 압축. 같은 경로에 저장됩니다.
dirs.forEach(dir => {
  fs.readdirSync(dir).forEach(file => {
    if (file.endsWith('.xml') && file !== 'sitemap.xml') {
      // gzip
      const fileContents = fs.createReadStream(dir + '/' + file);
      const writeStream = fs.createWriteStream(dir + '/' + file + '.gz');
      const zip = zlib.createGzip();

      fileContents
        .pipe(zip)
        .on('error', err => console.error(err))
        .pipe(writeStream)
        .on('error', err => console.error(err));
    }
  });
});
  1. script/sitemap.js
const fs = require('fs').promises;
const globby = require('globby');
const prettier = require('prettier');

const getDate = new Date().toISOString();
const DOMAIN = '<DOMAIN>';

(async () => {
  const pages = await globby(['../public/sitemap/*.gz']);

  const sitemapIndex = pages
    .map(page => {
      const path = page.replace('../public/', '');
      return `
          <sitemap>
            <loc>${`${DOMAIN}/${path}`}</loc>
            <lastmod>${getDate}</lastmod>
          </sitemap>`;
    })
    .join('');

  const sitemap = `
    <?xml version="1.0" encoding="UTF-8"?>
    <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      ${sitemapIndex}
    </sitemapindex>
  `;

  // fs.promises.writeFile을 사용하여 파일을 작성합니다.
  await fs.writeFile('../src/app/sitemap.xml', sitemap.trim(), 'utf8');

  console.log('Sitemap 생성 완료!');
})();
  1. sitemap-post.js
추후 추가 예정
  1. script/generate-sitemap.sh
# generate-sitemap.sh

# 퍼블릭 폴더로 이동
cd public

# 기존에 있던 사이트맵 폴더를 제거하고 빈 디렉토리를 만듦
rm -rf sitemap
mkdir sitemap

# 스크립트 폴더로 이동해서 아래의 순서대로 실행
cd ..
cd script

# robots.txt 생성
node ./robots.js
echo "robots.txt 생성!"


# 정적 sitemap 생성
node ./sitemap-common.js
echo "정적 sitemap 생성!"

#동적 sitemap 생성
# echo "동적 sitemap 조회 및 생성중.."
# node ./sitemap-posts.js
# echo "동적 sitemap 생성 완료!"

# sitemap 압축 및 병합
echo "sitemap gzip 압축중"
node ./sitemap-compress.js
node ./sitemap.js
echo "sitemap 압축 완료"

# Google 서치콘솔에 sitemap 업데이트 핑 전송
# curl http://google.com/ping?sitemap=<DOMAIN>/sitemap.xml
# echo "Google에 sitemap 핑 전송"
  1. github CI/CD

yarn i
<사이에 추가>
yarn build

- name: Install dependencies
  run: |
   yarn install

- name: create robot.txt & sitemap.xml
  run: sh script/generate-sitemap.sh
  
- name: Build the project
  run: |
   yarn build 
profile
김선익

0개의 댓글