-
-
Notifications
You must be signed in to change notification settings - Fork 501
Convert to ESM #3860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert to ESM #3860
Conversation
There was a problem hiding this 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 converts the Prettier VS Code extension from CommonJS to ECMAScript Modules (ESM), enabling modern JavaScript module support and improving compatibility with Prettier v3+. The conversion involves significant architectural changes while maintaining backward compatibility with Prettier v2.
Key Changes
- Module System: Converted to pure ESM with
"type": "module"in package.json, requiring.jsextensions on all imports - Dynamic Loading: Replaced worker thread-based Prettier loading with native ESM
import()for both Prettier and plugins - Build Configuration: Desktop extension outputs as ESM (
.js), browser extension as CJS (.cjs), and tests as bundled CJS (.cjs)
Reviewed changes
Copilot reviewed 47 out of 49 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
package.json |
Added "type": "module", updated entry points, removed find-up and resolve dependencies |
package-lock.json |
Contains outdated dependencies that need regeneration |
tsconfig.json / tsconfig.test.json |
Updated to ESM with module: "ESNext" and moduleResolution: "bundler" |
esbuild.mjs |
Configured ESM output for desktop, CJS for browser/tests, added Node.js built-in externals |
src/ModuleResolver.ts |
Complete refactor: removed find-up/resolve deps, added async module resolution with findUp utility |
src/PrettierDynamicInstance.ts |
New unified loader using dynamic import() for both ESM and CJS Prettier modules |
src/PrettierEditService.ts |
New loadPlugins() function to load plugins via dynamic import with pathToFileURL |
src/utils/find-up.ts |
New async utility replacing find-up package |
src/utils/exec.ts |
New async utility for executing shell commands with proper timeout handling |
src/utils/resolve-module-entry.ts |
New utility to resolve package.json entry points for ESM compatibility |
src/utils/global-node-paths.ts |
Converted to async, added pnpm support, uses new execAsync utility |
src/utils/resolvers.ts |
Removed loadNodeModule(), updated resolveNodeModule() to use createRequire() |
src/test/**/*.test.ts |
Updated imports to use .js extensions and assert module (not node:assert) |
test-fixtures/config/**/*.js |
Converted Prettier config files from module.exports to export default |
.vscode/launch.json |
Updated test configuration to use new test setup |
.vscode-test.mjs |
Updated to look for .cjs test files |
Comments suppressed due to low confidence (1)
src/utils/resolvers.ts:44
- The
resolveConfigPluginsfunction is exported but is no longer used anywhere in the codebase. Plugin resolution is now handled directly inPrettierEditService.loadPlugins()via dynamic imports. Consider removing this function, or if it's intended for future use or external API, add a comment explaining why it's kept.
7d800f8 to
7b94270
Compare
This PR converts the extension from CommonJS to ESM modules and improves how Prettier is loaded and resolved. Key changes: **ESM Conversion** - Convert all source files to use ESM imports/exports - Update esbuild configuration for ESM output - Add .js extensions to all relative imports - Update tsconfig for ESM module resolution **Prettier Module Loading** - Lazy-load bundled Prettier using dynamic import() for faster activation - Remove worker thread implementation (PrettierWorkerInstance) - now use PrettierDynamicInstance which loads Prettier dynamically - Improve plugin loading to resolve and import plugins as ES modules - Add utility functions for finding modules (find-up, resolve-module-entry) **Extension Activation** - Make activate() async and await formatter registration - Ensures formatters are ready when extension.isActive becomes true - Fixes race condition where tests could run before formatters registered **Test Infrastructure** - Add ensureExtensionActivated() helper for reliable test setup - Extract common format test utilities to formatTestUtils.ts - Update test imports for ESM compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Tests loading plugins via ESM import in prettier.config.mts files, which is a new feature in Prettier 3.5.0+. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
src/PrettierEditService.ts
Outdated
|
|
||
| if (pluginPath) { | ||
| try { | ||
| // Resolve to actual entry file since ESM doesn't support directory imports |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we try both import and require? require still avaiable in ESM.
Just to be clear, directory import is for v2, right? Since Prettier 3 already dropped support for it.
fisker
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know much about vscode extensions, but the code looks good to me.
Replace manual package.json parsing with createRequire().resolve() which handles all the complexity of exports, main fields, and fallbacks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Rename ModuleResolver.ts → ModuleResolverNode.ts (desktop) - Rename BrowserModuleResolver.ts → ModuleResolverWeb.ts (browser) - Keep class export name as ModuleResolver for simplicity - Update esbuild browser alias plugin for new file names - Update documentation to reflect new file naming convention 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Create the require function from within the target module's directory so Node's resolution works correctly for local Prettier installations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Fix scoped package resolution in resolveModuleEntry (e.g., @prettier/plugin-xml) - Simplify plugin loading to just resolve paths and let Prettier import them - Update browser languages script to dynamically get plugin list from prettier exports 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Handle URLs, absolute paths, relative paths, and package names - Use createRequire to resolve packages from file's directory - Remove unused findUp import 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Use require.resolve with createRequire from target directory - Only convert plugin paths to file:// URLs for Prettier v3+ - For Prettier v2, pass absolute paths that require() can handle 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Uh oh!
There was an error while loading. Please reload this page.