diff --git a/Dockerfile.admin b/Dockerfile.admin index 805813fe..b7255f1d 100644 --- a/Dockerfile.admin +++ b/Dockerfile.admin @@ -1,4 +1,4 @@ -FROM node:16 AS builder +FROM node:18-alpine AS builder # set working directory WORKDIR /app # install app dependencies @@ -8,8 +8,9 @@ COPY package.json ./ COPY yarn.lock ./ # Installs all node packages # RUN npm ci -RUN npm install yarn --global --force -RUN yarn install --immutable --immutable-cache --check-cache +RUN yarn set version 3.3.0 +RUN yarn install +# --immutable --immutable-cache --check-cache # Copies everything over to Docker environment diff --git a/Dockerfile.ticket b/Dockerfile.ticket index f8208a24..449bb478 100644 --- a/Dockerfile.ticket +++ b/Dockerfile.ticket @@ -1,4 +1,4 @@ -FROM node:16-alpine AS builder +FROM node:18-alpine AS builder # set working directory WORKDIR /app # install app dependencies @@ -8,8 +8,7 @@ COPY package.json ./ COPY yarn.lock ./ # Installs all node packages # RUN npm ci -RUN npm install yarn --global --force -RUN yarn install --immutable --immutable-cache --check-cache +RUN yarn set version 3.3.0 # Copies everything over to Docker environment @@ -35,4 +34,4 @@ RUN rm -rf apps/ticket/.next/cache # COPY --from=builder /app/build /usr/share/nginx/html/ # Containers run nginx with global directives and daemon off EXPOSE 3000 -CMD ["yarn", "ticket:start"] +CMD ["yarn", "ticket:start"] \ No newline at end of file diff --git a/README.md b/README.md index 10c07ef1..e6325461 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ yarn admin - [프론트엔드 모노레포 구축 삽질기 (3) - CICD 배포, Docker, Github Actions](https://9yujin.tistory.com/102?category=1013884) - [서버 사이드 렌더링(SSR)과 cookie 로그인 정보 다루기](https://www.9yujin.site/devlog/frontend/ssr-230122) - [선언적인 코드 작성하기](https://9yujin.tistory.com/109) - +-[웹 성능 최적화](https://9yujin.tistory.com/116)

diff --git a/apps/admin/index.html b/apps/admin/index.html index e0d535b7..3246b9d1 100644 --- a/apps/admin/index.html +++ b/apps/admin/index.html @@ -6,10 +6,17 @@ + + 두둥! - 어드민 diff --git a/apps/admin/src/components/shared/overlay/GlobalOverlay.tsx b/apps/admin/src/components/shared/overlay/GlobalOverlay.tsx index 8c926622..27984228 100644 --- a/apps/admin/src/components/shared/overlay/GlobalOverlay.tsx +++ b/apps/admin/src/components/shared/overlay/GlobalOverlay.tsx @@ -1,8 +1,8 @@ import { Modal } from '@dudoong/ui'; import useGlobalOverlay from '@lib/hooks/useGlobalOverlay'; import { overlayState } from '@store/globalOverlay'; -import { ReactNode } from 'react'; import { useRecoilValue } from 'recoil'; + import Approve from './content/Approve'; import DeleteEvent from './content/DeleteEvent'; import Invitation from './content/Invitation'; diff --git a/apps/ticket/next.config.js b/apps/ticket/next.config.js index 298e103e..3f19e3ed 100644 --- a/apps/ticket/next.config.js +++ b/apps/ticket/next.config.js @@ -2,42 +2,49 @@ // eslint-disable-next-line no-undef const withInterceptStdout = require('next-intercept-stdout'); +const withBundleAnalyzer = require('@next/bundle-analyzer')({ + enabled: process.env.ANALYZE === 'true', +}); + const withTM = require('next-transpile-modules')([ '@dudoong/ui', '@dudoong/utils', 'date-fns', ]); -module.exports = withInterceptStdout( - withTM({ - // Any additional config for next goes in here - swcMinify: true, - webpack: (config, options) => { - config.module.rules.push({ - test: /\.svg$/, - use: [ - options.defaultLoaders.babel, - { - loader: '@svgr/webpack', - options: { babel: false }, - }, - ], - }); - return config; - }, - images: { - domains: ['asset.dudoong.com'], - }, - rewrites: async () => [ - { - source: '/meta/term', - destination: '/term.html', +module.exports = withBundleAnalyzer( + withInterceptStdout( + withTM({ + // Any additional config for next goes in here + swcMinify: true, + webpack: (config, options) => { + config.module.rules.push({ + test: /\.svg$/, + use: [ + options.defaultLoaders.babel, + { + loader: '@svgr/webpack', + options: { babel: false }, + }, + ], + }); + return config; }, - { - source: '/meta/privacy', - destination: '/privacy.html', + images: { + domains: ['asset.dudoong.com'], + minimumCacheTTL: 5184000, }, - ], - }), - (text) => (text.includes('Duplicate atom key') ? '' : text), + rewrites: async () => [ + { + source: '/meta/term', + destination: '/term.html', + }, + { + source: '/meta/privacy', + destination: '/privacy.html', + }, + ], + }), + (text) => (text.includes('Duplicate atom key') ? '' : text), + ), ); diff --git a/apps/ticket/package.json b/apps/ticket/package.json index 7a1d988c..82b2abfe 100644 --- a/apps/ticket/package.json +++ b/apps/ticket/package.json @@ -15,6 +15,7 @@ "@emotion/styled": "^11.10.5", "@next/font": "13.0.7", "@toast-ui/react-editor": "^3.2.2", + "@toss/impression-area": "^1.3.1", "@tosspayments/payment-widget-sdk": "^0.5.2", "@types/node": "18.11.16", "@types/react": "18.0.26", @@ -30,6 +31,7 @@ "react-dom": "18.2.0", "react-spring-bottom-sheet": "^3.4.1", "recoil": "^0.7.6", + "sharp": "^0.32.1", "swiper": "^9.0.5", "typescript": "4.9.4" }, diff --git a/apps/ticket/pages/_app.tsx b/apps/ticket/pages/_app.tsx index 0ee43e86..bf404a3c 100644 --- a/apps/ticket/pages/_app.tsx +++ b/apps/ticket/pages/_app.tsx @@ -10,7 +10,8 @@ import type { AppProps, AppContext } from 'next/app'; import { useEffect, useState } from 'react'; import { MutableSnapshot, RecoilRoot } from 'recoil'; import 'react-spring-bottom-sheet/dist/style.css'; -import GlobalOverlay from '@components/shared/overlay/GlobalOverlay'; +import dynamic from 'next/dynamic'; +//import GlobalOverlay from '@components/shared/overlay/GlobalOverlay'; import { OauthLoginResponse } from '@dudoong/utils'; import { authState } from '@store/auth'; import { setCredentials } from '@lib/utils/setCredentials'; @@ -22,6 +23,11 @@ import { axiosPrivate } from '@lib/apis/axios'; import Script from 'next/script'; import { GA_TRACKING_ID } from '@lib/utils/gtag'; +const GlobalOverlay = dynamic( + () => import('@components/shared/overlay/GlobalOverlay'), + { ssr: false }, +); + interface MyAppProps extends AppProps { loginData: OauthLoginResponse | null; } @@ -52,6 +58,10 @@ function MyApp({ Component, pageProps, loginData }: MyAppProps) { name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width" /> + {/* Global Site Tag (gtag.js) - Google Analytics */}