Skip to content

Dual ESM-CJS release #1722

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

Closed
wants to merge 9 commits into from
Closed

Dual ESM-CJS release #1722

wants to merge 9 commits into from

Conversation

alexeyr-ci2
Copy link
Collaborator

@alexeyr-ci2 alexeyr-ci2 commented Apr 3, 2025

Summary

Publish both ESM and CJS versions of the package.

Pull Request checklist

  • Add/update test to cover these changes
  • Update documentation
  • Update CHANGELOG file

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced build process that now delivers both ECMAScript (ESM) and CommonJS (CJS) module formats.
    • Added a configuration option to indicate support for both ESM and CJS versions in the CHANGELOG.
  • Refactor

    • Streamlined module resolution by enforcing explicit file extensions in imports, ensuring more consistent and predictable behavior.
  • Chores

    • Updated build and TypeScript configuration settings—including module targets and resolution strategies—for improved performance and compatibility.

Copy link
Contributor

coderabbitai bot commented Apr 3, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request applies multiple configuration updates across the repository. It removes an ignored linting rule option in the GitHub Actions workflow and adjusts ESLint rules. A new build script is added to orchestrate sequential build steps including cleaning, TypeScript compilation for both ESM and CommonJS, and generating corresponding package files. In addition, nearly all internal TypeScript files update their import and export paths to explicitly include the “.ts” extension. Other configuration files, including those for TypeScript and package management, are updated accordingly.

Changes

File(s) Change Summary
.github/workflows/lint-js-and-ruby.yml Removed the --ignore-rules cjs-only-exports-default option from the linting command.
eslint.config.ts Updated the import/extensions rule values from 'never' to 'ignorePackages'.
node_package/scripts/build Added a new build script that cleans, compiles, and creates package config files for both ESM and CommonJS outputs.
package-scripts.yml, package.json, tsconfig.json,
tsconfig.cjs.json
Updated build file paths, main entry, exports configuration, TypeScript version, and compiler options (module system, resolution strategy, output directories).
node_package/src/... (e.g. Authenticity.ts,
CallbackRegistry.ts, ClientSideRenderer.ts, ComponentRegistry.ts, RSCClientRoot.ts, ReactOnRails.client.ts, ReactOnRails.full.ts, ReactOnRails.node.ts, ReactOnRailsRSC.ts, StoreRegistry.ts, buildConsoleReplay.ts, clientStartup.ts, context.ts, createReactOutput.ts, handleError.ts, isRenderFunction.ts, isServerRenderResult.ts, pageLifecycle.ts, reactHydrateOrRender.ts, registerServerComponent/client.ts,
registerServerComponent/server.ts, serverRenderReactComponent.ts, serverRenderUtils.ts, streamServerRenderedReactComponent.ts,
transformRSCStreamAndReplayConsoleLogs.ts, turbolinksUtils.ts)
Consistently updated import/export statements to explicitly include the .ts file extension.

Sequence Diagram(s)

sequenceDiagram
    participant Build as Build Script
    participant Clean as Cleaning Task
    participant TS as TypeScript Compiler
    participant ESM as ESM Config Generator
    participant CJS as CJS Config Generator

    Build->>Clean: Run "yarn run clean"
    Clean-->>Build: Cleaning complete
    Build->>TS: Compile TS with declaration (first run)
    TS-->>Build: Declaration files generated
    Build->>ESM: Create package.json with {"type": "module"} in esm folder
    Build->>TS: Compile TS with tsconfig.cjs.json (second run)
    TS-->>Build: CommonJS files generated
    Build->>CJS: Create package.json with {"type": "commonjs"} in cjs folder
Loading

Possibly related PRs

Suggested reviewers

  • justin808
  • Judahmeek

Poem

I’m a rabbit, quick on my feet,
Hopping through code with rhythm so neat.
Imports now shine with a “.ts” gleam,
Build scripts dance in a sequential dream.
With each little change, my world is bright –
Coding carrots make everything right!
🥕🐇


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (8)
node_package/src/turbolinksUtils.ts (1)

16-19: Robust Window Check

The current check (if (!window) { ... }) assumes that referencing window is safe even in non-browser contexts. However, if this code ever runs in a server-side environment where window is undefined, the direct reference may throw a ReferenceError. Consider updating the check to use a safer pattern:

-  if (!window) {
-    return;
-  }
+  if (typeof window === 'undefined') {
+    return;
+  }
node_package/src/buildConsoleReplay.ts (1)

1-2: Explicit File Extensions in Imports
The updated import statements now explicitly reference RenderUtils.ts and scriptSanitizedVal.ts, ensuring consistency with the new configuration.
However, note that the pipeline failure indicates:

Cannot find module './RenderUtils.js'
This suggests that the build/test environment may be expecting a JavaScript file instead of a TypeScript file. Please verify that your build/transpilation process correctly converts these TypeScript modules into the expected JavaScript outputs and updates import paths accordingly.

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 1-1: Cannot find module './RenderUtils.js' from 'node_package/src/buildConsoleReplay.ts'.

node_package/src/registerServerComponent/client.ts (1)

1-3: Explicit File Extensions & Formatting Update Needed
The modifications to include the .ts extension are in line with the new TypeScript configuration. However, static analysis (Prettier) has flagged a formatting issue with the named import on line 3. Please reformat it as follows to comply with the style guidelines:

-import { RegisterServerComponentOptions, RailsContext, ReactComponentOrRenderFunction } from '../types/index.ts';
+import {
+  RegisterServerComponentOptions,
+  RailsContext,
+  ReactComponentOrRenderFunction,
+} from '../types/index.ts';

This adjustment will address the Prettier lint error.

🧰 Tools
🪛 ESLint

[error] 3-3: Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎

(prettier/prettier)

🪛 GitHub Check: build

[failure] 3-3:
Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎

🪛 GitHub Actions: Lint JS and Ruby

[error] 3-3: Prettier formatting check failed. Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎.

package-scripts.yml (1)

28-30: Update file paths consistently for ESM/CJS dual build

The script has been updated to check for the ESM build output, but for a dual ESM/CJS build, you should check both.

  script: >
-    [ -f node_package/lib/esm/ReactOnRails.full.js ] ||
+    ([ -f node_package/lib/esm/ReactOnRails.full.js ] && [ -f node_package/lib/cjs/ReactOnRails.full.js ]) ||
      (npm run build >/dev/null 2>&1 || true) &&
-      [ -f node_package/lib/esm/ReactOnRails.full.js ] ||
+      ([ -f node_package/lib/esm/ReactOnRails.full.js ] && [ -f node_package/lib/cjs/ReactOnRails.full.js ]) ||
      { echo 'Building react-on-rails seems to have failed!'; }

This ensures that both ESM and CJS builds are present before considering the build successful.

eslint.config.ts (1)

1-182: Add recommended configuration for dual ESM/CJS publishing

To properly support dual ESM/CJS publishing, consider adding rules that enforce package.json configuration best practices.

I recommend adding these checks to your ESLint configuration:

// Add to your imports at the top
+import eslintPluginN from 'eslint-plugin-n';

// Add to your rules section
+rules: {
+  // Enforce correct package.json configuration for dual ESM/CJS
+  'n/no-missing-import': 'off',
+  'n/no-unpublished-import': 'off',
+  'n/no-extraneous-import': 'off',
+  'n/exports-style': ['error', 'module.exports'],
+  'n/file-extension-in-import': ['error', 'never'],
+},

Also, make sure your package.json has the proper configuration for dual publishing:

{
  "main": "lib/cjs/index.js",
  "module": "lib/esm/index.js",
  "exports": {
    "import": "./lib/esm/index.js",
    "require": "./lib/cjs/index.js"
  },
  "type": "module"
}
node_package/scripts/build (1)

1-9: Well-structured build script for dual module support.

This script correctly implements the dual ESM-CJS build process by compiling TypeScript twice with different configurations and creating the necessary package.json files to mark module types.

Consider adding a file header comment explaining the purpose of this script and ensuring the script is executable with:

 #!/bin/sh
+
+# Build script for generating both ESM and CommonJS outputs
+# Usage: yarn run build

 set -e
node_package/src/ReactOnRails.client.ts (2)

2-10: Import Statements Updated to Include .ts Extensions
The changes on lines 2–10 update all import paths to explicitly include the .ts extension. This is in line with the dual ESM-CJS release objectives. However, note the pipeline failure indicating that './clientStartup.js' cannot be found. Please verify that your TypeScript compiler/transpiler configuration (especially the module and moduleResolution settings) correctly rewrites these extensions in the output files so that consumers end up with the proper .js paths in the built artifacts.

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 2-2: Cannot find module './clientStartup.js' from 'node_package/src/ReactOnRails.client.ts'.


[error] 2-2: Cannot find module './clientStartup.js' from 'node_package/src/ReactOnRails.client.ts'.


