Setup NextJS project with Bun
Introduction
Bun is a modern JavaScript runtime built with the goal of optimizing performance and improving the development experience. In addition to being compatible with the NodeJS ecosystem, Bun also integrates a package manager, bundler and test runner in the same tool.
Some outstanding advantages of Bun:
- Dependency installation speed is significantly faster than npm, yarn and even pnpm.
- High startup and application execution performance thanks to being written in Zig.
- Integrates multiple tools in one runtime, helping reduce the number of dependencies required.
- Supports projects using modern frameworks like NextJS and NestJS well.
- Helps shorten build times and optimize the CI/CD process.
Detail
- Note that although using Bun can provide comprehensive and effective support for NPM packages, there are still many risks regarding compatibility with older package versions.
- If the project you are developing is relatively large and has been operating for a long time, consider carefully before deciding to migrate to Bun.
- It will be more suitable if you or your company intend to deploy a new project, then using Bun will help enhance your experience in the development, testing and CI/CD process quickly.
First, install as follows if you use Linux/MacOS:
curl -fsSL https://bun.sh/install | bash
To create a NextJS project:
bunx create-next-app@latest
Build Docker image
For NextJS projects, it supports a standalone mode to build a separate server that can handle both server side and client side, which you can use directly without going through any CDN.
First, configure the next.config.ts file to use standalone mode as follows:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: 'standalone',
};
export default nextConfig;
Create a Dockerfile with the following content:
FROM oven/bun:1-alpine AS deps
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
FROM oven/bun:1-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN bun run build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
The above Dockerfile uses a multi-stage build model to optimize image size and increase build speed, making the final image more compact, reducing deployment time and taking advantage of Bun's performance during package installation as well as application builds.
The
depsstage uses the Bun image to install all dependencies. Only copyingpackage.jsonandbun.lockhelps Docker utilize the cache layer effectively, only reinstalling packages when these files change.The
builderstage continues to use Bun to build the NextJS application. The entire source code is copied into the container and built using thebun run buildcommand.The
runnerstage uses a lighter NodeJS Alpine image to run the application in the production environment.Create a separate User and group to avoid running the container with root privileges, increasing security.
Copy the necessary folders such as:
public: resources allowing public access.next/static: static resources, without any logic processing.next/standalone: this is the structure created by NextJS when using the standalone mode, helping reduce image size and only keeping the files necessary to run the applicationThe command
CMD ["node", "server.js"]starts the NextJS application in the production environment.
Happy coding!
Comments
Post a Comment