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

Development mode for sync server (React Fast Refresh on port 5006) #4372

Merged
merged 9 commits into from
Feb 17, 2025

Conversation

lelemm
Copy link
Contributor

@lelemm lelemm commented Feb 13, 2025

I added a new command yarn start:server-dev: this command proxies calls to react from 5006 to port 3001 automatically. This way we can have the react fast refresh from the server port, not needing to connect from the 3001 port manually.

@actual-github-bot actual-github-bot bot changed the title Development mode for sync server (React Fast Refresh on port 5006) [WIP] Development mode for sync server (React Fast Refresh on port 5006) Feb 13, 2025
Copy link

netlify bot commented Feb 13, 2025

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit 500a67f
🔍 Latest deploy log https://app.netlify.com/sites/actualbudget/deploys/67b398022df95100088dc165
😎 Deploy Preview https://deploy-preview-4372.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@lelemm lelemm changed the title [WIP] Development mode for sync server (React Fast Refresh on port 5006) Development mode for sync server (React Fast Refresh on port 5006) Feb 13, 2025
Copy link
Contributor

coderabbitai bot commented Feb 13, 2025

Walkthrough

The changes introduce two new scripts in the main package.json: "start:server-monitor" for initiating a server monitoring process, and "start:server-dev" which sets the NODE_ENV to development and runs both the monitoring and start scripts in parallel. Additionally, packages/sync-server/package.json has been updated to include two new development dependencies: http-proxy-middleware and nodemon, along with a new script "start-monitor" that utilizes nodemon. Modifications in packages/sync-server/src/app.js implement conditional middleware for rate limiting and proxying based on the NODE_ENV. In development mode, a proxy middleware forwards requests to a React development server at http://localhost:3001, while in production, the application serves static files and responds to requests with index.html. The vite.config.mts file has also been updated to conditionally open a specific URL in development mode.

Suggested labels

:sparkles: Merged

Suggested reviewers

  • MikesGlitch
  • joel-jeremy
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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. (Beta)
  • @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)
packages/sync-server/src/app.js (1)

85-98: Consider extracting API paths to a constant.

The list of API paths in the context function could be moved to a constant to improve maintainability.

+const API_PATHS = [
+  '/api',
+  '/sync',
+  '/account',
+  '/gocardless',
+  '/simplefin',
+  '/secret',
+  '/admin',
+  '/openid',
+  '/mode'
+];
+
 context: (pathname, req) => {
   return (
-    !pathname.startsWith('/api') &&
-    !pathname.startsWith('/sync') &&
-    !pathname.startsWith('/account') &&
-    !pathname.startsWith('/gocardless') &&
-    !pathname.startsWith('/simplefin') &&
-    !pathname.startsWith('/secret') &&
-    !pathname.startsWith('/admin') &&
-    !pathname.startsWith('/openid') &&
-    !pathname.startsWith('/mode') &&
+    !API_PATHS.some(path => pathname.startsWith(path)) &&
     !req.url.includes('.')
   );
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 454f019 and 90316c0.

⛔ Files ignored due to path filters (2)
  • upcoming-release-notes/4372.md is excluded by !**/*.md
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • packages/sync-server/package.json (1 hunks)
  • packages/sync-server/src/app.js (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Visual regression
  • GitHub Check: Functional
  • GitHub Check: Build Docker image (alpine)
  • GitHub Check: Build Docker image (ubuntu)
🔇 Additional comments (5)
packages/sync-server/package.json (1)

60-60: LGTM! Appropriate dependency configuration.

The http-proxy-middleware is correctly added as a development dependency since it's only used in development mode.

package.json (1)

23-23: Verify port configuration for development mode.

The script correctly sets up parallel execution of server and client, but the PR mentions port 5006 while the script doesn't specify any port configuration.

Could you clarify where the port 5006 configuration is set? This might be in a configuration file not included in the PR.

packages/sync-server/src/app.js (3)

28-37: LGTM! Good practice to disable rate limiting in development.

The condition is well-structured and maintains rate limiting for production while allowing unrestricted access during development.


74-100: LGTM! Well-structured proxy configuration.

The proxy middleware is well configured with:

  • Appropriate target (localhost:3001)
  • WebSocket support enabled
  • Debug logging
  • Comprehensive path exclusions

101-106: LGTM! Clear production mode handling.

The else block appropriately handles static file serving in production mode.

Copy link
Contributor

@MikesGlitch MikesGlitch left a comment

Choose a reason for hiding this comment

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

Added some thoughts here: lelemm#3

Main changes were to:

  • Open the server url instead of the client url when launching
  • Remove the config that wasn't working

Feel free to merge or to rework it but it would be good to have those things in this PR.

@lelemm
Copy link
Contributor Author

lelemm commented Feb 17, 2025

Added some thoughts here: lelemm#3

Main changes were to:

  • Open the server url instead of the client url when launching
  • Remove the config that wasn't working

Feel free to merge or to rework it but it would be good to have those things in this PR.

I changed to open 5006 when running yarn start:server-dev
Also, I added a new command server-monitor that uses nodemon so changes on the server restarts it

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)
packages/sync-server/src/app.js (1)

87-92: Consider adding error handling for static file serving.

While the static file serving works, it might benefit from error handling for cases where index.html is not found.

-  app.get('/*', (req, res) => res.sendFile(config.webRoot + '/index.html'));
+  app.get('/*', (req, res, next) => {
+    res.sendFile(config.webRoot + '/index.html', err => {
+      if (err) {
+        console.error('Error serving index.html:', err);
+        next(err);
+      }
+    });
+  });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 90316c0 and 4a7b395.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • packages/desktop-client/vite.config.mts (1 hunks)
  • packages/sync-server/package.json (2 hunks)
  • packages/sync-server/src/app.js (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sync-server/package.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: compare
🔇 Additional comments (4)
package.json (1)

23-24: LGTM! Well-structured development scripts.

The new scripts effectively enable development mode with automatic monitoring:

  • start:server-monitor provides live reloading through nodemon
  • start:server-dev correctly sets up the development environment and runs necessary processes in parallel
packages/sync-server/src/app.js (2)

28-37: LGTM! Appropriate rate limiting configuration.

The rate limiting is correctly disabled in development mode while maintaining protection in production.


74-86:

❓ Verification inconclusive

Verify WebSocket proxy configuration.

The proxy middleware is well-configured, but let's verify the WebSocket setup to ensure it properly handles React Fast Refresh connections.


🌐 Web query:

What is the recommended WebSocket configuration for http-proxy-middleware with React Fast Refresh?

💡 Result:

To configure WebSockets with http-proxy-middleware for React Fast Refresh/HMR (Hot Module Replacement), follow these best practices:


1. Basic Proxy Configuration

Enable WebSocket support by setting ws: true and handle HTTP upgrade events:

// src/setupProxy.js (Create React App)
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    createProxyMiddleware('/sockjs-node', {
      target: 'http://localhost:3000', // Your dev server
      ws: true,
      changeOrigin: true
    })
  );
};

For non-CRA setups:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();

const wsProxy = createProxyMiddleware({
  target: 'http://localhost:3000',
  ws: true,
  pathFilter: '/sockjs-node'
});

app.use(wsProxy);
const server = app.listen(8080); // Proxy port
server.on('upgrade', wsProxy.upgrade); // Critical for WS upgrade [1][3]

2. React Fast Refresh Requirements

  • WebSocket Endpoint: Fast Refresh uses /sockjs-node by default
  • Dynamic Protocol Handling:
    // In React components
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const socket = new WebSocket(`${protocol}//${window.location.host}/sockjs-node`);

Key Configuration Options

Feature Configuration Purpose
WebSocket Support ws: true Enables WS proxying [1][4][10]
Path Filtering pathFilter: '/sockjs-node' Limits proxy to HMR endpoints
HTTP Upgrade server.on('upgrade') Required for WS connection initialization [1][3]
Secure Context changeOrigin: true Handles cross-origin requests correctly

Common Issues & Fixes

  1. Connection Drops:

    • Ensure proxy server listens for upgrade events [3]
    • Verify no conflicting CORS policies
  2. HTTPS Context:

    // For HTTPS dev servers
    const socket = new WebSocket(`wss://${window.location.host}/sockjs-node`);
  3. Path Rewrites (if needed):

    createProxyMiddleware({
      target: 'http://localhost:3000',
      ws: true,
      pathRewrite: { '^/websocket': '' } // Removes path segment
    });

This configuration ensures proper WebSocket handling for React's Fast Refresh system while maintaining compatibility with http-proxy-middleware's capabilities[1][3][6]. Always test both HTTP and WS connections when modifying proxy settings.

Citations:


Action: Confirm WebSocket Proxy Setup for React Fast Refresh

The current configuration correctly enables WebSocket proxying with ws: true and appears to work for standard requests. However, since React Fast Refresh typically uses the /sockjs-node endpoint, please verify that upgrade events are properly handled on that path. If you encounter issues with hot module replacement, consider constraining the proxy to /sockjs-node and explicitly wiring up the HTTP upgrade events (e.g. using server.on('upgrade', proxy.upgrade)).

  • File: packages/sync-server/src/app.js (Lines 74-86)
  • Details:
    • Existing config enables WebSocket support.
    • Best practices suggest verifying that /sockjs-node connections are routed correctly for Fast Refresh.

Please test both HTTP and WS connections in development to ensure full Fast Refresh compatibility.

packages/desktop-client/vite.config.mts (1)

138-149: LGTM! Well-structured conditional configuration.

The server.open configuration correctly:

  • Redirects to port 5006 in development mode
  • Preserves existing browser selection logic
  • Uses type-safe conditional expressions

@lelemm
Copy link
Contributor Author

lelemm commented Feb 17, 2025

saw your changes on your branch. better the BROWSER_OPEN=localhost:5006 than changing vite config

Copy link
Contributor

github-actions bot commented Feb 17, 2025

Bundle Stats — desktop-client

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
17 6.92 MB → 6.93 MB (+7.57 kB) +0.11%
Changeset
File Δ Size
locale/fr.json 📈 +7.57 kB (+12.39%) 61.06 kB → 68.62 kB
View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

Asset File Size % Changed
static/js/fr.js 61.06 kB → 68.62 kB (+7.57 kB) +12.39%

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
static/js/en-GB.js 99.42 kB 0%
static/js/de.js 111.72 kB 0%
static/js/workbox-window.prod.es5.js 5.69 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.5 kB 0%
static/js/resize-observer.js 18.37 kB 0%
static/js/BackgroundImage.js 122.29 kB 0%
static/js/pt-BR.js 106.43 kB 0%
static/js/nl.js 98.54 kB 0%
static/js/wide.js 102.8 kB 0%
static/js/en.js 100.34 kB 0%
static/js/uk.js 111.11 kB 0%
static/js/narrow.js 85.72 kB 0%
static/js/useAccountPreviewTransactions.js 1.69 kB 0%
static/js/AppliedFilters.js 10.52 kB 0%
static/js/ReportRouter.js 1.59 MB 0%
static/js/index.js 4.31 MB 0%

Copy link
Contributor

github-actions bot commented Feb 17, 2025

Bundle Stats — loot-core

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
1 1.33 MB 0%

Changeset

No files were changed

View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

No assets were bigger

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.js 1.33 MB 0%

Copy link
Contributor

@MikesGlitch MikesGlitch left a comment

Choose a reason for hiding this comment

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

Once the lint's fixed It'll be good to go

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)
packages/sync-server/src/app.js (1)

74-87: Consider improving the proxy configuration.

  1. The logLevel: 'debug' setting might be too verbose for regular development. Consider using environment variables to control the log level.
  2. Add error handling for proxy connection failures to improve developer experience.

Apply this diff to implement the improvements:

 app.use(
   createProxyMiddleware({
     target: 'http://localhost:3001',
     changeOrigin: true,
     ws: true,
-    logLevel: 'debug',
+    logLevel: process.env.PROXY_LOG_LEVEL || 'info',
+    onError: (err, req, res) => {
+      console.error('Proxy error:', err);
+      res.status(502).send('React development server is not running. Please start it with `yarn start` in a separate terminal.');
+    },
   }),
 );
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 27c37ab and 14c7c88.

📒 Files selected for processing (3)
  • package.json (1 hunks)
  • packages/desktop-client/vite.config.mts (2 hunks)
  • packages/sync-server/src/app.js (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/desktop-client/vite.config.mts
  • package.json
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (windows-latest)
  • GitHub Check: Analyze
  • GitHub Check: Wait for Netlify build to finish
  • GitHub Check: Build Docker image (alpine)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: Build Docker image (ubuntu)
🔇 Additional comments (3)
packages/sync-server/src/app.js (3)

8-8: LGTM!

The import statement is correctly placed and the package is used appropriately for development mode proxying.


88-92: LGTM!

The production mode implementation follows best practices for serving a single-page application:

  1. Disables automatic index serving
  2. Correctly handles all routes for client-side routing
  3. Uses the configured web root path

28-37:

❓ Verification inconclusive

Verify security implications of disabling rate limiting in development.

While disabling rate limiting in development mode improves the development experience, ensure that:

  1. Development servers are not exposed to the public internet
  2. Production deployments have NODE_ENV correctly set

🏁 Script executed:

#!/bin/bash
# Description: Check for potential security issues with NODE_ENV

# Check if NODE_ENV is set in deployment configurations
rg -A 5 "NODE_ENV.*production" --type yaml --type dockerfile

# Check for any exposed development servers in deployment configurations
rg -A 5 "port.*5006|port.*3001" --type yaml --type dockerfile

Length of output: 196


Verify the Security of Disabling Rate Limiting in Development Mode

The current implementation enables rate limiting only when process.env.NODE_ENV is not 'development', which is acceptable if we ensure that development servers remain isolated and are never accidentally exposed. However, misconfigurations—such as a production deployment inadvertently running with NODE_ENV=development—could disable rate limiting and introduce security risks.

Action Items:

  • Confirm Environment Settings: Double-check that all production deployment configurations (including Dockerfiles and docker-compose files) explicitly set NODE_ENV to 'production'.
  • Ensure Development Isolation: Verify that any development server instances are not accessible from public networks.

To further assess the deployment configurations, please run a revised verification script (using corrected file type filters) similar to the example below:

#!/bin/bash
# Attempt to locate production NODE_ENV assignments in deployment-related files

# Search in Dockerfiles
rg -A 5 "NODE_ENV.*production" -g "Dockerfile*"

# Search in docker-compose YAML files
rg -A 5 "NODE_ENV.*production" -g "docker-compose*.yml"

# Optionally, check for potential exposed ports in docker-compose files
rg -A 5 "port.*(5006|3001)" -g "docker-compose*.yml"

Please manually verify the output of these commands and ensure that production deployments are correctly configured.

@lelemm
Copy link
Contributor Author

lelemm commented Feb 17, 2025

Once the lint's fixed It'll be good to go

done

@MikesGlitch MikesGlitch merged commit 3b6c97f into actualbudget:master Feb 17, 2025
23 checks passed
@armanckeser
Copy link

I believe this PR broke my edge server:
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'http-proxy-middleware' imported from /app/src/app.js

lelemm added a commit to lelemm/actual that referenced this pull request Feb 18, 2025
…ctualbudget#4372)

* devmode for sync server

* removed pluggy from this version

* md

* code review

* changed how open browser

* missed this

* linter

* trigger actions
@MikesGlitch
Copy link
Contributor

MikesGlitch commented Feb 18, 2025

I believe this PR broke my edge server: Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'http-proxy-middleware' imported from /app/src/app.js

I've fixed it here: #4400

It'll hopefully go to edge some time today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants