From bdacd446b9b151b4da0a0c8b8fb1aefde8ccab61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nacho=20Codo=C3=B1er?= Date: Fri, 5 Sep 2025 09:16:35 +0200 Subject: [PATCH] implement dynamic port calculation for Rspack and Rsdoctor --- npm-packages/meteor-rspack/package-lock.json | 4 +- npm-packages/meteor-rspack/package.json | 2 +- npm-packages/meteor-rspack/rspack.config.js | 4 +- packages/rspack/lib/constants.js | 8 +-- packages/rspack/lib/processes.js | 56 ++++++++++++++++++- packages/rspack/rspack_plugin.js | 30 +++++++++- packages/rspack/rspack_server.js | 3 +- packages/tools-core/lib/meteor.js | 8 +++ tools/modern-tests/apps/vue/package.json | 2 +- tools/modern-tests/jest.setup.js | 5 ++ tools/static-assets/skel-apollo/package.json | 2 +- tools/static-assets/skel-blaze/package.json | 2 +- .../static-assets/skel-chakra-ui/package.json | 2 +- tools/static-assets/skel-full/package.json | 2 +- tools/static-assets/skel-react/package.json | 2 +- tools/static-assets/skel-solid/package.json | 2 +- tools/static-assets/skel-svelte/package.json | 2 +- .../static-assets/skel-tailwind/package.json | 2 +- .../skel-typescript/package.json | 2 +- tools/static-assets/skel-vue/package.json | 2 +- 20 files changed, 114 insertions(+), 28 deletions(-) diff --git a/npm-packages/meteor-rspack/package-lock.json b/npm-packages/meteor-rspack/package-lock.json index 14092166c2..3919f098ee 100644 --- a/npm-packages/meteor-rspack/package-lock.json +++ b/npm-packages/meteor-rspack/package-lock.json @@ -1,12 +1,12 @@ { "name": "@meteorjs/rspack", - "version": "0.0.40", + "version": "0.0.42", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@meteorjs/rspack", - "version": "0.0.40", + "version": "0.0.42", "license": "ISC", "dependencies": { "ignore-loader": "^0.1.2", diff --git a/npm-packages/meteor-rspack/package.json b/npm-packages/meteor-rspack/package.json index 5aaf6296b3..d9dfda3a7e 100644 --- a/npm-packages/meteor-rspack/package.json +++ b/npm-packages/meteor-rspack/package.json @@ -1,6 +1,6 @@ { "name": "@meteorjs/rspack", - "version": "0.0.40", + "version": "0.0.42", "description": "Configuration logic for using Rspack in Meteor projects", "main": "index.js", "type": "module", diff --git a/npm-packages/meteor-rspack/rspack.config.js b/npm-packages/meteor-rspack/rspack.config.js index e8934cec5c..ddc9651feb 100644 --- a/npm-packages/meteor-rspack/rspack.config.js +++ b/npm-packages/meteor-rspack/rspack.config.js @@ -260,7 +260,9 @@ export default function (inMeteor = {}, argv = {}) { const doctorPluginConfig = isBundleVisualizerEnabled && rsdoctorModule?.RsdoctorRspackPlugin ? [ new rsdoctorModule.RsdoctorRspackPlugin({ - port: isClient ? 8081 : 8082, + port: isClient + ? (parseInt(Meteor.rsdoctorClientPort || '8888', 10)) + : (parseInt(Meteor.rsdoctorServerPort || '8889', 10)), }), ] : []; diff --git a/packages/rspack/lib/constants.js b/packages/rspack/lib/constants.js index 7d63269724..b585a51453 100644 --- a/packages/rspack/lib/constants.js +++ b/packages/rspack/lib/constants.js @@ -5,7 +5,7 @@ export const DEFAULT_RSPACK_VERSION = '1.5.0'; -export const DEFAULT_METEOR_RSPACK_VERSION = '0.0.40'; +export const DEFAULT_METEOR_RSPACK_VERSION = '0.0.42'; export const DEFAULT_METEOR_RSPACK_REACT_HMR_VERSION = '1.4.3'; @@ -42,12 +42,6 @@ export const GLOBAL_STATE_KEYS = { BUILD_CONTEXT_FILES_CLEANED: 'rspack.buildContextFilesCleaned', }; -/** - * Default port for Rspack dev server - * @type {string|any|number} - */ -export const RSPACK_DEVSERVER_PORT = process.env.RSPACK_DEVSERVER_PORT || 8080; - /** * Directory name for Rspack build context * Can be overridden with RSPACK_BUILD_CONTEXT environment variable diff --git a/packages/rspack/lib/processes.js b/packages/rspack/lib/processes.js index 8e3d3c3e25..fbd4d1c787 100644 --- a/packages/rspack/lib/processes.js +++ b/packages/rspack/lib/processes.js @@ -3,7 +3,53 @@ * @description Functions for managing Rspack processes */ import { checkNpmDependencyExists, getNpxCommand } from 'meteor/tools-core/lib/npm'; -import { RSPACK_DEVSERVER_PORT } from "./constants"; +import { getMeteorAppPort } from 'meteor/tools-core/lib/meteor'; + +/** + * Calculates the devServerPort based on process.env.PORT + * Base port is 8077, and we add the sum of the digits of process.env.PORT + * @returns {number} The calculated devServerPort + */ +export function calculateDevServerPort() { + const port = getMeteorAppPort(); + const basePort = 8077; + + // Sum the digits of the port + const digitSum = port.split('').reduce((sum, digit) => sum + parseInt(digit, 10), 0); + + return basePort + digitSum; +} + +/** + * Calculates the Rsdoctor client port based on process.env.PORT + * Base port is 8885, and we add the sum of the digits of process.env.PORT + * @returns {number} The calculated Rsdoctor client port + */ +export function calculateRsdoctorClientPort() { + const port = getMeteorAppPort(); + const basePort = 8885; + + // Sum the digits of the port + const digitSum = port.split('').reduce((sum, digit) => sum + parseInt(digit, 10), 0); + + return basePort + digitSum; +} + +/** + * Calculates the Rsdoctor server port based on process.env.PORT + * Base port is 8885, and we add the sum of the digits of process.env.PORT + 1 + * @returns {number} The calculated Rsdoctor server port + */ +export function calculateRsdoctorServerPort() { + const port = getMeteorAppPort(); + const basePort = 8885; + + // Sum the digits of the port + const digitSum = port.split('').reduce((sum, digit) => sum + parseInt(digit, 10), 0); + + // Add 1 to differentiate from client port + return basePort + digitSum + 1; +} const { spawnProcess, @@ -131,7 +177,7 @@ export function getRspackEnv({ isClient, isServer, isTest: inIsTest }) { ['buildContext', RSPACK_BUILD_CONTEXT], ['chunksContext', RSPACK_CHUNKS_CONTEXT], ['assetsContext', RSPACK_ASSETS_CONTEXT], - ['devServerPort', RSPACK_DEVSERVER_PORT], + ['devServerPort', process.env.RSPACK_DEVSERVER_PORT], ...(swcExternalHelpers && [['swcExternalHelpers', swcExternalHelpers]] || []), ...(isReactEnabled && [['isReactEnabled', isReactEnabled]] || []), ...(isBlazeEnabled && [['isBlazeEnabled', isBlazeEnabled]] || []), @@ -139,7 +185,11 @@ export function getRspackEnv({ isClient, isServer, isTest: inIsTest }) { ...(isTypescriptEnabled && [['isTypescriptEnabled', isTypescriptEnabled]] || []), ...(isTsxEnabled && [['isTsxEnabled', isTsxEnabled]] || []), ...(isJsxEnabled && [['isJsxEnabled', isJsxEnabled]] || []), - ...(isBundleVisualizerEnabled && [['isBundleVisualizerEnabled', isBundleVisualizerEnabled]] || []), + ...(isBundleVisualizerEnabled && [ + ['isBundleVisualizerEnabled', isBundleVisualizerEnabled], + ['rsdoctorClientPort', process.env.RSDOCTOR_CLIENT_PORT], + ['rsdoctorServerPort', process.env.RSDOCTOR_SERVER_PORT], + ] || []), ].filter(Boolean); return pairs.flatMap(([key, val]) => [ diff --git a/packages/rspack/rspack_plugin.js b/packages/rspack/rspack_plugin.js index 4d961ed24a..737e590796 100644 --- a/packages/rspack/rspack_plugin.js +++ b/packages/rspack/rspack_plugin.js @@ -23,7 +23,6 @@ const { ensureRspackInstalled, checkReactInstalled, ensureRspackReactInstalled, - ensureRspackDoctorInstalled, } = require('./lib/dependencies'); const { @@ -37,6 +36,9 @@ const { startRspackServerWatch, runRspackBuild, cleanup, + calculateDevServerPort, + calculateRsdoctorClientPort, + calculateRsdoctorServerPort, } = require('./lib/processes'); const { @@ -66,6 +68,7 @@ const { isMeteorAppDebug, isMeteorAppConfigModernVerbose, isMeteorAppNative, + isMeteorBundleVisualizerProject, } = require('meteor/tools-core/lib/meteor'); const { @@ -112,6 +115,31 @@ if (isMeteorAppRun() || isMeteorAppBuild() || isMeteorAppTest()) { // Configure Meteor settings for Rspack configureMeteorForRspack(); + // Calculate and set the devServerPort at boot + if (!process.env.RSPACK_DEVSERVER_PORT) { + process.env.RSPACK_DEVSERVER_PORT = calculateDevServerPort(); + if (isMeteorAppDebug() || isMeteorAppConfigModernVerbose()) { + logInfo(`[i] Rspack DevServer Port: ${process.env.RSPACK_DEVSERVER_PORT}`); + } + } + + // Calculate and set the Rsdoctor client and server ports at boot only if bundle visualizer is enabled + if (isMeteorBundleVisualizerProject()) { + if (!process.env.RSDOCTOR_CLIENT_PORT) { + process.env.RSDOCTOR_CLIENT_PORT = calculateRsdoctorClientPort(); + if (isMeteorAppDebug() || isMeteorAppConfigModernVerbose()) { + logInfo(`[i] Rsdoctor Client Port: ${process.env.RSDOCTOR_CLIENT_PORT}`); + } + } + + if (!process.env.RSDOCTOR_SERVER_PORT) { + process.env.RSDOCTOR_SERVER_PORT = calculateRsdoctorServerPort(); + if (isMeteorAppDebug() || isMeteorAppConfigModernVerbose()) { + logInfo(`[i] Rsdoctor Server Port: ${process.env.RSDOCTOR_SERVER_PORT}`); + } + } + } + // Register cleanup handler process.on('exit', cleanup); process.on('SIGINT', () => { diff --git a/packages/rspack/rspack_server.js b/packages/rspack/rspack_server.js index 1dc9829777..7772083ab2 100644 --- a/packages/rspack/rspack_server.js +++ b/packages/rspack/rspack_server.js @@ -8,12 +8,11 @@ import { RSPACK_HOT_UPDATE_REGEX, RSPACK_BUNDLES_REGEX, RSPACK_ASSETS_REGEX, - RSPACK_DEVSERVER_PORT, } from "./lib/constants"; if (Meteor.isDevelopment) { // Target URL for the Rspack dev server - const target = `http://localhost:${RSPACK_DEVSERVER_PORT}`; + const target = `http://localhost:${process.env.RSPACK_DEVSERVER_PORT}`; // Proxy HMR websocket upgrade requests WebApp.connectHandlers.use('/ws', diff --git a/packages/tools-core/lib/meteor.js b/packages/tools-core/lib/meteor.js index 5dec528f61..2e00f1f9fb 100644 --- a/packages/tools-core/lib/meteor.js +++ b/packages/tools-core/lib/meteor.js @@ -29,6 +29,14 @@ export function getMeteorAppConfig() { : getMeteorAppPackageJson()?.meteor; } +/** + * Get Meteor's app port + * @returns {false|*} + */ +export function getMeteorAppPort() { + return Package?.meteor?.global?.currentCommand?.options?.['port'] || process.env.PORT || '3000'; +} + /** * Retrieves the modern configuration from the application's package.json. * @returns {Object|undefined} The modern configuration object or undefined if not found. diff --git a/tools/modern-tests/apps/vue/package.json b/tools/modern-tests/apps/vue/package.json index 1d34694d27..d2b0682e35 100644 --- a/tools/modern-tests/apps/vue/package.json +++ b/tools/modern-tests/apps/vue/package.json @@ -17,7 +17,7 @@ "vue-router": "^4.2.5" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rspack/cli": "^1.4.8", "@rspack/core": "^1.4.8", "@tailwindcss/postcss": "^4.1.12", diff --git a/tools/modern-tests/jest.setup.js b/tools/modern-tests/jest.setup.js index 83590326d1..6b950af3a3 100644 --- a/tools/modern-tests/jest.setup.js +++ b/tools/modern-tests/jest.setup.js @@ -1,6 +1,11 @@ // jest.setup.js import chalk from 'chalk'; +// Set fixed ports for all tests +process.env.RSPACK_DEVSERVER_PORT = '8080'; +process.env.RSDOCTOR_CLIENT_PORT = '8888'; +process.env.RSDOCTOR_SERVER_PORT = '8889'; + // This runs before each test beforeEach(() => { const name = expect.getState().currentTestName; diff --git a/tools/static-assets/skel-apollo/package.json b/tools/static-assets/skel-apollo/package.json index c3f8a702f3..a49c0d433c 100644 --- a/tools/static-assets/skel-apollo/package.json +++ b/tools/static-assets/skel-apollo/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@graphql-tools/webpack-loader": "^7.0.0", "@rsdoctor/rspack-plugin": "^1.2.3", - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", "@rspack/plugin-react-refresh": "^1.4.3", diff --git a/tools/static-assets/skel-blaze/package.json b/tools/static-assets/skel-blaze/package.json index ae64482e78..8aa66623b8 100644 --- a/tools/static-assets/skel-blaze/package.json +++ b/tools/static-assets/skel-blaze/package.json @@ -14,7 +14,7 @@ "meteor-node-stubs": "^1.2.12" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-chakra-ui/package.json b/tools/static-assets/skel-chakra-ui/package.json index d1b00f4b37..eadc9bddf0 100644 --- a/tools/static-assets/skel-chakra-ui/package.json +++ b/tools/static-assets/skel-chakra-ui/package.json @@ -21,7 +21,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-full/package.json b/tools/static-assets/skel-full/package.json index 52bc60066d..88f69f39cd 100644 --- a/tools/static-assets/skel-full/package.json +++ b/tools/static-assets/skel-full/package.json @@ -12,7 +12,7 @@ "meteor-node-stubs": "^1.2.12" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-react/package.json b/tools/static-assets/skel-react/package.json index 806556ff16..70cd48a738 100644 --- a/tools/static-assets/skel-react/package.json +++ b/tools/static-assets/skel-react/package.json @@ -15,7 +15,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-solid/package.json b/tools/static-assets/skel-solid/package.json index 0ecd1f51ef..def2402915 100644 --- a/tools/static-assets/skel-solid/package.json +++ b/tools/static-assets/skel-solid/package.json @@ -14,7 +14,7 @@ "picocolors": "^1.1.1" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-svelte/package.json b/tools/static-assets/skel-svelte/package.json index 2f38169f3e..b4894a9101 100644 --- a/tools/static-assets/skel-svelte/package.json +++ b/tools/static-assets/skel-svelte/package.json @@ -13,7 +13,7 @@ "meteor-node-stubs": "^1.2.12" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-tailwind/package.json b/tools/static-assets/skel-tailwind/package.json index 2df7afc9c1..1cbe6f7b56 100644 --- a/tools/static-assets/skel-tailwind/package.json +++ b/tools/static-assets/skel-tailwind/package.json @@ -16,7 +16,7 @@ "react-dom": "^17.0.2" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-typescript/package.json b/tools/static-assets/skel-typescript/package.json index 2a2542758f..e56f37e0ba 100644 --- a/tools/static-assets/skel-typescript/package.json +++ b/tools/static-assets/skel-typescript/package.json @@ -15,7 +15,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0", diff --git a/tools/static-assets/skel-vue/package.json b/tools/static-assets/skel-vue/package.json index dccb833cd5..2fe0b18e48 100644 --- a/tools/static-assets/skel-vue/package.json +++ b/tools/static-assets/skel-vue/package.json @@ -17,7 +17,7 @@ "vue-router": "^4.2.5" }, "devDependencies": { - "@meteorjs/rspack": "^0.0.40", + "@meteorjs/rspack": "^0.0.42", "@rsdoctor/rspack-plugin": "^1.2.3", "@rspack/cli": "^1.5.0", "@rspack/core": "^1.5.0",