For AI agents: the complete documentation index is available at https://rslint.rs/llms.txt, the full documentation bundle is available at https://rslint.rs/llms-full.txt, and this page is available as Markdown at https://rslint.rs/rules/unicorn/prefer-module.md.
close

prefer-module

Added in v0.10.1

Configuration

rslint.config.ts
import { defineConfig, unicornPlugin } from '@rslint/core';

export default defineConfig([
  unicornPlugin.configs.recommended,
  {
    rules: {
      'unicorn/prefer-module': 'error',
    },
  },
]);

Rule details

Prefer JavaScript modules (ESM) over CommonJS.

This rule reports:

  • "use strict" directives, because JavaScript modules are already strict.
  • return statements outside functions.
  • References to the CommonJS globals require, exports, module, __dirname, and __filename.

CommonJS names are checked when available as globals, for example through the Node.js globals in languageOptions.globals. Locally declared and imported bindings are ignored. Files ending in .cjs are ignored, regardless of case.

Examples of incorrect code:

const {fromPairs} = require('lodash');
module.exports = foo;
const file = path.join(__dirname, 'foo.js');

Examples of correct code:

import {fromPairs} from 'lodash-es';
export default foo;
const file = path.join(import.meta.dirname, 'foo.js');

Fixes and suggestions

In .mjs files, automatic fixing removes "use strict" directives. Other files receive a suggestion to remove the directive.

Suggestions convert top-level require() calls to imports and simple exports or module.exports assignments to exports. JSON imports include a with {type: 'json'} attribute. Calls inside functions, let declarations, multiple variable declarations, and destructuring with defaults or rest properties receive diagnostics without an import suggestion.

For __dirname and __filename, the rule suggests import.meta.dirname and import.meta.filename. It also offers alternatives using path.dirname(url.fileURLToPath(import.meta.url)) and url.fileURLToPath(import.meta.url). Add the required node:path and node:url imports when choosing those alternatives.

Options

This rule has no options.

Differences from upstream

Compared with eslint-plugin-unicorn v79.0.0, rslint keeps the diagnostic and withholds edits that would produce invalid syntax or remove comments.

  • The comment in "use strict" /* keep */; blocks removal of the directive. Move the comment outside the statement to enable the edit.
  • Calls such as require<string>('x') and require('x',) need manual conversion to imports. The upstream suggestion retains the type arguments or trailing comma in the generated import.
  • A local name that is invalid in ES modules blocks the import suggestion. For example, rename await in const await = require('x'); before converting it to an import.
  • For module /* comment */ .exports = value, move the comment outside module.exports before applying the export suggestion. Otherwise, replacing the member expression would delete the comment.
  • References in TypeScript types, such as type File = typeof __filename, receive no path replacement suggestions. Update the type manually when converting the file to ESM.
  • Assignments and updates such as __filename++ offer only the import.meta replacement. The alternative using url.fileURLToPath() cannot be assigned to.

Original documentation