Skip to main content
interlace
Plugin: import-nextRules

no-commonjs

Prevents CommonJS require/module.exports

šŸ’¼ This rule is enabled in the following configs: recommended, typescript. šŸ’” This rule is manually fixable by editor suggestions.

Rule Details

An ES module that uses CommonJS cannot be tree-shaken, is not statically analysable, and breaks when loaded as native ESM. This rule reports CommonJS in an ES module:

  • a call to the global require (static or dynamic argument), and TS import x = require('m');
  • assigning module.exports (dotted or computed), or one of its properties;
  • assigning a property of the global exports;
  • reading the global __dirname or __filename.

The rule decides by binding. A require the file binds itself (a parameter, or createRequire(import.meta.url), the sanctioned ESM way to load CommonJS), a local exports object, and the ESM __dirname shim (const __dirname = dirname(fileURLToPath(import.meta.url))) are the file's own values; a property named __dirname is not the global either.

A .cjs / .cts file, or one the config parses as CommonJS, is CommonJS on purpose and is not checked. require.resolve() loads nothing and is not reported.

āŒ Incorrect

const util = require('./util');
module.exports = { run };
exports.run = run;
console.log(__dirname);

āœ… Correct

import util from './util';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const data = require('./data.json');
export { run };

Options

[
  {
    "type": "object",
    "properties": {
      "allowRequire": {
        "type": "boolean",
        "default": false,
        "description": "Allow require() calls."
      },
      "allowModuleExports": {
        "type": "boolean",
        "default": false,
        "description": "Allow module.exports."
      },
      "allowExports": {
        "type": "boolean",
        "default": false,
        "description": "Allow exports.* patterns."
      },
      "allowInFiles": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "description": "Allow CommonJS in specific files."
      },
      "suggestES6": {
        "type": "boolean",
        "default": true,
        "description": "Suggest ES6 alternatives."
      }
    },
    "additionalProperties": false
  }
]
  • allowRequire (default false): accept require() and import x = require().
  • allowModuleExports (default false): accept module.exports assignments.
  • allowExports (default false): accept exports.* assignments.
  • allowInFiles (default []): file globs (or path substrings) where CommonJS is accepted. A glob matches any run of whole path segments.
  • suggestES6 (default true): offer an editor suggestion with the ES module equivalent.

When Not To Use It

In a CommonJS codebase that has not moved to ES modules.

Use this rule

npm install -D oxlint-plugin-import-next
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-import-next"],  "rules": {    "import-next/no-commonjs": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-import-next'],    rules: {      'import-next/no-commonjs': 'error',    },  },});

oxlint-plugin-import-next re-exports eslint-plugin-import-next/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.