diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 06e12ef6d..2da982a90 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -10,15 +10,38 @@ jobs: runs-on: ubuntu-latest steps: - - name: SSH Remote Commands - uses: appleboy/ssh-action@v1.0.0 + - name: Setup Node.js environment + uses: actions/setup-node@v3.8.0 + + - name: Checkout + uses: actions/checkout@v3 + + - name: Log in to the Container Registry + uses: docker/login-action@v2.2.0 + with: + registry: ghcr.io + username: ${{github.actor}} + password: ${{secrets.GITHUB_TOKEN}} + + - name: Create .env file + run: | + echo "NEXT_PUBLIC_KAKAO_MAP_API_KEY=${{secrets.KAKAO_MAP_API_KEY}}" > .env.local + - name: Build and push Docker images + uses: docker/build-push-action@v4.1.1 + with: + context: '.' + push: true + tags: | + ghcr.io/wafflestudio/csereal_nextjs_image:latest + ghcr.io/wafflestudio/csereal_nextjs_image:${{github.sha}} + - name: executing remote ssh commands using password + uses: appleboy/ssh-action@v1.0.3 with: - host: ${{secrets.SSH_HOST}} - username: ${{secrets.SSH_USER}} - key: ${{secrets.SSH_KEY}} + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_KEY }} script: | - cd ~/csereal-web - git pull - npm i - npm run build - pm2 restart csereal_front + docker stop csereal_nextjs_image + docker rm csereal_nextjs_image + docker pull ghcr.io/wafflestudio/csereal_nextjs_image:latest + docker run -d -p 3000:3000 --name csereal_nextjs_image ghcr.io/wafflestudio/csereal_nextjs_image diff --git a/Dockerfile b/Dockerfile index 90e3be0aa..410b22fec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ RUN \ if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ elif [ -f package-lock.json ]; then npm ci; \ - elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ else echo "Lockfile not found." && exit 1; \ fi @@ -25,12 +25,14 @@ COPY . . # Next.js collects completely anonymous telemetry data about general usage. # Learn more here: https://nextjs.org/telemetry # Uncomment the following line in case you want to disable telemetry during the build. -ENV NEXT_TELEMETRY_DISABLED 1 - -# RUN yarn build +# ENV NEXT_TELEMETRY_DISABLED 1 -# If using npm comment out above and use below instead -RUN npm run build +RUN \ + if [ -f yarn.lock ]; then yarn run build; \ + elif [ -f package-lock.json ]; then npm run build; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ + else echo "Lockfile not found." && exit 1; \ + fi # Production image, copy all the files and run next FROM base AS runner @@ -40,24 +42,97 @@ ENV NODE_ENV production # Uncomment the following line in case you want to disable telemetry during runtime. ENV NEXT_TELEMETRY_DISABLED 1 -RUN addgroup --system --gid 1001 yeolyi1310 -RUN adduser --system --uid 1001 yeolyi1310 - -USER yeolyi1310 +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs COPY --from=builder /app/public ./public +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs EXPOSE 3000 ENV PORT 3000 -ENV HOSTNAME localhost +# set hostname to localhost +ENV HOSTNAME "0.0.0.0" + +# 시간대 설정 ENV TZ Asia/Seoul ENV LANG ko_KR.UTF-8 ENV TIME ko_KR.UTF-8 +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output CMD ["node", "server.js"] + +# FROM node:18-alpine AS base + +# # Install dependencies only when needed +# FROM base AS deps +# # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +# RUN apk add --no-cache libc6-compat +# WORKDIR /app + +# # Install dependencies based on the preferred package manager +# COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ +# RUN \ +# if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ +# elif [ -f package-lock.json ]; then npm ci; \ +# elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ +# else echo "Lockfile not found." && exit 1; \ +# fi + + +# # Rebuild the source code only when needed +# FROM base AS builder +# WORKDIR /app +# COPY --from=deps /app/node_modules ./node_modules +# COPY . . + +# # Next.js collects completely anonymous telemetry data about general usage. +# # Learn more here: https://nextjs.org/telemetry +# # Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED 1 + +# # RUN yarn build + +# # If using npm comment out above and use below instead +# RUN npm run build + +# # Production image, copy all the files and run next +# FROM base AS runner +# WORKDIR /app + +# ENV NODE_ENV production +# # Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED 1 + +# RUN addgroup --system --gid 1001 yeolyi1310 +# RUN adduser --system --uid 1001 yeolyi1310 + +# USER yeolyi1310 + +# COPY --from=builder /app/public ./public + +# # Automatically leverage output traces to reduce image size +# # https://nextjs.org/docs/advanced-features/output-file-tracing +# COPY --from=builder /app/.next/standalone ./ +# COPY --from=builder /app/.next/static ./.next/static + +# EXPOSE 3000 + +# ENV PORT 3000 +# ENV HOSTNAME localhost +# ENV TZ Asia/Seoul +# ENV LANG ko_KR.UTF-8 +# ENV TIME ko_KR.UTF-8 + +# CMD ["node", "server.js"] diff --git a/app/[locale]/community/news/create/page.tsx b/app/[locale]/community/news/create/page.tsx index 9d037ff77..9d6de9336 100644 --- a/app/[locale]/community/news/create/page.tsx +++ b/app/[locale]/community/news/create/page.tsx @@ -1,8 +1,7 @@ 'use client'; -import { useRouter } from 'next/navigation'; - import { revalidateNewsTag } from '@/actions/newsActions'; +import { useRouter } from '@/navigation'; import { postNews } from '@/apis/news'; diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx index 8e49038a4..0054ad47a 100644 --- a/app/[locale]/layout.tsx +++ b/app/[locale]/layout.tsx @@ -1,5 +1,6 @@ import { notFound } from 'next/navigation'; import { NextIntlClientProvider } from 'next-intl'; +import { unstable_setRequestLocale } from 'next-intl/server'; import { ReactNode } from 'react'; import { Toaster } from 'react-hot-toast'; @@ -31,6 +32,9 @@ export default async function RootLayout({ children: React.ReactNode; params: { locale: string }; }) { + // https://next-intl-docs.vercel.app/docs/getting-started/app-router#static-rendering + unstable_setRequestLocale(params.locale); + return ( diff --git a/components/editor/common/SunEditorWrapper.tsx b/components/editor/common/SunEditorWrapper.tsx index 2af8913fa..74b0d9b0f 100644 --- a/components/editor/common/SunEditorWrapper.tsx +++ b/components/editor/common/SunEditorWrapper.tsx @@ -1,10 +1,13 @@ 'use client'; -import { MutableRefObject, Suspense, lazy } from 'react'; +import { MutableRefObject, lazy } from 'react'; import { ko } from 'suneditor/src/lang/'; import SunEditorCore from 'suneditor/src/lib/core'; import plugins from 'suneditor/src/plugins'; +// TODO +// 정말 왜그러는지 모르겠는데 lazy + typeof window 조합으로만 빌드가 됨 +// 건들지 말..것.. const SunEditor = lazy(() => import('suneditor-react')); import './suneditor.css'; @@ -18,7 +21,7 @@ export default function SunEditorWrapper({ initialContent?: string; }) { return ( - }> + typeof window !== 'undefined' && ( (editorRef.current = x)} setDefaultStyle={`padding: 1rem;`} @@ -39,25 +42,26 @@ export default function SunEditorWrapper({ // imageUploadUrl: `${BASE_URL}/file/upload`, }} /> - + ) ); } -const SunEditorFallback = () => { - return ( -
-
-
-
-
-
-
-
-
-
-
- ); -}; +// Suspense 쓰도록 고칠 때까지 삭제 +// const SunEditorFallback = () => { +// return ( +//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+// ); +// }; // https://github.com/JiHong88/SunEditor/issues/199 export const isContentEmpty = (editor: SunEditorCore) => { diff --git a/components/layout/header/Header.tsx b/components/layout/header/Header.tsx index 07d846760..454a9dbe4 100644 --- a/components/layout/header/Header.tsx +++ b/components/layout/header/Header.tsx @@ -2,7 +2,6 @@ import { useTranslations } from 'next-intl'; - import { BASE_URL } from '@/apis'; import { useSessionContext } from '@/contexts/SessionContext'; import { Link } from '@/navigation'; diff --git a/next.config.mjs b/next.config.mjs index 223c069c2..368427e2f 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -5,6 +5,14 @@ const withNextIntl = createNextIntlPlugin(); /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, + output: 'standalone', + + // TODO: 아래 옵션 없이 빌드 + eslint: { + // Warning: This allows production builds to successfully complete even if + // your project has ESLint errors. + ignoreDuringBuilds: true, + }, webpack(config) { // Grab the existing rule that handles SVG imports