implement dynamic port calculation for Rspack and Rsdoctor

This commit is contained in:
Nacho Codoñer
2025-09-05 09:16:35 +02:00
parent 4d9347651e
commit bdacd446b9
20 changed files with 114 additions and 28 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -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)),
}),
]
: [];

View File

@@ -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

View File

@@ -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]) => [

View File

@@ -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', () => {

View File

@@ -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',

View File

@@ -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.

View File

@@ -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",

View File

@@ -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;

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",