Skip to content
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

Reduce bundle size #1697

Merged
merged 14 commits into from
Mar 1, 2025
Merged

Reduce bundle size #1697

merged 14 commits into from
Mar 1, 2025

Conversation

Romex91
Copy link
Contributor

@Romex91 Romex91 commented Feb 12, 2025

Summary

This PR reduces bundle size by doing two things:

  • Migrate from CJS to ESM for more compact modules (~1KB improvement)
  • Add export 'react-on-rails/client' to avoid shipping React server-rendering to browsers (~14KB improvement).

Pull Request checklist

  • Add/update test to cover these changes
    - [ ] Update documentation Should be added here?
  • Update CHANGELOG file
    Add the CHANGELOG entry at the top of the file.

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated client export that delivers a leaner browser bundle by omitting server-only code.
    • Added a server-specific module variant that supports full server-side rendering capabilities.
  • Chores

    • Updated build configurations, module paths, and TypeScript settings to leverage modern JavaScript standards.
    • Streamlined test imports and project metadata, ensuring alignment with the new module structure.
    • Added .vscode/ directory to the .gitignore file.
  • Documentation

    • Revised the changelog and contribution guidelines to reflect these updates.

Copy link
Contributor

coderabbitai bot commented Feb 12, 2025

Walkthrough

This pull request enforces a stricter separation between client-side and server-side functionalities in the ReactOnRails library. It updates method signatures in the client module to throw errors if used in the wrong context, adjusts imports and exports across multiple files to reference the new full version of the module, and revises configuration and testing details. Documentation and build scripts are updated accordingly.

Changes

Files Change Summary
node_package/src/ReactOnRails.client.ts
node_package/src/ReactOnRails.full.ts
In the client module, unused imports have been removed and method signatures (serverRenderReactComponent, handleError) updated to throw errors in a client context; a new file (ReactOnRails.full.ts) adds the full server-side functionality.
node_package/src/ReactOnRails.node.ts
package-scripts.yml
Changed import/export references from ReactOnRails to ReactOnRails.full and updated file existence checks accordingly.
package.json Modified the default export from ReactOnRails.js to ReactOnRails.full.js and added a new export "./client": "./node_package/lib/ReactOnRails.client.js".
tsconfig.json Added compiler options: lib set to ["dom", "es2020"], module as "node16", and target as "es2020".
CHANGELOG.md Added an entry under "Added" to note the new client export (react-on-rails/client) and its size improvement.
node_package/tests/Authenticity.test.js
spec/dummy/client/app/packs/client-bundle.js
Updated import paths to reference ReactOnRails.client from their previous generic or main module paths.
.gitignore Added the .vscode/ directory to the list of ignored files.
CONTRIBUTING.md Updated the test command to use rake shakapacker_examples:gen_all instead of examples:gen_all.

Sequence Diagram(s)

sequenceDiagram
    participant CC as Client Code
    participant RCR as ReactOnRails.client
    CC->>RCR: Call serverRenderReactComponent()
    RCR-->>CC: Throw error ("Not available in client. Import server-side.")
Loading
sequenceDiagram
    participant SA as Server App
    participant RRF as ReactOnRails.full
    SA->>RRF: Call serverRenderReactComponent(options)
    RRF-->>SA: Process rendering and return result
Loading

Possibly related PRs

Suggested reviewers

  • alexeyr-ci

Poem

In code meadows I happily bound,
Hopping through changes with a joyful sound,
No more server calls on the client trail,
Errors now guide, never to fail,
With exports aligned and tests set right,
I nibble on bugs ‘til they’re out of sight,
A rabbit’s cheer in every byte!


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 207407b and 29889db.

📒 Files selected for processing (1)
  • node_package/tests/ReactOnRails.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • node_package/tests/ReactOnRails.test.js
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: dummy-app-integration-tests (newest)
  • GitHub Check: dummy-app-integration-tests (oldest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: rspec-package-tests (oldest)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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: 0

🧹 Nitpick comments (1)
package.json (1)

5-11: Consider adding "type": "module" for ESM support.

To fully migrate to ESM as mentioned in the PR objectives, consider adding the "type": "module" field to package.json. This ensures Node.js treats .js files as ES modules by default.

{
  "name": "react-on-rails",
+ "type": "module",
  "version": "14.1.1",
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 923525d and 54a9286.

📒 Files selected for processing (5)
  • node_package/src/ReactOnRails.client.ts (2 hunks)
  • node_package/src/ReactOnRails.node.ts (1 hunks)
  • node_package/src/ReactOnRails.server.ts (1 hunks)
  • package.json (1 hunks)
  • tsconfig.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (newest)
  • GitHub Check: examples (newest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (oldest)
  • GitHub Check: examples (oldest)
  • GitHub Check: build
🔇 Additional comments (6)
node_package/src/ReactOnRails.node.ts (1)

1-1: LGTM! Clean separation of server and client exports.

The changes correctly implement the export splitting strategy by importing and re-exporting the server implementation.

Also applies to: 6-7

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

11-13: LGTM! Effective runtime check to prevent browser usage.

The runtime check ensures that server-side code is not accidentally included in browser bundles, which aligns with the PR's goal of reducing bundle size.

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

242-244: LGTM! Clear error messages for server-side methods.

The implementation properly enforces the server/client split by throwing descriptive errors when server-side methods are called from the client bundle.

Also applies to: 258-260

tsconfig.json (1)

7-7: Verify TypeScript configuration for ESM compatibility.

The TypeScript configuration changes support ESM:

  • "module": "Preserve" maintains ESM syntax
  • "target": "es2015" enables modern JS features

Let's verify these settings are optimal for ESM:

Also applies to: 12-12

❌ Verification inconclusive

🌐 Web query:

What is the recommended TypeScript configuration for ESM modules?

💡 Result:

To configure TypeScript for native ESM modules in Node.js, follow these key recommendations based on industry standards and official documentation:

Core Configuration

  1. Set "type": "module" in package.json to enable native ESM support[1][2][6]
  2. Configure tsconfig.json with:
{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "target": "ES2020",
    "outDir": "./dist",
    "esModuleInterop": true,
    "strict": true
  }
}

[1][5][6][10]

Essential Requirements

  • File extensions: Always include .js extensions in imports:
    import { util } from './utils.js'; // GOOD[1][3][6]
  • Avoid CommonJS patterns: Replace require() with import/export syntax[1][3]

Advanced Settings

For modern Node.js (v20+):

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "extends": ["@tsconfig/node20/tsconfig.json"]
}

[1][6]

For tooling compatibility:

{
  "compilerOptions": {
    // Enable these if using mixed CJS/ESM dependencies
    "allowSyntheticDefaultImports": true,
    // Required when mixing module types
    // (not needed for pure ESM projects)
  }
}

[6][9]

Tool-Specific Configuration

For Jest testing:

// jest.config.ts
import type { JestConfigWithTsJest } from 'ts-jest';

const config: JestConfigWithTsJest = {
  preset: 'ts-jest/presets/default-esm',
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1'
  }
};