206-207: Export Statement Updated with Explicit Extension
The export on line 206 now references ./types/index.ts using the explicit extension. Ensure that the build process transforms these paths appropriately (e.g., to .js if needed) so that runtime module resolution works seamlessly in both ESM and CJS environments.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74dc30b and bbc73c7.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (33)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • eslint.config.ts (1 hunks)
  • node_package/scripts/build (1 hunks)
  • node_package/src/Authenticity.ts (1 hunks)
  • node_package/src/CallbackRegistry.ts (1 hunks)
  • node_package/src/ClientSideRenderer.ts (1 hunks)
  • node_package/src/ComponentRegistry.ts (1 hunks)
  • node_package/src/RSCClientRoot.ts (1 hunks)
  • node_package/src/ReactOnRails.client.ts (3 hunks)
  • node_package/src/ReactOnRails.full.ts (2 hunks)
  • node_package/src/ReactOnRails.node.ts (1 hunks)
  • node_package/src/ReactOnRailsRSC.ts (2 hunks)
  • node_package/src/StoreRegistry.ts (1 hunks)
  • node_package/src/buildConsoleReplay.ts (1 hunks)
  • node_package/src/clientStartup.ts (1 hunks)
  • node_package/src/context.ts (1 hunks)
  • node_package/src/createReactOutput.ts (1 hunks)
  • node_package/src/handleError.ts (1 hunks)
  • node_package/src/isRenderFunction.ts (1 hunks)
  • node_package/src/isServerRenderResult.ts (1 hunks)
  • node_package/src/pageLifecycle.ts (1 hunks)
  • node_package/src/reactHydrateOrRender.ts (1 hunks)
  • node_package/src/registerServerComponent/client.ts (1 hunks)
  • node_package/src/registerServerComponent/server.ts (1 hunks)
  • node_package/src/serverRenderReactComponent.ts (1 hunks)
  • node_package/src/serverRenderUtils.ts (1 hunks)
  • node_package/src/streamServerRenderedReactComponent.ts (1 hunks)
  • node_package/src/transformRSCStreamAndReplayConsoleLogs.ts (1 hunks)
  • node_package/src/turbolinksUtils.ts (1 hunks)
  • package-scripts.yml (1 hunks)
  • package.json (3 hunks)
  • tsconfig.cjs.json (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
node_package/src/buildConsoleReplay.ts (1)
Learnt from: alexeyr-ci
PR: shakacode/react_on_rails#1687
File: node_package/src/buildConsoleReplay.ts:12-12
Timestamp: 2025-04-02T19:31:07.890Z
Learning: When reviewing imports, carefully distinguish between default exports and named exports, as they represent different usage patterns. The presence of an import from a file doesn't necessarily mean all exported members are being used.
package-scripts.yml (1)
Learnt from: Romex91
PR: shakacode/react_on_rails#1697
File: package-scripts.yml:28-28
Timestamp: 2025-04-02T19:31:07.890Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.
node_package/src/ReactOnRails.client.ts (1)
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1644
File: node_package/src/clientStartup.ts:18-21
Timestamp: 2025-04-02T19:31:07.890Z
Learning: In the react_on_rails module, the `reactOnRailsPageUnloaded` function in clientStartup.ts is intentionally kept private as it's only used internally as a callback for `onPageUnloaded`.
🧬 Code Definitions (1)
node_package/src/ReactOnRails.node.ts (2)
node_package/src/types/index.ts (1)
  • ReactOnRails (182-246)
node_package/src/ReactOnRails.client.ts (1)
  • streamServerRenderedReactComponent (165-169)
🪛 ESLint
node_package/src/registerServerComponent/client.ts

[error] 3-3: Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎

(prettier/prettier)

🪛 GitHub Check: build
node_package/src/registerServerComponent/client.ts

[failure] 3-3:
Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎

🪛 GitHub Actions: Lint JS and Ruby
node_package/src/registerServerComponent/client.ts

[error] 3-3: Prettier formatting check failed. Replace ·RegisterServerComponentOptions,·RailsContext,·ReactComponentOrRenderFunction· with ⏎··RegisterServerComponentOptions,⏎··RailsContext,⏎··ReactComponentOrRenderFunction,⏎.

🪛 Biome (1.9.4)
tsconfig.cjs.json

[error] 7-7: Expected a property but instead found '}'.

Expected a property here.

(parse)


[error] 7-8: Expected a property but instead found '}'.

Expected a property here.

(parse)

🪛 GitHub Actions: JS unit tests for Renderer package
node_package/src/buildConsoleReplay.ts

[error] 1-1: Cannot find module './RenderUtils.js' from 'node_package/src/buildConsoleReplay.ts'.

node_package/src/RSCClientRoot.ts

[error] 6-6: Cannot find module './utils.js' from 'node_package/src/RSCClientRoot.ts'.

node_package/src/ComponentRegistry.ts

[error] 2-2: Cannot find module './isRenderFunction.js' from 'node_package/src/ComponentRegistry.ts'.

node_package/src/CallbackRegistry.ts

[error] 2-2: Cannot find module './pageLifecycle.js' from 'node_package/src/CallbackRegistry.ts'.

node_package/src/streamServerRenderedReactComponent.ts

[error] 5-5: Cannot find module './ComponentRegistry.js' from 'node_package/src/streamServerRenderedReactComponent.ts'.

node_package/src/serverRenderReactComponent.ts

[error] 4-4: Cannot find module './ComponentRegistry.js' from 'node_package/src/serverRenderReactComponent.ts'.

node_package/src/ReactOnRails.client.ts

[error] 2-2: Cannot find module './clientStartup.js' from 'node_package/src/ReactOnRails.client.ts'.


[error] 2-2: Cannot find module './clientStartup.js' from 'node_package/src/ReactOnRails.client.ts'.

🔇 Additional comments (39)
node_package/src/isRenderFunction.ts (1)

3-3: Explicit File Extension in Import Statement
The import now explicitly includes the .ts extension, ensuring consistency with the module resolution needed for dual ESM/CJS support. This change aligns well with similar updates across the codebase.

node_package/src/context.ts (1)

1-1: Explicit Import Path Improves Module Resolution

The updated import statement now explicitly references ./types/index.ts instead of a generic ./types. This clarity is especially beneficial in a dual ESM/CJS environment as it helps the TypeScript compiler resolve the module paths unambiguously. It also aligns well with similar updates across the codebase.

node_package/src/serverRenderUtils.ts (1)

1-1: Explicit File Extension in Import Statement

The updated import statement now explicitly references ./types/index.ts, which aligns with the dual ESM-CJS release requirements and ensures consistent module resolution. This change is clear and appropriate.

node_package/src/turbolinksUtils.ts (3)

1-1: Explicit Import Extension Update

The import statement now explicitly includes the .ts extension (./context.ts), ensuring clarity in module resolution for dual ESM/CJS environments. Please verify that the bundler and runtime configurations (both ESM and CJS) are adjusted accordingly so that the explicit extension does not cause runtime resolution issues.


21-25: Context Usage in Debug Function

The use of reactOnRailsContext() to access configuration options inside debugTurbolinks is clear and consistent. No changes are needed here, but please ensure that this context function is reliably available in all environments where this module might be used.


27-46: General Code Review

The remaining functions (turbolinksInstalled, turboInstalled, turbolinksVersion5, and turbolinksSupported) are straightforward and correctly implement their intended checks. Ensure that the global Turbolinks object and its related properties are defined in all deployment contexts, especially under dual module systems.

node_package/src/clientStartup.ts (4)

1-1: Explicit File Extension for Context Module Import
The import now explicitly includes the .ts extension for the context module. This aligns with the dual ESM/CJS release strategy by ensuring accurate module resolution.


2-8: Explicit File Extension for ClientSideRenderer Import
The import statement for ClientSideRenderer has been updated to include .ts, which promotes consistent module resolution across environments. This explicit approach can help prevent potential runtime issues in ESM contexts.


9-9: Consistent Import for pageLifecycle Module
The onPageLoaded and onPageUnloaded functions are now imported from ./pageLifecycle.ts. This change is consistent with the overall update and prevents any resolution ambiguities.


10-10: Consistent Import for turbolinksUtils Module
Similarly, the import for debugTurbolinks now includes the .ts extension. This helps maintain uniformity and correct resolution in different module systems.

node_package/src/isServerRenderResult.ts (1)

1-1: Explicit File Extension in Import Statement
The updated import now includes the .ts extension ('./types/index.ts'), ensuring consistent module resolution which is especially important for the dual ESM-CJS release strategy.

node_package/src/StoreRegistry.ts (1)

2-2: Consistent Import Path Update
The change from importing types from './types' to './types/index.ts' aligns with the overall project update. This explicit file extension improves clarity for module resolution without affecting functionality.

node_package/src/Authenticity.ts (1)

1-1: Updated Import with Explicit Extension
The import for AuthenticityHeaders now explicitly includes the .ts extension, which enhances consistency with other files in the codebase. This minor change aids in correct and predictable module resolution.

node_package/src/handleError.ts (1)

3-3: Clarified Import Path for ErrorOptions
Changing the import to use './types/index.ts' ensures that the file extension is explicitly set, thereby improving consistency and preventing potential resolution issues in a dual module system.

node_package/src/transformRSCStreamAndReplayConsoleLogs.ts (1)

1-1: Standardized Import Path for RenderResult
The update to explicitly include the .ts extension in the import path improves clarity and aligns with the broader codebase update. This adjustment is particularly beneficial for environments that require explicit module extensions.

node_package/src/pageLifecycle.ts (1)

7-7: Explicit Module Extension Update
The import now explicitly includes the .ts extension (i.e. ./turbolinksUtils.ts), which aligns with the updated TypeScript configuration and ensures clearer module resolution.

node_package/src/reactHydrateOrRender.ts (1)

3-4: Consistent Import Path Clarification
Including the .ts extension in the import paths for both ./types/index.ts and ./reactApis.ts is consistent with the project's updated module resolution strategy.

node_package/src/registerServerComponent/server.ts (1)

1-2: Consistent Explicit Import Extensions
The import updates to include .ts (for both ReactOnRails.client.ts and ../types/index.ts) are clear and maintain consistency across the codebase. No functional issues were introduced with these changes.

node_package/src/createReactOutput.ts (1)

8-9: Ensure Consistent Module Resolution with Explicit Extensions
The import statements on lines 8–9 now explicitly include the .ts extension. This change is consistent with the new module resolution approach across the codebase. Please verify that your TypeScript compiler and bundler/test configurations (e.g., tsconfig paths, module resolvers, or Jest configuration) support explicit .ts references to avoid potential runtime or testing issues.
[request_verification, suggest_nitpick]

node_package/src/RSCClientRoot.ts (1)

6-8: Verify Module Resolution for Updated Imports
The import statements on lines 6–8 now reference ./utils.ts, ./transformRSCStreamAndReplayConsoleLogs.ts, and ./types/index.ts explicitly. However, the pipeline failure indicates an error: "Cannot find module './utils.js'" which suggests that some tooling or test configuration is still expecting a .js extension. Please verify and adjust your build/test configuration (for example, updating moduleFileExtensions or path mappings in your test runner) to ensure that these explicit .ts imports are resolved correctly at runtime and during tests.
[request_verification, offer_assistance]

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 6-6: Cannot find module './utils.js' from 'node_package/src/RSCClientRoot.ts'.

node_package/src/ComponentRegistry.ts (1)

1-3: Confirm Resolution for Updated TypeScript Imports
The modified imports on lines 1–3 now include the .ts extension (e.g., ./types/index.ts, ./isRenderFunction.ts, and ./CallbackRegistry.ts). Note that the pipeline error ("Cannot find module './isRenderFunction.js'") indicates that some processes might still be looking for JavaScript files. It’s important to update your bundler or test configuration accordingly so that imports with explicit extensions are handled properly.
[request_verification, offer_assistance]

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 2-2: Cannot find module './isRenderFunction.js' from 'node_package/src/ComponentRegistry.ts'.

node_package/src/CallbackRegistry.ts (1)

1-3: Review Import Resolution Settings for Page Lifecycle Module
The import statements on lines 1–3 have been updated to include .ts extensions (for example, ./types/index.ts, ./pageLifecycle.ts, and ./context.ts). However, the pipeline failure—"Cannot find module './pageLifecycle.js'"—suggests that your test or runtime environment might still expect a .js file. Please verify your module resolution settings and update them to account for these explicit .ts paths, or adjust the imports if necessary.
[request_verification, offer_assistance]

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 2-2: Cannot find module './pageLifecycle.js' from 'node_package/src/CallbackRegistry.ts'.

node_package/src/ClientSideRenderer.ts (1)

6-13: Consistent Update of Import Extensions; Confirm Downstream Compatibility
The import updates on lines 6–13 now explicitly include .ts extensions across several modules (e.g., ./types/index.ts, ./context.ts, ./createReactOutput.ts, ./isServerRenderResult.ts, ./reactHydrateOrRender.ts, ./reactApis.ts, and ./turbolinksUtils.ts). This change enhances clarity and consistency in module resolution. However, ensure that your build and runtime environments (including test runners) are configured to correctly resolve these explicit .ts imports in place of the compiled .js versions.
[request_verification, suggest_nitpick]

.github/workflows/lint-js-and-ruby.yml (1)

93-93: Properly removing CJS-specific lint rule exception.

The removal of --ignore-rules cjs-only-exports-default suggests that with the dual ESM-CJS implementation, the package now properly handles CommonJS default exports and no longer needs this exception. This change aligns well with the PR objective.

tsconfig.json (1)

9-17: TypeScript configuration properly updated for dual module support.

The changes to tsconfig.json correctly configure TypeScript for ESM output:

  1. Changing to module: "es2020" and target: "es2020" modernizes the JavaScript output
  2. Adding moduleResolution: "bundler" improves compatibility with modern bundlers
  3. The new settings for TypeScript extensions (allowImportingTsExtensions and rewriteRelativeImportExtensions) properly support the explicit .ts extension imports
  4. The output directory is now specifically for ESM files

These changes work in conjunction with the separate tsconfig.cjs.json to enable the dual module format.

node_package/src/ReactOnRails.full.ts (2)

1-5: Import statements correctly updated with .ts extensions.

The explicit .ts extensions in import statements work with the new TypeScript configuration options (allowImportingTsExtensions and rewriteRelativeImportExtensions) to enable proper module resolution and transformation for dual ESM/CJS support.


18-18: Export statement correctly updated with .ts extension.

The explicit .ts extension in the export statement ensures consistency with the import statements and proper module resolution.

node_package/src/ReactOnRailsRSC.ts (3)

5-9: Import Statements Updated to Explicit .ts Extensions
The updates on lines 5–9 explicitly add the .ts extension to the imported modules. This change improves the clarity of module resolution in an ESM context and is consistent with the overall dual ESM-CJS strategy.


14-15: Stream Module Imports Now Use Explicit Extensions
The imports on lines 14–15 for streamServerRenderedReactComponent and loadReactClientManifest have been updated to include the .ts extension. This aligns with the updated module resolution and enforces consistency across the codebase.


68-68: Updated Re-Export for Types
The export on line 68 now explicitly references ./types/index.ts, ensuring that type exports are clear and unambiguous when consumed by downstream modules.

node_package/src/ReactOnRails.node.ts (3)

1-2: Imports Updated with Explicit .ts Extensions
The import statements on lines 1–2 now include the .ts extension, which is necessary for proper resolution under the dual ESM-CJS release strategy.


6-6: Re-Export Now Reflects TypeScript File Extensions
The export on line 6 has been updated to use the .ts extension for ReactOnRails.full.ts, ensuring consistency with the updated import paths.


8-8: Default Export Updated with Explicit Extension
The default export on line 8 now includes the .ts extension for ReactOnRails.full.ts, maintaining alignment with the project's new module referencing strategy.

package.json (6)

5-5: Main Entry Point Updated for ESM Build
The main field on line 5 is now set to node_package/lib/esm/ReactOnRails.full.js, which correctly reflects the shift toward ECMAScript modules. Confirm that the dual build process produces both ESM and CJS outputs as expected.


8-21: Exports Structure Refined for Dual Module Support
Lines 8–21 show a nested object structure in the exports field that differentiates between import and require paths for react-server, node, and default exports. This clear separation supports both module systems and enhances compatibility.


22-25: Client Export Configuration Updated
The "./client" export now specifies separate paths for ESM (import) and CJS (require) builds, which is essential for maintaining cross-environment compatibility.


26-33: Register Server Component Exports Now Support Dual Formats
The changes on lines 26–33 update the exports for ./registerServerComponent/client and ./registerServerComponent/server to include both import and require paths. This ensures that consumers can correctly load these components regardless of their module system.


79-79: TypeScript Version Bumped to ^5.8.2
The TypeScript dependency on line 79 has been updated to ^5.8.2. Please verify that this version is compatible with your build tools and that no new type errors are introduced.


96-97: Build Scripts Updated to Support Custom Build Process
The build script now delegates to node_package/scripts/build, and the build-watch script has been updated with the --no-declaration flag. These changes should streamline the build process for both module formats. Make sure the new script handles cleaning, compilation, and file generation correctly in both ESM and CJS outputs.

Comment on lines +4 to +9
import ComponentRegistry from './ComponentRegistry.ts';
import createReactOutput from './createReactOutput.ts';
import { isPromise, isServerRenderHash } from './isServerRenderResult.ts';
import buildConsoleReplay from './buildConsoleReplay.ts';
import handleError from './handleError.ts';
import { createResultObject, convertToError, validateComponent } from './serverRenderUtils.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix import paths to work with both ESM and CJS builds

The current approach of using explicit .ts extensions in imports causes build failures. The TypeScript compiler is trying to resolve these as .js files after compilation (as seen in the pipeline error).

The correct approach for dual ESM/CJS builds is to:

  1. Remove the file extensions from imports
  2. Configure TypeScript properly in tsconfig files
-import ComponentRegistry from './ComponentRegistry.ts';
-import createReactOutput from './createReactOutput.ts';
-import { isPromise, isServerRenderHash } from './isServerRenderResult.ts';
-import buildConsoleReplay from './buildConsoleReplay.ts';
-import handleError from './handleError.ts';
-import { createResultObject, convertToError, validateComponent } from './serverRenderUtils.ts';
+import ComponentRegistry from './ComponentRegistry';
+import createReactOutput from './createReactOutput';
+import { isPromise, isServerRenderHash } from './isServerRenderResult';
+import buildConsoleReplay from './buildConsoleReplay';
+import handleError from './handleError';
+import { createResultObject, convertToError, validateComponent } from './serverRenderUtils';

And for the types import:

-} from './types/index.ts';
+} from './types';

