Next example
In this guide, you'll learn how to integrate Next.js into moon.
Begin by creating a new Next.js project at a specified folder path (this should not be created in the workspace root, unless a polyrepo).
cd apps && npx create-next-app <project> --typescript
View the official Next.js docs for a more in-depth guide to getting started!
Setup
Since Next.js is per-project, the associated moon tasks should be defined in each project's
moon.yml
file.
We suggest inheriting Next.js tasks from the official moon configuration preset.
# Inherit tasks from the `next` preset
# https://github.com/moonrepo/moon-configs
tags: ['next']
ESLint integration
Next.js has built-in support for ESLint, which is great, but complicates things a bit. Because of this, you have two options for moving forward:
- Use a global
lint
task and bypass Next.js's solution (preferred). - Use Next.js's solution only.
Regardless of which option is chosen, the following changes are applicable to all options and should
be made. Begin be installing the
eslint-config-next
dependency in
the application's package.json
.
- Yarn
- Yarn (classic)
- npm
- pnpm
- Bun
yarn workspace <project> add --dev eslint-config-next
yarn workspace <project> add --dev eslint-config-next
npm install --save-dev --workspace <project> eslint-config-next
pnpm add --save-dev --filter <project> eslint-config-next
bun install --dev eslint-config-next
Since the Next.js app is located within a subfolder, we'll need to tell the ESLint plugin where to
locate it. This can be achieved with a project-level .eslintrc.js
file.
module.exports = {
extends: 'next', // or 'next/core-web-vitals'
settings: {
next: {
rootDir: __dirname,
},
},
};
With the basics now setup, choose the option that works best for you.
- Global lint
- Next.js lint
We encourage using the global lint
task for consistency across all projects within the repository.
With this approach, the eslint
command itself will be ran and the next lint
command will be
ignored, but the eslint-config-next
rules will still be used.
Additionally, we suggest disabling the linter during the build process, but is not a requirement. As
a potential alternative, add the lint
task as a dependency for the build
task.
module.exports = {
eslint: {
ignoreDuringBuilds: true,
},
};
If you'd prefer to use the next lint
command, add it as a task to the project's
moon.yml
.
tasks:
lint:
command: 'next lint'
inputs:
- '@group(next)'
Furthermore, if a global lint
task exists, be sure to exclude it from being inherited.
workspace:
inheritedTasks:
exclude: ['lint']
TypeScript integration
Next.js also has built-in support for TypeScript, but has similar caveats to the ESLint integration. TypeScript itself is a bit involved, so we suggest reading the official Next.js documentation before continuing.
At this point we'll assume that a tsconfig.json
has been created in the application, and
typechecking works. From here we suggest utilizing a global typecheck
task for
consistency across all projects within the repository.
Additionally, we suggest disabling the typechecker during the build process, but is not a
requirement. As a potential alternative, add the typecheck
task as a dependency for the build
task.
module.exports = {
typescript: {
ignoreBuildErrors: true,
},
};
Configuration
Root-level
We suggest against root-level configuration, as Next.js should be installed per-project, and the
next
command expects the configuration to live relative to the project root.
Project-level
When creating a new Next.js project, a
next.config.<js|mjs>
is
created, and must exist in the project root. This allows each project to configure Next.js for
their needs.
module.exports = {
compress: true,
};