From 6f4428797ec0b287b7a5230cc527bbb360e9645b Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Wed, 31 Jul 2024 18:38:34 +0100 Subject: [PATCH 01/12] feat: update server.js --- Dockerfile | 3 ++- server.js | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 76b7676..8942118 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,7 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/server.js ./server.js USER nextjs @@ -48,4 +49,4 @@ EXPOSE 3000 ENV PORT 3000 -CMD ["npm", "start"] +CMD ["node", "server.js"] diff --git a/server.js b/server.js index 705249d..bdde3ee 100644 --- a/server.js +++ b/server.js @@ -25,7 +25,17 @@ const handler = app.getRequestHandler(); const nextUpgradeHandler = app.getUpgradeHandler(); app.prepare().then(() => { - const httpServer = createServer(handler); + const httpServer = createServer((req, res) => { + const parsedUrl = parse(req.url, true); + const { pathname } = parsedUrl; + + // Custom route for /resourcing + if (pathname.startsWith('/resourcing')) { + app.render(req, res, '/', parsedUrl.query); + } else { + handler(req, res, parsedUrl); + } + }); httpServer .once('error', (err) => { From 23f66e79261b6749f478d7a49740d69b9a23d364 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Wed, 31 Jul 2024 18:58:23 +0100 Subject: [PATCH 02/12] feat: update server.js --- server.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index bdde3ee..570247e 100644 --- a/server.js +++ b/server.js @@ -31,10 +31,12 @@ app.prepare().then(() => { // Custom route for /resourcing if (pathname.startsWith('/resourcing')) { - app.render(req, res, '/', parsedUrl.query); - } else { - handler(req, res, parsedUrl); + // Rewrite /resourcing to / + req.url = req.url.replace('/resourcing', '/'); } + + // Serve the Next.js app + handler(req, res, parsedUrl); }); httpServer From 741bb9e7a29dd6e03a0180cc86077cfc1825534e Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Thu, 1 Aug 2024 15:34:29 +0100 Subject: [PATCH 03/12] feat: update server.js --- server.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/server.js b/server.js index 570247e..14b2877 100644 --- a/server.js +++ b/server.js @@ -29,14 +29,14 @@ app.prepare().then(() => { const parsedUrl = parse(req.url, true); const { pathname } = parsedUrl; - // Custom route for /resourcing if (pathname.startsWith('/resourcing')) { // Rewrite /resourcing to / - req.url = req.url.replace('/resourcing', '/'); + const newUrl = req.url.replace('/resourcing', ''); + req.url = newUrl; + app.render(req, res, '/', parsedUrl.query); + } else { + handler(req, res, parsedUrl); } - - // Serve the Next.js app - handler(req, res, parsedUrl); }); httpServer @@ -44,15 +44,9 @@ app.prepare().then(() => { console.error(err); process.exit(1); }) - // eslint-disable-next-line consistent-return .on('upgrade', (request, socket, head) => { - // You may check auth of request here.. - // See https://github.com/websockets/ws#client-authentication - /** - * @param {any} ws - */ const { pathname } = parse(request.url || '/', true); - // Make sure we all for hot module reloading + if (pathname === '/_next/webpack-hmr') { return nextUpgradeHandler(request, socket, head); } @@ -61,6 +55,7 @@ app.prepare().then(() => { wss.emit('connection', ws, request); }; wss.handleUpgrade(request, socket, head, handleAuth); + return undefined; // Explicitly return undefined to satisfy consistent-return }) .listen(port, () => { console.log(`> Ready on http://${hostname}:${port}`); From 1cddf72f1d709d76ecebbc82178d0c982ed1c4ea Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Fri, 2 Aug 2024 16:13:43 +0100 Subject: [PATCH 04/12] feat: update Dockerfile and middleware routing --- Dockerfile | 38 ++++++++++++++++---------------------- middleware.ts | 9 +++++++++ server.js | 23 ++++++++--------------- 3 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 middleware.ts diff --git a/Dockerfile b/Dockerfile index 8942118..08055ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,27 @@ -FROM node:18.18-alpine AS deps -# RUN apk add --no-cache libc6-compat gcompat -# RUN apk add --no-cache g++ make +# Stage 1: Build +FROM node:18.18-alpine AS builder +# Set working directory WORKDIR /app -COPY package.json package-lock.json ./ -RUN --mount=type=secret,id=FONTAWESOME_NPM_AUTH_TOKEN \ - npm config set "@fortawesome:registry" https://npm.fontawesome.com/ && \ - export FONTAWESOME_NPM_AUTH_TOKEN=$(cat /run/secrets/FONTAWESOME_NPM_AUTH_TOKEN) && \ - npm config set "//npm.fontawesome.com/:_authToken" $FONTAWESOME_NPM_AUTH_TOKEN && \ - npm install && \ - echo "done" - # find /app/node_modules/ ! -user root | xargs chown root:root - +# Copy package.json and package-lock.json +COPY package*.json ./ -FROM node:18.18-alpine AS builder -# RUN apk add --no-cache libc6-compat gcompat -# RUN apk add --no-cache g++ make +# Install dependencies +RUN npm install -# RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 -WORKDIR /app -COPY --from=deps /app/node_modules ./node_modules +# Copy all project files COPY . . ENV NEXT_TELEMETRY_DISABLED 1 +# Build the application RUN npm run build +# Stage 2: Run FROM node:18.18-alpine AS runner +# Set working directory WORKDIR /app ENV NODE_ENV production @@ -37,16 +30,17 @@ ENV NEXT_TELEMETRY_DISABLED 1 RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs +# Copy only the necessary files from the build stage +COPY --from=builder /app/package*.json ./ COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next - COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/server.js ./server.js +COPY --from=builder /app/middleware.ts ./ +# Expose the port the app runs on USER nextjs EXPOSE 3000 -ENV PORT 3000 - +# Command to run the app CMD ["node", "server.js"] diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..db98561 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,9 @@ +import type { NextRequest } from 'next/server'; +import { NextResponse } from 'next/server'; + +export function middleware(request: NextRequest) { + if (request.nextUrl.pathname.startsWith('/resourcing')) { + return NextResponse.rewrite(new URL('/', request.url)); + } + return NextResponse.next(); +} diff --git a/server.js b/server.js index 14b2877..705249d 100644 --- a/server.js +++ b/server.js @@ -25,28 +25,22 @@ const handler = app.getRequestHandler(); const nextUpgradeHandler = app.getUpgradeHandler(); app.prepare().then(() => { - const httpServer = createServer((req, res) => { - const parsedUrl = parse(req.url, true); - const { pathname } = parsedUrl; - - if (pathname.startsWith('/resourcing')) { - // Rewrite /resourcing to / - const newUrl = req.url.replace('/resourcing', ''); - req.url = newUrl; - app.render(req, res, '/', parsedUrl.query); - } else { - handler(req, res, parsedUrl); - } - }); + const httpServer = createServer(handler); httpServer .once('error', (err) => { console.error(err); process.exit(1); }) + // eslint-disable-next-line consistent-return .on('upgrade', (request, socket, head) => { + // You may check auth of request here.. + // See https://github.com/websockets/ws#client-authentication + /** + * @param {any} ws + */ const { pathname } = parse(request.url || '/', true); - + // Make sure we all for hot module reloading if (pathname === '/_next/webpack-hmr') { return nextUpgradeHandler(request, socket, head); } @@ -55,7 +49,6 @@ app.prepare().then(() => { wss.emit('connection', ws, request); }; wss.handleUpgrade(request, socket, head, handleAuth); - return undefined; // Explicitly return undefined to satisfy consistent-return }) .listen(port, () => { console.log(`> Ready on http://${hostname}:${port}`); From ebe1e017739b2c2f24b1543bbad69fda774b4762 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Fri, 2 Aug 2024 16:38:55 +0100 Subject: [PATCH 05/12] feat: add handler for static assets --- Dockerfile | 7 +++++++ next.config.js | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 next.config.js diff --git a/Dockerfile b/Dockerfile index 08055ae..22a05a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,10 @@ COPY . . ENV NEXT_TELEMETRY_DISABLED 1 # Build the application +ARG ASSET_PREFIX +ARG BASE_PATH +ENV ASSET_PREFIX=${ASSET_PREFIX} +ENV BASE_PATH=${BASE_PATH} RUN npm run build # Stage 2: Run @@ -42,5 +46,8 @@ USER nextjs EXPOSE 3000 +ENV ASSET_PREFIX=${ASSET_PREFIX} +ENV BASE_PATH=${BASE_PATH} + # Command to run the app CMD ["node", "server.js"] diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..3c93ee2 --- /dev/null +++ b/next.config.js @@ -0,0 +1,7 @@ +const nextConfig = { + assetPrefix: process.env.ASSET_PREFIX || '', + basePath: process.env.BASE_PATH || '', + trailingSlash: true, +}; + +export default nextConfig; From 2194de3ce41285d4670cb638923a8306d7c4fdec Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Fri, 2 Aug 2024 16:41:56 +0100 Subject: [PATCH 06/12] feat: use commonJS syntax for next.config.js --- next.config.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/next.config.js b/next.config.js index 3c93ee2..9e0d55f 100644 --- a/next.config.js +++ b/next.config.js @@ -1,7 +1,5 @@ -const nextConfig = { +module.exports = { assetPrefix: process.env.ASSET_PREFIX || '', basePath: process.env.BASE_PATH || '', trailingSlash: true, }; - -export default nextConfig; From 03a23b11ea1217724b862914c03e63428ea13a17 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Mon, 5 Aug 2024 10:41:07 +0100 Subject: [PATCH 07/12] feat: test new dockerfile for aws deployments --- Dockerfile | 68 +++++++++++++++++++++++++++++++------------------- next.config.js | 1 + 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/Dockerfile b/Dockerfile index 22a05a4..b9952d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,53 +1,69 @@ -# Stage 1: Build -FROM node:18.18-alpine AS builder +FROM node:18-alpine AS base -# Set working directory +# 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 -# Copy package.json and package-lock.json -COPY package*.json ./ +# 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 corepack enable pnpm && pnpm i --frozen-lockfile; \ + else echo "Lockfile not found." && exit 1; \ + fi -# Install dependencies -RUN npm install -# Copy all project files +# 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 - -# Build the application ARG ASSET_PREFIX ARG BASE_PATH ENV ASSET_PREFIX=${ASSET_PREFIX} ENV BASE_PATH=${BASE_PATH} -RUN npm run build -# Stage 2: Run -FROM node:18.18-alpine AS runner +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 -# Set working directory +# Production image, copy all the files and run next +FROM base AS runner WORKDIR /app ENV NODE_ENV production -ENV NEXT_TELEMETRY_DISABLED 1 +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED 1 RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs -# Copy only the necessary files from the build stage -COPY --from=builder /app/package*.json ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/server.js ./server.js -COPY --from=builder /app/middleware.ts ./ +# 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 --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static -# Expose the port the app runs on USER nextjs EXPOSE 3000 -ENV ASSET_PREFIX=${ASSET_PREFIX} -ENV BASE_PATH=${BASE_PATH} +ENV PORT=3000 -# Command to run the app -CMD ["node", "server.js"] +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output +CMD HOSTNAME="0.0.0.0" node server.js \ No newline at end of file diff --git a/next.config.js b/next.config.js index 9e0d55f..648cf16 100644 --- a/next.config.js +++ b/next.config.js @@ -2,4 +2,5 @@ module.exports = { assetPrefix: process.env.ASSET_PREFIX || '', basePath: process.env.BASE_PATH || '', trailingSlash: true, + output: 'standalone', }; From d15c00ab595eb29b6d4df9f3e1e5ffeb0cb4ba68 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Mon, 5 Aug 2024 10:51:58 +0100 Subject: [PATCH 08/12] feat: remove breaking asset paths --- Dockerfile | 4 ---- next.config.js | 2 -- 2 files changed, 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index b9952d8..f304af9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,10 +26,6 @@ COPY . . # 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 -ARG ASSET_PREFIX -ARG BASE_PATH -ENV ASSET_PREFIX=${ASSET_PREFIX} -ENV BASE_PATH=${BASE_PATH} RUN \ if [ -f yarn.lock ]; then yarn run build; \ diff --git a/next.config.js b/next.config.js index 648cf16..0d5245f 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,4 @@ module.exports = { - assetPrefix: process.env.ASSET_PREFIX || '', - basePath: process.env.BASE_PATH || '', trailingSlash: true, output: 'standalone', }; From c23ce0b6502a75532c8ac73be8f893af75a0b7d3 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Fri, 9 Aug 2024 17:23:52 +0100 Subject: [PATCH 09/12] feat: stage working aws deployment --- Dockerfile | 9 +++++++-- middleware.ts | 41 ++++++++++++++++++++++++++++++++++++++--- next.config.js | 21 ++++++++++++++++++++- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index f304af9..2e73c4b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,8 @@ COPY . . # 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 +ARG SITE_URL +ENV SITE_URL=${SITE_URL} RUN \ if [ -f yarn.lock ]; then yarn run build; \ @@ -40,7 +42,7 @@ WORKDIR /app ENV NODE_ENV production # Uncomment the following line in case you want to disable telemetry during runtime. -# ENV NEXT_TELEMETRY_DISABLED 1 +ENV NEXT_TELEMETRY_DISABLED 1 RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs @@ -53,6 +55,7 @@ RUN chown nextjs:nodejs .next # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./resourcing/.next/static USER nextjs @@ -62,4 +65,6 @@ ENV PORT=3000 # server.js is created by next build from the standalone output # https://nextjs.org/docs/pages/api-reference/next-config-js/output -CMD HOSTNAME="0.0.0.0" node server.js \ No newline at end of file +CMD node server.js +# CMD HOSTNAME="0.0.0.0" node server.js +# CMD ["npm", "start"] \ No newline at end of file diff --git a/middleware.ts b/middleware.ts index db98561..34f70ef 100644 --- a/middleware.ts +++ b/middleware.ts @@ -2,8 +2,43 @@ import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; export function middleware(request: NextRequest) { - if (request.nextUrl.pathname.startsWith('/resourcing')) { - return NextResponse.rewrite(new URL('/', request.url)); + console.log('hostname'); + console.log(process.env.HOSTNAME); + + console.log('call1'); + console.log(request.url); + console.log(request.nextUrl.pathname); + console.log(''); + + let response; + + if (request.nextUrl.pathname.startsWith('/api/resourcing')) { + const newUrl = new URL(request.url); + newUrl.pathname = request.nextUrl.pathname.replace( + '/api/resourcing', + '/resourcing/api/resourcing' + ); + + response = NextResponse.rewrite(newUrl); + + console.log('call3'); + console.log(response); + console.log(''); + + return response; } - return NextResponse.next(); + + console.log('call2'); + + console.log(request.url); + console.log(request.nextUrl.pathname); + console.log(); + + response = NextResponse.next(); + + console.log('call4'); + console.log(response); + console.log(); + + return response; } diff --git a/next.config.js b/next.config.js index 0d5245f..0cd1238 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,23 @@ +const isProd = process.env.NODE_ENV === 'production'; +console.log(isProd); + module.exports = { - trailingSlash: true, output: 'standalone', + basePath: '/resourcing', + // async rewrites() { + // return { + // beforeFiles: [ + // { + // source: '/', + // destination: '/resourcing', + // }, + // { + // source: '/:slug*', + // destination: '/resourcing/:slug*', // Matched parameters can be used in the destination + // }, + // ], + // }; + // }, + // Use the CDN in production and localhost for development. + assetPrefix: isProd ? '/resourcing' : undefined, }; From 6b414f93322c1a2b83f574a23143f8b98872dcee Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Mon, 12 Aug 2024 16:17:10 +0100 Subject: [PATCH 10/12] feat: add basepath --- next.config.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/next.config.js b/next.config.js index 0cd1238..ae3bf1f 100644 --- a/next.config.js +++ b/next.config.js @@ -1,23 +1,7 @@ const isProd = process.env.NODE_ENV === 'production'; -console.log(isProd); module.exports = { output: 'standalone', basePath: '/resourcing', - // async rewrites() { - // return { - // beforeFiles: [ - // { - // source: '/', - // destination: '/resourcing', - // }, - // { - // source: '/:slug*', - // destination: '/resourcing/:slug*', // Matched parameters can be used in the destination - // }, - // ], - // }; - // }, - // Use the CDN in production and localhost for development. assetPrefix: isProd ? '/resourcing' : undefined, }; From 79ea2cfcca68baa4ce943912d4bb3654f306e3c8 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Mon, 12 Aug 2024 16:34:16 +0100 Subject: [PATCH 11/12] feat: remove logging statements --- middleware.ts | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/middleware.ts b/middleware.ts index 34f70ef..6bcc0ef 100644 --- a/middleware.ts +++ b/middleware.ts @@ -2,15 +2,7 @@ import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; export function middleware(request: NextRequest) { - console.log('hostname'); - console.log(process.env.HOSTNAME); - - console.log('call1'); - console.log(request.url); - console.log(request.nextUrl.pathname); - console.log(''); - - let response; + let response = NextResponse.next(); if (request.nextUrl.pathname.startsWith('/api/resourcing')) { const newUrl = new URL(request.url); @@ -21,24 +13,8 @@ export function middleware(request: NextRequest) { response = NextResponse.rewrite(newUrl); - console.log('call3'); - console.log(response); - console.log(''); - return response; } - console.log('call2'); - - console.log(request.url); - console.log(request.nextUrl.pathname); - console.log(); - - response = NextResponse.next(); - - console.log('call4'); - console.log(response); - console.log(); - return response; } From 90c4cc1af98b005ed68251cd636001af379f3849 Mon Sep 17 00:00:00 2001 From: Andy Payne Date: Mon, 12 Aug 2024 16:47:23 +0100 Subject: [PATCH 12/12] feat: update dockerfile --- Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2e73c4b..7e29dfa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,7 +55,6 @@ RUN chown nextjs:nodejs .next # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./resourcing/.next/static USER nextjs @@ -66,5 +65,3 @@ ENV PORT=3000 # 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 -# CMD HOSTNAME="0.0.0.0" node server.js -# CMD ["npm", "start"] \ No newline at end of file