Also applies to: 17-17

🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 4-4: Cannot find module './ComponentRegistry.js' from 'node_package/src/serverRenderReactComponent.ts'.

Comment on lines 5 to 11
import ComponentRegistry from './ComponentRegistry.ts';
import createReactOutput from './createReactOutput.ts';
import { isPromise, isServerRenderHash } from './isServerRenderResult.ts';
import buildConsoleReplay from './buildConsoleReplay.ts';
import handleError from './handleError.ts';
import { createResultObject, convertToError, validateComponent } from './serverRenderUtils.ts';
import type { RenderParams, StreamRenderState } from './types/index.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix import paths to work with both ESM and CJS builds

Similar to the previous file, these explicit .ts extensions in imports are causing build failures. The same solution needs to be applied here.

-import ComponentRegistry from './ComponentRegistry.ts';
-import createReactOutput from './createReactOutput.ts';
-import { isPromise, isServerRenderHash } from './isServerRenderResult.ts';
-import buildConsoleReplay from './buildConsoleReplay.ts';
-import handleError from './handleError.ts';
-import { createResultObject, convertToError, validateComponent } from './serverRenderUtils.ts';
-import type { RenderParams, StreamRenderState } from './types/index.ts';
+import ComponentRegistry from './ComponentRegistry';
+import createReactOutput from './createReactOutput';
+import { isPromise, isServerRenderHash } from './isServerRenderResult';
+import buildConsoleReplay from './buildConsoleReplay';
+import handleError from './handleError';
+import { createResultObject, convertToError, validateComponent } from './serverRenderUtils';
+import type { RenderParams, StreamRenderState } from './types';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import ComponentRegistry from './ComponentRegistry.ts';
import createReactOutput from './createReactOutput.ts';
import { isPromise, isServerRenderHash } from './isServerRenderResult.ts';
import buildConsoleReplay from './buildConsoleReplay.ts';
import handleError from './handleError.ts';
import { createResultObject, convertToError, validateComponent } from './serverRenderUtils.ts';
import type { RenderParams, StreamRenderState } from './types/index.ts';
import ComponentRegistry from './ComponentRegistry';
import createReactOutput from './createReactOutput';
import { isPromise, isServerRenderHash } from './isServerRenderResult';
import buildConsoleReplay from './buildConsoleReplay';
import handleError from './handleError';
import { createResultObject, convertToError, validateComponent } from './serverRenderUtils';
import type { RenderParams, StreamRenderState } from './types';
🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 5-5: Cannot find module './ComponentRegistry.js' from 'node_package/src/streamServerRenderedReactComponent.ts'.

Comment on lines 1 to 8
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16",
"outDir": "node_package/lib/cjs",
},
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix JSON syntax error and add necessary configuration for dual ESM/CJS support

There's a trailing comma after the outDir property that should be removed according to static analysis.

Additionally, some configuration options are missing that are essential for dual ESM/CJS builds.

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "node16",
    "moduleResolution": "node16",
-    "outDir": "node_package/lib/cjs",
+    "outDir": "node_package/lib/cjs"
  },
}

You should also consider adding these properties to properly handle the dual module format:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "node16",
    "moduleResolution": "node16",
    "outDir": "node_package/lib/cjs",
+    "declaration": true,
+    "esModuleInterop": true,
+    "preserveConstEnums": true
  }
}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 7-7: Expected a property but instead found '}'.

Expected a property here.

(parse)


[error] 7-8: Expected a property but instead found '}'.

Expected a property here.

(parse)

eslint.config.ts Outdated
Comment on lines 94 to 96
js: 'ignorePackages',
jsx: 'ignorePackages',
ts: 'ignorePackages',
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix ESLint import/extensions configuration for dual ESM/CJS builds

The current configuration doesn't match the standard pattern for dual builds. Using 'ignorePackages' will still enforce extensions for relative imports, which contradicts how TypeScript should handle imports for proper compilation.

  'import/extensions': [
    'error',
    'ignorePackages',
    {
-      js: 'ignorePackages',
-      jsx: 'ignorePackages',
-      ts: 'ignorePackages',
+      js: 'never',
+      jsx: 'never',
+      ts: 'never'
    },
  ],

This configuration tells ESLint to enforce no extensions on imports for these file types, which is the recommended approach for TypeScript projects that need to support both ESM and CJS.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
js: 'ignorePackages',
jsx: 'ignorePackages',
ts: 'ignorePackages',
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never'
},
],

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
docs/release-notes/15.0.0.md (1)

33-40: New “ESM Support” Section in Release Notes
The added section clearly outlines the dual module publication (ESM and CommonJS) and provides good guidance on future improvements and a recommendation for users still employing require.

  • Stylistic Suggestion: At the beginning of the second sentence (“In most cases you don't need to do anything to take advantage of that,”), consider inserting a comma after “In most cases” to improve readability (i.e. “In most cases, you don't need to…”).
🧰 Tools
🪛 LanguageTool

[formatting] ~36-~36: Insert a comma after ‘cases’: “In most cases,”?
Context: ...re tree-shakable to reduce bundle size. In most cases you don't need to do anything to take a...

(IN_MOST_CASES_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbc73c7 and 89d3c4c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (33)
  • .github/workflows/lint-js-and-ruby.yml (1 hunks)
  • CHANGELOG.md (1 hunks)
  • docs/release-notes/15.0.0.md (1 hunks)
  • eslint.config.ts (1 hunks)
  • node_package/src/Authenticity.ts (1 hunks)
  • node_package/src/CallbackRegistry.ts (1 hunks)
  • node_package/src/ClientSideRenderer.ts (1 hunks)
  • node_package/src/ComponentRegistry.ts (1 hunks)
  • node_package/src/RSCClientRoot.ts (1 hunks)
  • node_package/src/ReactOnRails.client.ts (3 hunks)
  • node_package/src/ReactOnRails.full.ts (2 hunks)
  • node_package/src/ReactOnRails.node.ts (1 hunks)
  • node_package/src/ReactOnRailsRSC.ts (2 hunks)
  • node_package/src/StoreRegistry.ts (1 hunks)
  • node_package/src/buildConsoleReplay.ts (1 hunks)
  • node_package/src/clientStartup.ts (1 hunks)
  • node_package/src/context.ts (1 hunks)
  • node_package/src/createReactOutput.ts (1 hunks)
  • node_package/src/handleError.ts (1 hunks)
  • node_package/src/isRenderFunction.ts (1 hunks)
  • node_package/src/isServerRenderResult.ts (1 hunks)
  • node_package/src/loadReactClientManifest.cts (1 hunks)
  • node_package/src/pageLifecycle.ts (1 hunks)
  • node_package/src/reactHydrateOrRender.ts (1 hunks)
  • node_package/src/registerServerComponent/client.ts (1 hunks)
  • node_package/src/registerServerComponent/server.ts (1 hunks)
  • node_package/src/serverRenderReactComponent.ts (1 hunks)
  • node_package/src/serverRenderUtils.ts (1 hunks)
  • node_package/src/streamServerRenderedReactComponent.ts (1 hunks)
  • node_package/src/transformRSCStreamAndReplayConsoleLogs.ts (1 hunks)
  • node_package/src/turbolinksUtils.ts (1 hunks)
  • package.json (3 hunks)
  • tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • node_package/src/loadReactClientManifest.cts
🚧 Files skipped from review as they are similar to previous changes (30)
  • node_package/src/handleError.ts
  • node_package/src/serverRenderUtils.ts
  • node_package/src/buildConsoleReplay.ts
  • node_package/src/pageLifecycle.ts
  • node_package/src/StoreRegistry.ts
  • node_package/src/context.ts
  • node_package/src/isServerRenderResult.ts
  • node_package/src/isRenderFunction.ts
  • node_package/src/turbolinksUtils.ts
  • node_package/src/registerServerComponent/server.ts
  • node_package/src/reactHydrateOrRender.ts
  • node_package/src/registerServerComponent/client.ts
  • node_package/src/Authenticity.ts
  • tsconfig.json
  • node_package/src/createReactOutput.ts
  • node_package/src/RSCClientRoot.ts
  • .github/workflows/lint-js-and-ruby.yml
  • node_package/src/ClientSideRenderer.ts
  • node_package/src/CallbackRegistry.ts
  • node_package/src/transformRSCStreamAndReplayConsoleLogs.ts
  • node_package/src/ReactOnRailsRSC.ts
  • node_package/src/ComponentRegistry.ts
  • eslint.config.ts
  • node_package/src/streamServerRenderedReactComponent.ts
  • node_package/src/ReactOnRails.node.ts
  • node_package/src/ReactOnRails.full.ts
  • node_package/src/serverRenderReactComponent.ts
  • node_package/src/ReactOnRails.client.ts
  • node_package/src/clientStartup.ts
  • package.json
🧰 Additional context used
🪛 LanguageTool
docs/release-notes/15.0.0.md

[formatting] ~36-~36: Insert a comma after ‘cases’: “In most cases,”?
Context: ...re tree-shakable to reduce bundle size. In most cases you don't need to do anything to take a...

(IN_MOST_CASES_COMMA)

🔇 Additional comments (1)
CHANGELOG.md (1)

29-29: ESM/CJS Dual Format Entry Added
The new bullet point documenting that “The package now includes both ESM and CJS versions” correctly reflects the dual-release objective. Please double-check that this entry aligns with the updated module export settings in the package configuration.

@alexeyr-ci2 alexeyr-ci2 marked this pull request as draft April 3, 2025 08:49
@alexeyr-ci alexeyr-ci force-pushed the alexeyr/cjs-esm branch 2 times, most recently from 2908e1f to d75d4d5 Compare April 3, 2025 09:03
@alexeyr-ci alexeyr-ci force-pushed the alexeyr/cjs-esm branch 4 times, most recently from 01ed2c2 to bdf3492 Compare April 3, 2025 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants