---
sidebar_position: 0
---

# Configuring Modern.js

There are two configurations in the Modern.js, a compile configuration and a server runtime configuration.

The compile configuration can be configured in two places:

- `modern.config.(ts|js|mjs)` file in the root path
- `package.json` file

:::info
Configurations in both package.json and modern.config.ts file are not supported for the same configuration. Configuration in modern.config.ts is recommended.
:::

Server runtime configuration can be configured in the `modern.server-runtime.config.(ts|js|mjs)` file in the root path.

## Configure in the configuration file

Modern.js configuration files are defined in the root path of the project, and supports `.ts`, `.js` and `.mjs` formats:

- `modern.config.ts`
- `modern.config.js`
- `modern.config.mjs`

### modern.config.ts (recommended)

We recommend using configuration files in `.ts` format, which provides friendly TypeScript type hints to help you avoid configuration errors.

Import the `defineConfig` tool function from `@modern-js/app-tools`, which will help you with configuration type derivation and type completion:

```ts title="modern.config.ts"
import { defineConfig } from '@modern-js/app-tools';

export default defineConfig({
  source: {
    alias: {
      '@common': './src/common',
    },
  },
});
```

When using Rspack as the bundler, due to some differences in configuration types between webpack and Rspack, you need to specify `<'rspack'>` generic type for `defineConfig`:

```diff title=modern.config.ts
- export default defineConfig({
+ export default defineConfig<'rspack'>({
   //...
});
```

### modern.config.js

If you are developing a non-TypeScript project, you can use the configuration file in .js format:

```js title="modern.config.js"
export default {
  source: {
    alias: opts => {
      opts['@common'] = './src/common';
    },
  },
};
```

You can also dynamically set it with `process.env.NODE _ENV`:

```js title="modern.config.js"
export default {
  server: {
    ssr: process.env.NODE_ENV === 'development',
  },
};
```

### Export Configuration Function

Modern.js supports exporting a function in the configuration file, and you can dynamically compute the configuration in the function and return it to Modern.js.

```js title="modern.config.js"
import { defineConfig } from '@modern-js/app-tools';

export default defineConfig(({ env, command }) => ({
  source: {
    alias: {
      '@foo': env === 'development' ? './src/foo.dev.ts' : './src/foo.prod.ts',
    },
  },
}));
```

This function takes the following parameters:

- `env`: same as the value of `process.env.NODE_ENV`.
  - When running `modern dev` or `modern start`, the value of `env` is `development`.
  - When running `modern build` or `modern serve`, the value of `env` is `production`.
  - When running `modern test`, the value of `env` is `test`.
- `command`: corresponds to the currently running command, such as `dev`, `start`, `build`, `serve`.

### Export Async Function

Modern.js also supports exporting an asynchronous function in the configuration file, you can perform some asynchronous operations in the function:

```js title="modern.config.js"
import { defineConfig } from '@modern-js/app-tools';

export default defineConfig(async ({ env, command }) => {
  const result = await someAsyncFunction();

  return {
    html: {
      title: result,
    },
  };
});
```

### Specify the Configuration File

You can specify the name of the configuration file using the `--config` option.

For example, if you need to use the `modern.prod.config.js` file when running build, you can add the following scripts to `package.json`:

```json title="package.json"
{
  "scripts": {
    "dev": "modern dev",
    "build": "modern build --config modern.prod.config.js"
  }
}
```

You can also abbreviate the `--config` option to `-c`:

```bash
$ modern build -c modern.prod.config.js
```

## Configure in package.json (not recommended)

In addition to configuration files, configuration options can also be set the `modernConfig` field in the `package.json`, such as:

```json title="package.json"
{
  "modernConfig": {
    "source": {
      "alias": {
        "@common": "./src/common"
      }
    }
  }
}
```

Due to the limitation of the JSON file format, only simple types such as numbers, strings, boolean values, arrays, etc. can be defined in `package.json`. When we need to set the value of the function type, it is recommended to set it in the Modern.js configuration file.

### Note

- It is not recommended to use both `package.json` and `modern.config.t[j]s` for configuration. If both are used and a configuration conflict occurs, Modern.js will prompt error on the command line.
- `@modern-js/runtime` exports the [defineConfig](/apis/app/runtime/app/define-config) API of the same name, please pay attention to the distinction.

## Debug configuration locally

To facilitate local debugging configuration locally, Modern.js supports creating `modern.config.local.(ts|js|mjs)` files in the root directory of the project to override `modern.config.(ts|js|mjs)` configurations.

### Example

For example, the port number is configured as `3000` in `modern.config.ts`:

```ts title="modern.config.ts"
import { defineConfig } from '@modern-js/app-tools';

export default defineConfig({
  server: {
    port: 3000,
  },
});
```

If you need to change the port number to `3001` to debugging locally, but you don't want to change the `modern.config.ts` file of the current project, you can create a `modern.config.local.ts` file and add the following configuration:

```ts title="modern.config.local.ts"
import { defineConfig } from '@modern-js/app-tools';

export default defineConfig({
  server: {
    port: 3001,
  },
});
```

The configuration in the `modern.config.local.ts` file will be deep merged with the configuration in `modern.config.ts` and override the configurations in `modern.config.ts`, so `server.port` will be is overridden by `3001`.

### Note

When using `modern.config.local.ts`, please note the following:

- The `modern.config.local.ts` file is only loaded when running `modern dev` or `modern start` commands, and will not be loaded when running `modern build`.
- The `modern.config.local.ts` file overrides not only over `modern.config.ts`, but also the `modernConfig` field in `package.json`.
- As `modern.config.local.ts` is only used for local debugging, it is not recommended to commit it to the repository, please ensure that the project's `.gitignore` file contains `modern.config.local.ts`.

```bash title=".gitingore"
modern.config.local.ts
modern.config.local.js
modern.config.local.mjs
```

## Merge Multiple Configurations

In some cases, you may need to merge multiple configurations into one configuration. You can use the `mergeConfig` util to merge multiple configurations.

The `mergeConfig` function accepts an array as a parameter, and each item in the array is a configuration object. `mergeConfig` will deeply merge each configuration object in the array, automatically merge multiple functions into an array, and returns a merged configuration object.

### Example

```ts title="modern.config.ts"
import { mergeConfig } from '@modern-js/app-tools';

const config1 = {
   dev: {
     port: 3000,
   },
   tools: {
     postcss: () => console. log('config1');
   },
};
const config2 = {
   dev: {
     port: 3001,
   },
   tools: {
     postcss: () => console. log('config2');
   },
};

const mergedConfig = mergeConfig([config1, config2]);
```

In the above example, the merged configuration object is:

```ts
const mergedConfig = {
  dev: {
    port: 3001,
  },
  tools: {
    postcss: [() => console.log('config1'), () => console.log('config2')],
  },
};
```

## Configuration Type

Modern.js exports `AppUserConfig` type, which corresponds to the type of Modern.js configuration object:

```ts title="modern.config.ts"
import type { AppUserConfig } from '@modern-js/app-tools';

const config: AppUserConfig = {
  tools: {
    webpack: {},
  },
};
```

When using Rspack as the bundler, due to some differences in configuration types between webpack and Rspack, you need to specify `<'rspack'>` generic type for `defineConfig`:

```ts title="modern.config.ts"
import type { AppUserConfig } from '@modern-js/app-tools';

const config: AppUserConfig<'rspack'> = {
  tools: {
    rspack: {},
  },
};
```
