Back to Moon

Next example

website/docs/guides/examples/next.mdx

2.2.44.9 KB
Original Source

import AddDepsTabs from '@site/src/components/AddDepsTabs'; import CreateDepTabs from '@site/src/components/CreateDepTabs'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import HeadingApiLink from '@site/src/components/Docs/HeadingApiLink';

<HeadingApiLink to="https://github.com/moonrepo/examples/tree/master/apps/nextjs-app" />

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).

shell
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.* file.

:::tip

We suggest inheriting Next.js tasks from the official moon configuration preset.

:::

yaml
# 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.

<AddDepsTabs dep="eslint-config-next" package="<project>" dev />

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.

js
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.

<Tabs groupId="lint-type" defaultValue="global" values={[ { label: 'Global lint', value: 'global' }, { label: 'Next.js lint', value: 'nextjs' }, ]}

<TabItem value="global">

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.

js
module.exports = {
  eslint: {
    ignoreDuringBuilds: true,
  },
};
</TabItem> <TabItem value="nextjs">

If you'd prefer to use the next lint command, add it as a task to the project's moon.*.

yaml
tasks:
  lint:
    command: 'next lint'
    inputs:
      - '@group(next)'

Furthermore, if a global lint task exists, be sure to exclude it from being inherited.

yaml
workspace:
  inheritedTasks:
    exclude: ['lint']
</TabItem> </Tabs>

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.

js
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.

js
module.exports = {
  compress: true,
};