[2]

For TS-Node execution:
Add to tsconfig.json:

{
  "ts-node": {
    "esm": true
  }
}

[1]

Key Benefits

  • Full ES module compatibility[1]
  • Support for top-level await[1]
  • Better tree-shaking with bundlers[1]
  • Future-proof standard implementation[5][6]

Always verify your configuration by checking:

  1. No CommonJS-specific features (require, __dirname)[1]
  2. All imports use explicit .js extensions[3][6]
  3. Package dependencies support ESM (use lodash-es instead of lodash)[1]

This setup ensures proper ES module resolution while maintaining TypeScript type checking capabilities across modern Node.js environments[5][6][10].

Citations:


ESM Configuration Review – Consider Updating for Native Node ESM
The current configuration with "module": "Preserve" and "target": "es2015" does preserve the ES module syntax and enables modern JS features, which can support a migration from CommonJS. However, based on industry recommendations for native ESM support in Node.js, please consider the following:

  • Module Setting:
    • While "Preserve" leaves ES module syntax intact for subsequent processing (e.g., by a bundler), the recommended configuration for native Node ESM is to use "module": "NodeNext" (often paired with "moduleResolution": "NodeNext").

  • Target Setting:
    • Using "target": "es2015" is broadly compatible, but adopting a more modern target (such as "ES2020") can unlock features like top-level await and better optimizations.

  • Package.json:
    • Ensure that "type": "module" is set in your package.json if you intend to execute the output as native ES modules.

If your build pipeline relies on further transformation (for example, if you’re using a bundler), preserving the ES module syntax might be acceptable. Otherwise, if you are targeting native ESM execution in Node.js, aligning with the recommended settings will offer improved compatibility and future-proofing.

[founded_issues]

package.json (2)

6-10: LGTM! The export separation aligns with bundle size reduction goals.

The separation of server and client exports is a good approach to prevent server-side rendering code from being included in the browser bundle, which should help achieve the stated goal of reducing bundle size by ~14KB.


40-41: ⚠️ Potential issue

Verify React version compatibility.

React 19.0.0 is specified as a devDependency, but this version is not yet released.

Update the React version to the latest stable release:

-    "react": "^19.0.0",
-    "react-dom": "^19.0.0",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
❌ Incorrect review comment

🌐 Web query:

What is the latest stable version of React?

💡 Result:

The latest stable version of React is 19.0, released on December 5, 2024[2][4][6][8]. This version introduced major features like Actions for simplified form handling, new hooks (useActionState, useFormStatus), Server Components/Server Actions integration, and improved hydration performance[4][5].

Key details about React 19:

  • Available via npm using npm install react@19[8]
  • Requires Node.js 18+ and dropping support for IE11[5]
  • Includes breaking changes like removing deprecated APIs (string refs, propTypes) and requiring the new JSX transform[5]

Developers creating new projects with npx create-react-app will automatically use React 19[1][6]. For existing projects upgrading from React 18.x, a migration guide was provided to handle deprecated APIs[5][9].

Citations:


React version is valid.
The web query confirms that React 19.0.0 is now the latest stable release, so there’s no need to change it to 18.2.0.

Likely an incorrect or invalid review comment.

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)
lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js (1)

1-1: Add file extension to import statement.

ESLint is reporting a missing file extension in the import statement.

-import ReactOnRails from 'react-on-rails/server';
+import ReactOnRails from 'react-on-rails/server.js';
🧰 Tools
🪛 ESLint

[error] 1-1: Missing file extension for "react-on-rails/server"

(import/extensions)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 54a9286 and e3f0279.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js (1 hunks)
  • node_package/tests/Authenticity.test.js (1 hunks)
  • node_package/tests/ReactOnRails.test.js (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • node_package/tests/ReactOnRails.test.js
🧰 Additional context used
🪛 ESLint
lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js

[error] 1-1: Missing file extension for "react-on-rails/server"

(import/extensions)

⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: build-dummy-app-webpack-test-bundles (newest)
  • GitHub Check: examples (newest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (oldest)
  • GitHub Check: examples (oldest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: build
🔇 Additional comments (3)
lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js (1)

1-1: LGTM! Import path change aligns with bundle size optimization.

The change from 'react-on-rails' to 'react-on-rails/server' supports the PR's goal of reducing bundle size by separating server and client code.

🧰 Tools
🪛 ESLint

[error] 1-1: Missing file extension for "react-on-rails/server"

(import/extensions)

node_package/tests/Authenticity.test.js (1)

1-1: LGTM! Import path update maintains test functionality.

The change from '../src/ReactOnRails' to '../src/ReactOnRails.client' correctly reflects the new module structure while preserving the authentication functionality being tested.

CHANGELOG.md (1)

21-24: LGTM! Clear and detailed changelog entries.

The changelog entries effectively document both the technical changes and their quantified benefits:

  1. Migration to ESM for more compact modules (~1KB improvement)
  2. Split exports strategy to avoid shipping server code to browsers (~14KB improvement)

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 (2)
node_package/src/ReactOnRails.full.ts (2)

11-13: Enhance the warning message with more specific details.

While the warning correctly alerts about server code in the browser bundle, consider making it more actionable by:

  1. Including the approximate bundle size impact (~14KB as per PR objectives).
  2. Providing a public documentation link or including brief guidance in the message itself.
-  console.warn('Optimization opportunity: "react-on-rails" includes server-rendering code. Browser may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (requires sign in)');
+  console.warn('Bundle size optimization: "react-on-rails" full bundle includes ~14KB of server-rendering code. To reduce bundle size, import from "react-on-rails/client" instead of "react-on-rails" in browser environments.');

15-16: Add JSDoc comments for better documentation.

Consider adding JSDoc comments to document the purpose and usage of these methods.

+/**
+ * Handles errors in server-side rendering context.
+ * @param options Error handling options
+ * @returns Formatted error message or undefined
+ */
 Client.handleError = (options: ErrorOptions): string | undefined => handleError(options);
+
+/**
+ * Renders React components on the server side.
+ * @param options Rendering parameters
+ * @returns Rendered component or Promise of render result
+ */
 Client.serverRenderReactComponent = (options: RenderParams): null | string | Promise<RenderResult> => serverRenderReactComponent(options);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e3f0279 and 859d3d9.

📒 Files selected for processing (6)
  • .gitignore (1 hunks)
  • CHANGELOG.md (1 hunks)
  • node_package/src/ReactOnRails.full.ts (1 hunks)
  • node_package/src/ReactOnRails.node.ts (1 hunks)
  • package.json (1 hunks)
  • tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (4)
  • package.json
  • tsconfig.json
  • node_package/src/ReactOnRails.node.ts
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: build-dummy-app-webpack-test-bundles (newest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (oldest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: examples (oldest)
  • GitHub Check: build
🔇 Additional comments (2)
node_package/src/ReactOnRails.full.ts (2)

1-9: LGTM! Well-organized imports.

The imports are properly structured with clear type definitions.


18-19: LGTM! Clean export structure.

The exports are well-organized, making types available while maintaining Client as the default export.

import Client from './ReactOnRails.client';

if (typeof window !== 'undefined') {
console.log('ReactOnRails: Optimization opportunity: "react-on-rails" includes server-rendering code. Browser may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (requires sign in)');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@justin808 could you update the article to use react-on-rails/client client-side?

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: 1

🧹 Nitpick comments (1)
tsconfig.json (1)

13-13: Consider browser compatibility with ESNext target.

While targeting "ESNext" allows using the latest JavaScript features, ensure that:

  1. Your build pipeline includes appropriate transpilation for production
  2. The target browsers are compatible with the generated code

Consider adding a browserslist configuration to ensure proper transpilation for your target browsers.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9973270 and bb778cb.

📒 Files selected for processing (4)
  • CONTRIBUTING.md (1 hunks)
  • node_package/src/ReactOnRails.full.ts (1 hunks)
  • package-scripts.yml (1 hunks)
  • tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • CONTRIBUTING.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • node_package/src/ReactOnRails.full.ts
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: dummy-app-integration-tests (newest)
  • GitHub Check: dummy-app-integration-tests (oldest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: build
🔇 Additional comments (3)
tsconfig.json (1)

6-8: Verify TypeScript version compatibility for moduleResolution "bundler".

The configuration changes align well with the PR's objective of migrating to ESM and reducing bundle size. However, the "moduleResolution": "bundler" setting is a relatively new TypeScript feature.

✅ Verification successful

🌐 Web query:

What TypeScript version introduced moduleResolution "bundler" and what are its implications?

💡 Result:

TypeScript introduced the moduleResolution: "bundler" option in version 5.0 (March 2023). This feature targets modern bundlers like Vite, Webpack, esbuild, and Parcel, offering a hybrid resolution strategy that balances flexibility with compatibility.

Key Implications:

  1. Bundler-First Compatibility

    • Designed for projects using bundlers that blend ESM and CommonJS resolution rules[3][9].
    • Avoids strict Node.js ESM requirements (e.g., mandatory file extensions in imports)[9].
  2. Relaxed Import Rules

    • Allows extensionless imports (e.g., import "./utils" instead of "./utils.mjs")[3][9].
    • Supports importing .ts files directly if paired with allowImportingTsExtensions (requires noEmit or declaration-only output)[6][7].
  3. Configuration Requirements

    • Requires module: "esnext" or similar ESM-targeting settings[7][9].
    • Implicitly enables resolvePackageJsonExports to honor package.json exports/imports fields[9].
  4. Tradeoffs for Library Authors

    • Not recommended for libraries published to npm, as it may obscure compatibility issues for non-bundler users[9].
    • Prefer node16/nodenext for libraries to ensure stricter Node.js compliance[9].
  5. Enhanced Tooling Integration

    • In TypeScript 5.4+, works with module: "preserve" to support require() calls in hybrid environments (e.g., Bun)[5].

Example Configuration:

{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "noEmit": true // Required for .ts imports
  }
}

This mode simplifies development workflows but shifts responsibility to bundlers for runtime resolution[6][8].

Citations:


TS 5.0 Compatibility Verified for "moduleResolution": "bundler"

  • The "moduleResolution": "bundler" option was introduced in TypeScript 5.0 (March 2023) and is intended for modern bundler workflows.
  • It enables a relaxed import strategy (e.g., allowing extensionless imports) and implicitly sets resolvePackageJsonExports, which aligns with an ESM-first approach.
  • Ensure that the project uses TypeScript 5.0 or newer to fully take advantage of this configuration.
package-scripts.yml (2)

49-50: Simplified glob patterns improve maintainability.

The change from specific path patterns to a more generic "**/*.@(js|jsx)" pattern is a good improvement that:

  1. Reduces maintenance overhead
  2. Ensures consistent formatting across all JS/JSX files
  3. Prevents missing new files/directories

Also applies to: 53-54


58-58: Verify the cleanup of temporary test files.

The addition of rm -rf packages/vm-renderer/tests/tmp before running prettier ensures a clean state, but we should verify that this directory is actually used and that the cleanup is necessary.

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Description: Check the usage of the tmp directory.

# Search for references to the tmp directory
rg -l "vm-renderer/tests/tmp" --type js --type ts

# Check if the directory is mentioned in test files
rg -l "tmp" "packages/vm-renderer/tests"

Length of output: 155


Review Verification: Temporary Test Files Cleanup

  • Our static search for "vm-renderer/tests/tmp" in JavaScript/TypeScript files returned no matches.
  • Attempting to list the packages/vm-renderer/tests directory resulted in an "os error 2" (i.e., the directory isn’t present in the repository).
  • These findings suggest that the cleanup command is currently redundant based on the static codebase; however, it’s possible the directory may be created dynamically at runtime during tests.
  • Action: Please verify during test execution whether the tmp folder is ever created. If tests do not generate temporary files there, the rm -rf command might be unnecessary.

@@ -25,9 +25,9 @@ scripts:
# 3. Check if the project is built now;
# 4. If it failed, print an error message (still follow https://docs.npmjs.com/cli/v8/using-npm/scripts#best-practices).
script: >
[ -f node_package/lib/ReactOnRails.js ] ||
[ -f node_package/lib/ReactOnRails.full.js ] ||
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 12, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the new file path aligns with the export split.

The file check has been updated from ReactOnRails.js to ReactOnRails.full.js, which aligns with the PR's objective of splitting exports. However, let's verify that this is the correct path after the migration.

Also applies to: 30-30


🏁 Script executed:

#!/bin/bash
# Description: Verify the existence and exports of the new file.

# Check if the new file exists in the expected location
if [ -f "node_package/lib/ReactOnRails.full.js" ]; then
    echo "File exists at the expected location"
else
    echo "File not found at the expected location"
fi

# Check for any remaining references to the old file
rg -l "ReactOnRails\.js" --type js --type json --type yaml

Length of output: 200


Missing File: Expected "ReactOnRails.full.js" Was Not Found

Our verification check indicates that the file at node_package/lib/ReactOnRails.full.js is missing from the repository. This is a concern because the update in the package-scripts expects this file to be generated or present to align with the export split changes. Please review the build process or file generation steps to ensure that the new file is correctly produced and referenced.

  • The expected file node_package/lib/ReactOnRails.full.js does not exist.
  • Verify that the build/migration process correctly produces the new ESM file.
  • Ensure no unresolved dependencies on the old file name remain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's autogenerated

Copy link
Contributor

Choose a reason for hiding this comment

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

@Romex91 Understood, thank you for the clarification.


✏️ Learnings added
Learnt from: Romex91
PR: shakacode/react_on_rails#1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.410Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

@alexeyr-ci
Copy link
Collaborator

In https://github.com/shakacode/react_on_rails/tree/master/docs, see where imports need to be updated.

tsconfig.json Outdated
@@ -3,13 +3,14 @@
"allowJs": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"lib": ["dom", "es2015"],
"module": "CommonJS",
"lib": ["dom", "ESNext"],
Copy link
Collaborator

@alexeyr-ci alexeyr-ci Feb 12, 2025

Choose a reason for hiding this comment

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

Mentioned in Slack, but duplicating here: extend https://www.npmjs.com/package/@tsconfig/node16 and add comments about keeping it in sync with

node-version: ${{ matrix.versions == 'oldest' && '16' || '20' }}
(probably to both places).

You'll still need to override lib, but it will be ["dom", "es2021"].

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Downgraded back to es2015, to avoid unexpected compatibility issues

@Romex91
Copy link
Contributor Author

Romex91 commented Feb 13, 2025

In https://github.com/shakacode/react_on_rails/tree/master/docs, see where imports need to be updated.

The only doc that needs to be updated is #1697 (comment)

@Romex91 Romex91 force-pushed the roman-kuksin/reduce-bundle-size branch from 1fd1f32 to ba43321 Compare February 13, 2025 06:06
@Romex91 Romex91 requested a review from alexeyr-ci February 13, 2025 06:06
@Romex91 Romex91 force-pushed the roman-kuksin/reduce-bundle-size branch 2 times, most recently from abad002 to fb671dc Compare February 13, 2025 06:11
tsconfig.json Outdated
"noImplicitAny": true,
"outDir": "node_package/lib",
"strict": true,
"incremental": true,
"target": "es5"
"target": "es2015"
Copy link
Collaborator

@alexeyr-ci alexeyr-ci Feb 13, 2025

Choose a reason for hiding this comment

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

Even Node 14 has es2020, so that should definitely be safe.

This tells TypeScript that it's okay to output JavaScript syntax with features from ES2020. In practice, this means that it will e.g. output optional chaining operators & async/await syntax instead of embedding a polyfill.

Anyone running an older Node is also not going to upgrade this before upgrading Node, I think :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@Romex91 Romex91 force-pushed the roman-kuksin/reduce-bundle-size branch from e20d592 to eba5b39 Compare February 13, 2025 07:39
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)
CHANGELOG.md (1)

1192-1193: Update the version comparison link.

The version comparison link needs to be updated to include this PR's changes.

-[Unreleased]: https://github.com/shakacode/react_on_rails/compare/14.1.1...master
+[Unreleased]: https://github.com/shakacode/react_on_rails/compare/14.1.1...HEAD
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bb778cb and eba5b39.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • node_package/src/ReactOnRails.full.ts (1 hunks)
  • tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tsconfig.json
  • node_package/src/ReactOnRails.full.ts
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: dummy-app-integration-tests (newest)
  • GitHub Check: dummy-app-integration-tests (oldest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: build
🔇 Additional comments (1)
CHANGELOG.md (1)

21-24: LGTM! Clear documentation of breaking changes.

The breaking changes section effectively communicates:

  • The migration from CJS to ESM with the expected improvement (~1KB)
  • The new export option with its benefit (~14KB)
  • The required action for users to update their code

@alexeyr-ci
Copy link
Collaborator

alexeyr-ci commented Feb 13, 2025

@Romex91 Please check the new version with https://www.npmjs.com/package/@arethetypeswrong/cli (see gregberge/loadable-components#989 (comment) for an example).

@@ -1,4 +1,4 @@
import type { AuthenticityHeaders } from './types/index';
import type { AuthenticityHeaders } from './types/index.js';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems to be the only way to make "type": "module" in package.json happy

.eslintrc Outdated
plugins:
- "@typescript-eslint"
- "require-extensions"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Enforces .js extensions in relative imports

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it better than import/extensions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because import/extensions doesn't enforce '.js' extensions in typescript files (required by "type": "module" which is required by attw)

package.json Outdated
@@ -2,16 +2,19 @@
"name": "react-on-rails",
"version": "14.1.1",
"description": "react-on-rails JavaScript for react_on_rails Ruby gem",
"type": "module",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

attw says some bundlers may fail without it.

package.json Outdated
@@ -57,7 +61,7 @@
"start": "nps",
"prepack": "nps build.prepack",
"prepare": "nps build.prepack",
"prepublishOnly": "yarn run build",
"prepublishOnly": "yarn run build && attw --profile esm-only --pack .",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Attw errors will prevent publishing (linter rules should prevent any issues, added the step just in case)

package.json Outdated
@@ -57,7 +62,7 @@
"start": "nps",
"prepack": "nps build.prepack",
"prepare": "nps build.prepack",
"prepublishOnly": "yarn run build",
"prepublishOnly": "yarn run build && (command -v attw >/dev/null && attw --profile esm-only --pack . || (echo 'attw not found, skipping' && exit 0))",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

attw doesn't work on node 16. The check will only run on node 20

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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 611b85f and 9006b79.

📒 Files selected for processing (2)
  • jest.config.js (1 hunks)
  • package.json (4 hunks)
🧰 Additional context used
🪛 GitHub Actions: JS unit tests for Renderer package
jest.config.js

[error] 1-1: SyntaxError: Unexpected token 'export'. This may indicate that the file is using ES module syntax in a CommonJS context.

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: build
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (newest)
  • GitHub Check: rspec-package-tests (oldest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (oldest)
🔇 Additional comments (4)
jest.config.js (1)

5-7: LGTM! Essential configuration for ESM support.

The moduleNameMapper configuration is correctly set up to handle ESM imports with .js extensions, which is necessary for the migration from CommonJS to ESM.

package.json (3)

34-34: LGTM! Dependencies support ESM migration.

The new dependencies effectively support the migration to ESM:

  • eslint-plugin-require-extensions enforces .js extensions required for ESM
  • @arethetypeswrong/cli helps verify ESM compatibility

Also applies to: 47-49


65-65: LGTM! Robust publish script with ESM verification.

The modified prepublishOnly script ensures ESM compatibility by running attw checks while gracefully handling cases where attw is not available.


6-10:

❓ Verification inconclusive

Verify bundle size reduction from export splitting.

The export changes align with the PR objective of separating client and server code. Let's verify the actual bundle size reduction.


🏁 Script executed:

#!/bin/bash
# Description: Compare bundle sizes of old and new exports

# Get size of full implementation
ls -l node_package/lib/ReactOnRails.full.js | awk '{print $5}'

# Get size of client-only implementation
ls -l node_package/lib/ReactOnRails.client.js | awk '{print $5}'

Length of output: 303


🏁 Script executed:

#!/bin/bash
# Re-verify the existence and locations of the bundle files

echo "Searching for 'ReactOnRails.full.js' across the repository..."
fd -t f "ReactOnRails.full.js"

echo "Searching for 'ReactOnRails.client.js' across the repository..."
fd -t f "ReactOnRails.client.js"

Length of output: 345


Action Required: Verify Export File Paths and Build Artifacts

The export changes in package.json (lines 6-10) follow the objective of splitting server/client bundles. However, our verification scripts didn't locate either ReactOnRails.full.js or ReactOnRails.client.js in the repository. Please verify that these files are generated by your build process and that the paths set in package.json correctly reference the output locations.

  • Confirm that node_package/lib/ReactOnRails.full.js and node_package/lib/ReactOnRails.client.js are generated.
  • If these files are produced at runtime or by a build script, consider updating the export paths accordingly or adding documentation for maintainers.

jest.config.js Outdated
@@ -1,5 +1,8 @@
module.exports = {
export default {
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

Revert to CommonJS syntax for Jest configuration.

The ESM export syntax is causing test failures because Jest configuration files should use CommonJS. While the PR aims to migrate to ESM, Jest config files are an exception to this rule.

Apply this diff to fix the syntax error:

-export default {
+module.exports = {
📝 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
export default {
module.exports = {
🧰 Tools
🪛 GitHub Actions: JS unit tests for Renderer package

[error] 1-1: SyntaxError: Unexpected token 'export'. This may indicate that the file is using ES module syntax in a CommonJS context.

@Romex91 Romex91 force-pushed the roman-kuksin/reduce-bundle-size branch from 9006b79 to c352b50 Compare February 14, 2025 07:45
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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9006b79 and 91d363f.

⛔ Files ignored due to path filters (1)
  • spec/dummy/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • jest.config.js (1 hunks)
  • node_package/src/context.ts (1 hunks)
  • package.json (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • jest.config.js
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (newest)
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles (oldest)
  • GitHub Check: rspec-package-tests (oldest)
🔇 Additional comments (5)
node_package/src/context.ts (2)

9-9: LGTM! Good improvement using globalThis.

Using globalThis instead of this is a better approach as it:

  • Aligns with the function's this: void type
  • Provides a standardized way to access the global object
  • Works consistently across different JavaScript environments

9-9:

✅ Verification successful

Verify minimum environment requirements for globalThis.

Let's ensure that globalThis is supported in all target environments.


🌐 Web query:

What browsers and Node.js versions support globalThis?

💡 Result:

The globalThis property was standardized in ECMAScript 2020 (ES11) to provide a unified way of accessing the global object across JavaScript environments. Here's a breakdown of its support:

Browser Support

  • Chrome: Supported since v71 (released Dec 2018)
  • Firefox: Supported since v65 (released Jan 2019)
  • Safari: Supported since v12.1 (released Mar 2019)
  • Edge: Supported since v79 (Chromium-based)
  • Web Workers: Supported via self equivalence

Node.js Support

  • Node.js: Supported since v12.0 (released Apr 2019)[2][3][6]

Key Compatibility Notes

  1. Polyfill Requirements:

    // Polyfill for pre-ES2020 environments
    (function() {
      if (typeof globalThis !== 'object') {
        Object.defineProperty(Object.prototype, '__magic__', {
          get: function() { return this; },
          configurable: true
        });
        __magic__.globalThis = __magic__;
        delete Object.prototype.__magic__;
      }
    })();

    Required for environments like Internet Explorer or older Node.js versions[3][5].

  2. Module Context:

    • In ES modules (import/export), top-level this is undefined but globalThis still works[4]
    • CommonJS modules require explicit globalThis usage instead of implicit global[6]
  3. Security Contexts:

    • In browsers with strict CSP policies, eval-based fallbacks may be blocked[4]
    • Cross-origin iframes maintain isolation through WindowProxy[4][5]

All modern JavaScript environments released after Q1 2019 natively support globalThis, making it safe for cross-platform development without polyfills in current applications[2][3][4].

Citations:


GlobalThis support confirmed for modern environments

The use of globalThis in this file is acceptable since it is natively supported in all modern environments:

  • Chrome ≥ v71
  • Firefox ≥ v65
  • Safari ≥ v12.1
  • Edge (Chromium-based) and Web Workers
  • Node.js ≥ v12

If your project targets these or later versions, no additional polyfill is required. Otherwise, ensure that legacy environments (like IE or older Node.js versions) include an appropriate polyfill.

package.json (3)

35-35: LGTM! Dependencies support ESM migration.

The new dependencies effectively support the ESM migration:

  • eslint-plugin-require-extensions enforces .js extensions required for ESM
  • @arethetypeswrong/cli helps verify type compatibility

Also applies to: 48-50


66-66: LGTM! Robust build script.

The modified prepublishOnly script gracefully handles the attw check, ensuring type compatibility while maintaining backward compatibility with Node 16.


5-5:

❓ Verification inconclusive

LGTM! Verify import compatibility.

The addition of "type": "module" correctly enables ESM, supporting the bundle size reduction goal.

Run this script to check for potential import compatibility issues:


🏁 Script executed:

#!/bin/bash
# Description: Check for potential import compatibility issues after ESM migration

# Search for require() calls that need to be converted to import
rg "require\(" --type js --type ts

# Search for .js extensions in imports (required for ESM)
rg "from ['\"](\.\/|\.\.\/)[^'\"]*['\"]" --type js --type ts

Length of output: 2312


ESM Migration: Verify Compatibility of Legacy CJS Code
The addition of "type": "module" in the package.json is correctly enabling ESM to support the bundle size reduction goal. However, the verification script revealed some legacy require() calls (in test, dummy, and configuration files) that still exist, and the regex for checking relative imports produced an error. Please do the following:

  • Review remaining require() calls: Confirm that the CJS usages in non-production files (e.g., configuration and test files) are intentionally left unchanged.
  • Re-verify relative import statements: Update the regex to a correctly escaped version (e.g.,
    rg "from ['\\\"](\\./|\\.\\./)[^'\\\"]*['\\\"]" --type js --type ts) and manually inspect that all relative imports include the necessary file extensions for ESM compatibility.

Comment on lines 8 to +11
"node": "./node_package/lib/ReactOnRails.node.js",
"default": "./node_package/lib/ReactOnRails.js"
}
"default": "./node_package/lib/ReactOnRails.full.js"
},
"./client": "./node_package/lib/ReactOnRails.client.js"
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

LGTM! Effective bundle size optimization.

The separation of client and server exports effectively prevents server-rendering code from being included in the browser bundle, supporting the 14KB size reduction goal.

Run this script to verify the export paths:


🏁 Script executed:

#!/bin/bash
# Description: Verify the existence and content of the export files

# Check if the export files exist
ls -l node_package/lib/ReactOnRails.{node,full,client}.js || echo "Missing export files"

# Check file sizes to confirm bundle size reduction
du -h node_package/lib/ReactOnRails.{node,full,client}.js

Length of output: 812


Attention: Missing Export Files

It appears that the export paths in package.json (lines 8-11) reference files:

  • node_package/lib/ReactOnRails.node.js
  • node_package/lib/ReactOnRails.full.js
  • node_package/lib/ReactOnRails.client.js

However, the verification script indicates that these files are missing. Please verify whether:

  • These files are generated during the build process (and might need to be checked post-build), or
  • The export paths in package.json need to be updated to match the actual file locations.

This review comment cannot be approved until the discrepancy is resolved.

@alexeyr-ci alexeyr-ci force-pushed the roman-kuksin/reduce-bundle-size branch 3 times, most recently from 63c2d2d to fc42b26 Compare February 26, 2025 09:27
@Judahmeek
Copy link
Contributor

@alexeyr-ci are you done making changes to this branch?

@alexeyr-ci
Copy link
Collaborator

@alexeyr-ci are you done making changes to this branch?

@Judahmeek Yes.

@Judahmeek Judahmeek force-pushed the roman-kuksin/reduce-bundle-size branch from 0d98c5b to bbf3274 Compare March 1, 2025 20:08
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)
node_package/src/ReactOnRails.full.ts (1)

11-13: Consider making the browser detection warning more specific and actionable.

The warning about optimization opportunity is helpful but could be clearer about when it's relevant and what exact action to take.

-if (typeof window !== 'undefined') {
-  console.log('Optimization opportunity: "react-on-rails" includes ~14KB of server-rendering code. Browsers may not need it. See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 (Requires creating a free account)');
+if (typeof window !== 'undefined' && process.env.NODE_ENV !== 'development') {
+  console.warn('Optimization opportunity: You are including server-rendering code (~14KB) in your browser bundle. Consider importing from "react-on-rails/client" instead of "react-on-rails". See https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352');
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0d98c5b and bbf3274.

📒 Files selected for processing (11)
  • .gitignore (1 hunks)
  • CHANGELOG.md (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • node_package/src/ReactOnRails.client.ts (2 hunks)
  • node_package/src/ReactOnRails.full.ts (1 hunks)
  • node_package/src/ReactOnRails.node.ts (1 hunks)
  • node_package/tests/Authenticity.test.js (1 hunks)
  • package-scripts.yml (1 hunks)
  • package.json (1 hunks)
  • spec/dummy/client/app/packs/client-bundle.js (1 hunks)
  • tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • .gitignore
  • package.json
  • node_package/src/ReactOnRails.node.ts
  • CONTRIBUTING.md
  • package-scripts.yml
  • node_package/tests/Authenticity.test.js
  • spec/dummy/client/app/packs/client-bundle.js
  • tsconfig.json
  • CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: dummy-app-integration-tests (newest)
  • GitHub Check: dummy-app-integration-tests (oldest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: rspec-package-tests (oldest)
🔇 Additional comments (6)
node_package/src/ReactOnRails.full.ts (3)

19-19: LGTM - The handleError method is correctly implemented.

The method is properly extending the Client object with server-side error handling functionality.


25-25: LGTM - The serverRenderReactComponent method is correctly implemented.

The method is properly extending the Client object with server-side rendering functionality.


27-28: Remember to update documentation references to the new import paths.

Ensure that the documentation is updated to reflect the new import paths (react-on-rails/client vs react-on-rails).

As mentioned in the PR comments, don't forget to update the article at https://forum.shakacode.com/t/how-to-use-different-versions-of-a-file-for-client-and-server-rendering/1352 to reference the new import paths.

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

242-243: LGTM - The serverRenderReactComponent method correctly prevents server-side usage in client context.

The error message clearly indicates that this functionality is not available in the client module and directs users to the correct import.


258-259: LGTM - The handleError method correctly prevents server-side usage in client context.

The error message clearly indicates that this functionality is not available in the client module and directs users to the correct import.


242-260:

❓ Verification inconclusive

Verify potential backward compatibility impact for existing applications.

The changes enforce a stricter separation between client and server code, which is good for bundle size but may impact existing applications that import from the main module.


🌐 Web query:

What's the recommended approach for handling breaking changes in NPM packages?

💡 Result:

When upgrading npm packages with breaking changes, adopt a structured approach combining automated tools, manual verification, and incremental updates to minimize disruptions. Here's the recommended strategy:

1. Assess Dependencies & Security Risks

  • Use npm outdated or npm-check-updates (ncu) to identify outdated packages[2][7].
  • Run npm audit to detect security vulnerabilities and apply fixes with npm audit fix, but verify breaking changes using the SEMVER WARNING output[3][7].

2. Plan Major Version Upgrades

  • Check release notes for breaking changes before major version updates (e.g., [email protected]2.x)[2][6].
  • Test in isolation: Create a feature branch to validate compatibility and update dependencies incrementally[1][5].

3. Manage Dependencies Strategically

  • Use resolutions/overrides in package.json to enforce specific sub-dependency versions (e.g., force [email protected])[1].
  • Lock versions with npm ci for reproducible builds, ensuring consistency across environments[1][4].

4. Iterative Codebase Updates

  • Adopt dual versions temporarily (e.g., const newAxios = require('axios2.1.3');) while migrating code[1].
  • Refactor incrementally to minimize downtime, prioritizing critical dependencies first[1][7].

5. Automate & Monitor

  • Configure Dependabot or CI/CD pipelines to check for updates daily[2][7].
  • Use monorepo tools (e.g., Lerna) for coordinated updates across multiple packages[2].

Key Tools & Commands

# Check outdated packages
ncu

# Update package.json versions
ncu -u && npm install

# Audit security vulnerabilities
npm audit --audit-level=critical

# Install exact versions
npm install [email protected] --save-exact

Best Practices

  • Avoid --legacy-peer-deps unless absolutely necessary, as it masks dependency conflicts[7].
  • Commit package-lock.json to ensure consistent dependency resolution[1][4].
  • Test extensively in staging environments before deploying major updates[2][7].

By combining automation, cautious upgrades, and thorough testing, teams can mitigate risks while keeping dependencies secure and up-to-date[1][2][7].

Citations:


Action: Verify the backward compatibility impact of the separation between client and server APIs.

The refactoring in node_package/src/ReactOnRails.client.ts (lines 242–260) now explicitly disables server rendering methods by throwing errors. This change helps reduce bundle size and reinforces the separation between client and server environments. However, it may break existing applications that rely on these APIs from the main module. Please ensure:

  • Client/Server Separation: Applications are not mistakenly importing or invoking serverRenderReactComponent, streamServerRenderedReactComponent, or handleError on the client-side.
  • Migration Strategy: Users update their imports to use the server-side bundle where necessary.
  • Versioning and Documentation: A major version bump and a clear migration guide are provided to help developers adapt to these breaking changes, as recommended for handling breaking changes in NPM packages.

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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bbf3274 and 207407b.

📒 Files selected for processing (1)
  • node_package/tests/ReactOnRails.test.js (1 hunks)
🧰 Additional context used
🪛 ESLint
node_package/tests/ReactOnRails.test.js

[error] 9-9: Missing file extension for "../src/ReactOnRails/client"

(import/extensions)

🪛 GitHub Actions: Lint JS and Ruby
node_package/tests/ReactOnRails.test.js

[error] 9-9: Unresolved imports detected.

🪛 GitHub Actions: JS unit tests for Renderer package
node_package/tests/ReactOnRails.test.js

[error] 9-9: Cannot find module '../src/ReactOnRails/client' from 'node_package/tests/ReactOnRails.test.js'

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: dummy-app-integration-tests (newest)
  • GitHub Check: dummy-app-integration-tests (oldest)
  • GitHub Check: rspec-package-tests (newest)
  • GitHub Check: rspec-package-tests (oldest)

@Judahmeek Judahmeek force-pushed the roman-kuksin/reduce-bundle-size branch from 207407b to 29889db Compare March 1, 2025 22:09
@Judahmeek Judahmeek merged commit 35a6aae into master Mar 1, 2025
11 of 12 checks passed
@Judahmeek Judahmeek deleted the roman-kuksin/reduce-bundle-size branch March 1, 2025 22:16
@coderabbitai coderabbitai bot mentioned this pull request Mar 2, 2025
1 task
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.

5 participants