# Build FAQ

Here only some common problems and bad cases are recorded.

**If the build products do not meet expectations, especially when [buildPreset](/api/config/build-preset) is configured,
please first understand what configuration items buildPreset represents, and then check each configuration item based on all configuration items.**

## Product FAQ

import BuildProductFAQ from '@site-docs-en/components/faq-build-product';

<BuildProductFAQ />

### Initialization of Class Fields

TypeSript provides the `useDefineForClassFields` configuration to control the conversion handling for `public class fields`.

If we have a piece of code:

```ts
class C {
  foo = 100;
  bar: string;
}
```

When `useDefineForClassFields` is `false`, then the compiled code will look like:

```ts
class C {
  constructor() {
    this.foo = 100;
  }
}
```

When `useDefineForClassFields` is `true`, then the compiled code will look like:

```ts
class C {
  constructor() {
    Object.defineProperty(this, 'foo', {
      enumerable: true,
      configurable: true,
      writable: true,
      value: 100,
    });
    Object.defineProperty(this, 'bar', {
      enumerable: true,
      configurable: true,
      writable: true,
      value: void 0,
    });
  }
}
```

Also the default value of this configuration will change depending on the [`target`](https://www.typescriptlang.org/tsconfig#target) configuration of tsconfig.json: When `target` is ES2022 or higher, then `useDefineForClassFields` is configured to `true` by default, otherwise it defaults to `false`.

For more information on this configuration of TypeScript, you can refer to the following link:

- [The useDefineForClassFields Flag and The declare Property Modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier)

The Modern.js Module will currently process according to the following logic:

1. The first decision to enable this feature inside Modern.js Module is based on the `useDefineForClassFields` configuration in tsconfig.json of the current project. Currently, only the contents of the tsconfig.json file under the current project path will be read, and the final tsconfig configuration based on the [`extends`](https://www.typescriptlang.org/tsconfig#extends) configuration is not supported at this time.
2. If the `useDefineForClassFields` configuration of tsconfig.json is not detected, the default value is determined based on the `target` configuration of tsconfig.json. If `target` is greater than `ES2022` (including `EsNext`), then `useDefineForClassFields` defaults to `true`, otherwise it is `false`.
3. If the `target` of tsconfig.json is not detected, it is processed according to the value of `useDefineForClassFields` as `true`.

### babel-plugin-lodash treats the introduced lodash as `undefined`

This problem occurs when using something like the following:

```ts
import * as Lodash from 'lodash';

export const libs = {
  _: Lodash,
};
```

Current related issues on the `babel-plugin-lodash` Github:

- [#235](https://github.com/lodash/babel-plugin-lodash/issues/235)

The solution to this problem is to remove `babel-plugin-lodash`, since the plugin is not needed for on-demand referencing at this point and using it would have side effects.

A similar situation occurs with `babel-plugin-import`. If there is code like the following:

```ts
import * as Comps from 'components';

export const libs = {
  comps: Comps,
};
```

In this case `babel-plugin-import` may also cause `Comps` to become `undefined`. So you need to remove the corresponding `babel-plugin-import` as well.

### Cannot find module 'http'

If the output reports an error like `Cannot find module 'http'` at browser runtime, it means that your output has bundled node modules.
This may occur if some of your dependencies support both browser and node, such as `axios`, in which case you only need to set the [platform](/api/config/build-config.html#platform) to `browser`.
If some third-party packages don't support the browser, you may need to manually inject [node polyfill](/plugins/official-list/plugin-node-polyfill).

## Exceptions FAQ

import BuildExceptionFAQ from '@site-docs-en/components/faq-build-exception';

<BuildExceptionFAQ />

### Dynamic require of "react" is not supported

#### Problem Description

When the product format in the product configuration of the build is ES modules.

```ts
export default defineConfig({
  buildConfig: {
    format: 'esm',
  },
});
```

If you import a cjs product from a third-party npm package, the resulting product may not work properly under webpack.

![](https://lf3-static.bytednsdoc.com/obj/eden-cn/shylnyhaeh7uldvivhn/1280X1280.png)

#### Solution

1. **First you need to find which third-party package is causing the problem**. For example, if the error message points to the `react` package, then look for a third-party package that has code like `require('react')` in it. For example [`react-draggable`](https://www.npmjs.com/package/react-draggable), which only contains `cjs` artifacts, then the problem is localized to the `react-draggable` package.
2. Then we need to exclude this package with the following configuration, i.e. **not package problematic third-party packages**.

```ts
export default defineConfig({
  buildConfig: {
    externals: ['react-draggable'],
  },
});
```

#### Reference Links

- [When using esbuild with external react I get Dynamic require of "react" is not supported](https://stackoverflow.com/questions/68423950/when-using-esbuild-with-external-react-i-get-dynamic-require-of-react-is-not-s)

### During compilation, an error was reported in the less file of a component library:`'Operation on an invalid type'`

This is probably because the component library depends on Less version v3, while Modern.js Module defaults to v4. v3 and v4 have a Break Change in the `math` configuration, check this [link](https://stackoverflow.com/questions/73298187/less-error-operation-on-an-invalid-type-in-antd-dependency) for details.

Therefore, if a component library like this is used in the source code:

`buildPreset` is used in the build configuration, make the following changes:

```js
module.exports = {
  buildPreset({ extendPreset }) {
    return extendPreset('your-build-preset', {
      style: {
        less: {
          lessOptions: {
            math: 'always',
          },
        },
      },
    });
  },
};
```

Or, if a custom `buildConfig` is used, modify it as follows:

```js
module.exports = {
  buildConfig: {
    style: {
      less: {
        lessOptions: {
          math: 'always',
        },
      },
    },
  },
};
```

If you are using a component like this in Storybook, you will need to modify the debugging configuration of Storybook:

```js filename='.storybook/main.ts'
module.exports = {
  framework: {
    options: {
      builderConfig: {
        tools: {
          webpackChain(chain, { CHAIN_ID }) {
            chain.module
              .rule(CHAIN_ID.RULE.LESS)
              .use(CHAIN_ID.USE.LESS)
              .tap(options => {
                options.lessOptions = {
                  ...options.lessOptions,
                  math: 'always',
                };
                return options;
              });
          },
        },
      },
    },
  },
};
```

### Bundleless DTS failed

In the bundleless scenario, it's `tsc` that generates the type declaration file directly. You can find the problem file by printing the error message in the terminal.
For source code files, it is recommended to fix the type problem, which can better enable reuse of your package. However. if you encounter a type checking problem with a thrid-party package:

1. enable [skipLibCheck](https://www.typescriptlang.org/tsconfig#skipLibCheck) to skip the d.ts check of the thrid-party package.
2. If the package exports ts files directly, skipLibCheck will not work because it can only skip the d.ts check,
   so you can only turn off [dts.abortOnError](/api/config/build-config.html#dtsabortonerror) to ignore these errors.

### Bundle DTS failed

The Modern.js Module directly uses [rollup-plugin-dts](https://github.com/Swatinem/rollup-plugin-dts) to package your type description files.
**It may not be able to handle the type files of some third-party dependencies**

If you encounter an error message titled "Bundle DTS failed" during the build process of the Modern.js Module, you can observe that the error message is from a third-party dependency.
Try setting [`dts.respectExternal`](/api/config/build-config.html#dtsrespectexternal) to `false` to turn off the behavior of packaging type files of third-party dependencies.

### Error reported for `defineConfig` function type: `If there is no reference to "..." then the inferred type of "default" cannot be named`

Check if the [`include`](https://www.typescriptlang.org/tsconfig#include) configuration exists in the project's tsconfig.json file, and if not, try adding the following:

```json
{
  "include": ["src"]
}
```

## Other FAQ

import BuildOtherFAQ from '@site-docs-en/components/faq-build-other';

<BuildOtherFAQ />

### How to skip the pre-processing of less/scss files with bundleless

Bundleless is a single-file compilation method. You just need to remove your less/scss files from the entry and copy them to the output.
Note that we will also rewrite the moduleId of js referencing less/scss, turn it off through the [redirect](/api/config/build-config#redirect) plugin.

Below is an example of skipping less file processing. You will find that all less files in src are copied to dist and the relative path is preserved.

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundleless',
    input: ['src', '!src/**/*.less'],
    redirect: {
      style: false,
    },
    copy: {
      patterns: [
        {
          from: './**/*.less',
          to: './',
        },
      ],
      options: {
        enableCopySync: true,
      },
    },
  },
});
```

### Add additional compilation feature

The Modern.js Module is based on the esbuild implementation, so if you have special needs or want to add additional compilation capabilities, you can do so by implementing the esbuild plugin.

The Modern.js Module provides [`esbuildOptions`](/api/config/build-config.html#esbuildoptions) configuration to allow modification of Modern.js's internal esbuild configuration, so that custom esbuild plugins can be added via this configuration:

import RegisterEsbuildPlugin from '@site-docs-en/components/register-esbuild-plugin';

<RegisterEsbuildPlugin />

### Support for generating TypeScript declaration files for CSS Modules

- First Solution: [typed-css-modules](https://github.com/Quramy/typed-css-modules)
- Second Solution: [postcss-modules-dts](https://www.npmjs.com/package/@guanghechen/postcss-modules-dts)

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

export default defineConfig(async () => {
  const { dts } = await import('@guanghechen/postcss-modules-dts');
  return {
    buildConfig: {
      style: {
        modules: { ...dts },
      },
    },
    // custom config
  };
});
```
