Skip to content

Comments

refactor(linter/plugins): remove require(esm)#15866

Merged
graphite-app[bot] merged 1 commit intomainfrom
11-19-refactor_linter_plugins_remove_require_esm_
Nov 19, 2025
Merged

refactor(linter/plugins): remove require(esm)#15866
graphite-app[bot] merged 1 commit intomainfrom
11-19-refactor_linter_plugins_remove_require_esm_

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented Nov 19, 2025

loadPlugin is already async, so we don't need to use require(esm) for lazy-loading the JS plugins-related code. Use import instead.

This has 3 advantages:

  1. Removes the hacky workaround of a separate entry point for TSDown, and hard-coded path in require('./plugins.js'), which is only correct if TSDown config remains unchanged.
  2. TypeScript can "see into" the import -> better type safety.
  3. Support versions of NodeJS which don't support require(esm).

On the last one, it's not strictly necessary, as oxlint requires a version of NodeJS with require(esm) support:

"engines": {
"node": "^20.19.0 || >=22.12.0"
},

But if user is on an older version of NodeJS, JS plugins should now work.

@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI A-linter-plugins Area - Linter JS plugins labels Nov 19, 2025
Copy link
Member Author


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions bot added the C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior label Nov 19, 2025
@overlookmotel overlookmotel marked this pull request as ready for review November 19, 2025 10:52
Copilot AI review requested due to automatic review settings November 19, 2025 10:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the plugin loading mechanism to replace require(esm) with dynamic import(), eliminating a hacky workaround and improving type safety. The change enables better TypeScript integration and broadens Node.js version compatibility for JS plugins.

Key Changes

  • Removed dual-entry build configuration in TSDown, simplifying to a single entry point
  • Replaced synchronous require() with asynchronous import() for lazy-loading plugin code
  • Improved type checking by allowing TypeScript to "see into" the import statement

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
apps/oxlint/tsdown.config.ts Simplified build configuration from dual entries (cli and plugins) to single entry (cli)
apps/oxlint/src-js/cli.ts Replaced require(esm) with dynamic import() for plugin loading, updated import path from ./plugins.js to ./plugins/index.js

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@overlookmotel overlookmotel removed the A-linter Area - Linter label Nov 19, 2025
@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Nov 19, 2025
Copy link
Contributor

camc314 commented Nov 19, 2025

Merge activity

`loadPlugin` is already async, so we don't need to use `require(esm)` for lazy-loading the JS plugins-related code. Use `import` instead.

This has 3 advantages:

1. Removes the hacky workaround of a separate entry point for TSDown, and hard-coded path in `require('./plugins.js')`, which is only correct if TSDown config remains unchanged.
2. TypeScript can "see into" the `import` -> better type safety.
3. Support versions of NodeJS which don't support `require(esm)`.

On the last one, it's not strictly necessary, as `oxlint` requires a version of NodeJS with `require(esm)` support:

https://github.com/oxc-project/oxc/blob/b622ef87adf1bbed1e76ba0f610b653acb93e72b/apps/oxlint/package.json#L19-L21

But if user *is* on an older version of NodeJS, JS plugins should now work.
@graphite-app graphite-app bot force-pushed the 11-19-refactor_linter_plugins_remove_require_esm_ branch from 03bd005 to dd28d82 Compare November 19, 2025 11:08
@github-actions github-actions bot added the A-linter Area - Linter label Nov 19, 2025
@camc314
Copy link
Contributor

camc314 commented Nov 19, 2025

// `dist/cli.js`
function loadPluginWrapper(path, packageName) {
	return loadPlugin === null ? import("./plugins-fSGqXK1n.js").then((mod) => ({loadPlugin, lintFile} = mod, loadPlugin(path, packageName))) : loadPlugin(path, packageName);
}
$ ls -la dist
total 95552
cli.js
generated
index.d.ts
index.js
oxlint.darwin-arm64.node
plugins-fSGqXK1n.js

@graphite-app graphite-app bot merged commit dd28d82 into main Nov 19, 2025
18 checks passed
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Nov 19, 2025
@graphite-app graphite-app bot deleted the 11-19-refactor_linter_plugins_remove_require_esm_ branch November 19, 2025 11:13
@overlookmotel
Copy link
Member Author

$ ls -la dist
total 95552
cli.js
generated
index.d.ts
index.js
oxlint.darwin-arm64.node
plugins-fSGqXK1n.js

Note: *.node binary is not included in releases. It's only there in local dev.

@camc314
Copy link
Contributor

camc314 commented Nov 19, 2025

yep this was just a local sanity check to make sure we were going to be including everything that was needed in the published packages

graphite-app bot pushed a commit that referenced this pull request Nov 19, 2025
#15876)

Follow-on after #15866. Don't include hashes in filenames in `dist`. They're unnecessary and ugly, and Oxlint is not a front-end package, so hashes are not useful for caching.
taearls pushed a commit to taearls/oxc that referenced this pull request Dec 11, 2025
`loadPlugin` is already async, so we don't need to use `require(esm)` for lazy-loading the JS plugins-related code. Use `import` instead.

This has 3 advantages:

1. Removes the hacky workaround of a separate entry point for TSDown, and hard-coded path in `require('./plugins.js')`, which is only correct if TSDown config remains unchanged.
2. TypeScript can "see into" the `import` -> better type safety.
3. Support versions of NodeJS which don't support `require(esm)`.

On the last one, it's not strictly necessary, as `oxlint` requires a version of NodeJS with `require(esm)` support:

https://github.com/oxc-project/oxc/blob/b622ef87adf1bbed1e76ba0f610b653acb93e72b/apps/oxlint/package.json#L19-L21

But if user *is* on an older version of NodeJS, JS plugins should now work.
taearls pushed a commit to taearls/oxc that referenced this pull request Dec 11, 2025
oxc-project#15876)

Follow-on after oxc-project#15866. Don't include hashes in filenames in `dist`. They're unnecessary and ugly, and Oxlint is not a front-end package, so hashes are not useful for caching.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter A-linter-plugins Area - Linter JS plugins C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants