enhance static file handling for Rspack assets

This commit is contained in:
Nacho Codoñer
2025-09-23 12:26:06 +02:00
parent 3fe1cf682d
commit e53f76baee

View File

@@ -1,33 +1,36 @@
import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';
import { WebApp, WebAppInternals } from 'meteor/webapp';
import { shuffleString } from 'meteor/tools-core/lib/string';
import { createProxyMiddleware } from 'http-proxy-middleware';
import path from 'path';
import { parse as parseUrl } from 'url';
import {
RSPACK_CHUNKS_CONTEXT,
RSPACK_ASSETS_CONTEXT,
RSPACK_HOT_UPDATE_REGEX,
} from "./lib/constants";
// Define constants for both development and production
const rspackChunksContext = process.env.RSPACK_CHUNKS_CONTEXT || RSPACK_CHUNKS_CONTEXT;
const rspackAssetsContext = process.env.RSPACK_ASSETS_CONTEXT || RSPACK_ASSETS_CONTEXT;
/**
* Regex pattern for rspack bundles
* @constant {RegExp}
*/
const RSPACK_CHUNKS_REGEX = new RegExp(
`^\/${rspackChunksContext}\/(.+)$`,
);
/**
* Regex pattern for rspack assets
* @constant {RegExp}
*/
const RSPACK_ASSETS_REGEX = new RegExp(
`^\/${rspackAssetsContext}\/(.+)$`,
);
if (Meteor.isDevelopment) {
const rspackChunksContext = process.env.RSPACK_CHUNKS_CONTEXT || RSPACK_CHUNKS_CONTEXT;
const rspackAssetsContext = process.env.RSPACK_ASSETS_CONTEXT || RSPACK_ASSETS_CONTEXT;
/**
* Regex pattern for rspack bundles
* @constant {RegExp}
*/
const RSPACK_CHUNKS_REGEX = new RegExp(
`^\/${rspackChunksContext}\/(.+)$`,
);
/**
* Regex pattern for rspack assets
* @constant {RegExp}
*/
const RSPACK_ASSETS_REGEX = new RegExp(
`^\/${rspackAssetsContext}\/(.+)$`,
);
// Target URL for the Rspack dev server
const target = `http://localhost:${process.env.RSPACK_DEVSERVER_PORT}`;
@@ -121,3 +124,80 @@ if (Meteor.isDevelopment) {
// Enable client reload on server startup
enableClientReloadOnServerStart();
}
/**
* Register a single rspack static asset with WebAppInternals.staticFilesByArch
* @param {string} arch - The architecture to register the asset for
* @param {string} pathname - The pathname of the asset
* @param {string} filePath - The absolute path to the asset on disk
* @returns {Object} The static file info object
*/
function registerRspackStaticAsset(arch, pathname, filePath) {
// Ensure the architecture exists in staticFilesByArch
if (!WebAppInternals.staticFilesByArch[arch]) {
WebAppInternals.staticFilesByArch[arch] = Object.create(null);
}
// Get the static files object for this architecture
const staticFiles = WebAppInternals.staticFilesByArch[arch];
// Skip if already registered
if (staticFiles[pathname]) {
// Ensure the entry is marked as cacheable
staticFiles[pathname].cacheable = true;
return staticFiles[pathname];
}
// Determine file type based on extension
const type = pathname.endsWith(".js") ? "js" :
pathname.endsWith(".css") ? "css" :
pathname.endsWith(".json") ? "json" : undefined;
// Extract hash from filename (assuming it's the second part after splitting by '.')
const filename = pathname.split("/").pop();
const hash = filename.split(".")[1];
// Register the asset
staticFiles[pathname] = {
absolutePath: filePath,
cacheable: true, // Most rspack assets are cacheable
hash,
type
};
return staticFiles[pathname];
}
// Store the original staticFilesMiddleware
const originalStaticFilesMiddleware = WebAppInternals.staticFilesMiddleware;
// Handle rspack assets on-demand to add Meteor's static files headers
WebAppInternals.staticFilesMiddleware = async function(staticFilesByArch, req, res, next) {
const pathname = parseUrl(req.url).pathname;
try {
// Check if this is a rspack asset request
const chunksMatch = pathname.match(RSPACK_CHUNKS_REGEX);
const assetsMatch = pathname.match(RSPACK_ASSETS_REGEX);
if (chunksMatch || assetsMatch) {
const cwd = process.cwd();
const architectures = ["web.browser", "web.browser.legacy", "web.cordova"];
WebApp.categorizeRequest(req);
// Try to find the file on disk
const context = chunksMatch ? rspackChunksContext : rspackAssetsContext;
const filename = (chunksMatch ? chunksMatch[1] : assetsMatch[1]);
const filePath = path.join(cwd, context, filename);
architectures.forEach(archName => {
registerRspackStaticAsset(archName, pathname, filePath);
});
}
} catch (e) {
console.error(`Error handling rspack asset: ${e.message}`);
}
// Call the original middleware
return originalStaticFilesMiddleware(staticFilesByArch, req, res, next);
};