From f53cb015782d76aa5e6d9e47c5e4e019bfa3a4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nacho=20Codo=C3=B1er?= Date: Thu, 26 Jun 2025 17:26:22 +0200 Subject: [PATCH] ensure only skip dev modules as part of the build command context --- tools/isobuild/bundler.js | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index dbec9b7215..fc483fbe81 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -1989,6 +1989,23 @@ function hashOfFiles(files) { ClientTarget.prototype[method] = Profile(`ClientTarget#${method}`, ClientTarget.prototype[method]); }); +/** + * Collects all dev-only package names. + * + * @returns {string[]} Array of dev-only package names + */ +function getDevOnlyPackages() { + const targets = global.meteorBundlerTargets || {}; + return ['client', 'server'].flatMap(target => { + const pkgMap = targets[target]?.packageMap?._map; + if (!pkgMap) { + return []; + } + return Object.entries(pkgMap) + .filter(([_, pkg]) => pkg.packageSource?.devOnly) + .map(([name]) => name); + }); +} //////////////////// JsImageTarget and JsImage //////////////////// @@ -2418,6 +2435,10 @@ class JsImage { addNodeModulesDirToObject(nmd, nodeModulesDirectories); }); + var devOnlySkipPackages = []; + const trySkipDevModule = global.currentCommand?.name === 'build' && buildMode === 'production'; + if (trySkipDevModule) devOnlySkipPackages = getDevOnlyPackages(); + // If multiple load files share the same asset, only write one copy of // each. (eg, for app assets). var assetFilesBySha = {}; @@ -2429,6 +2450,11 @@ class JsImage { throw new Error("No targetPath?"); } + // Skip dev-only packages on build for production + if (devOnlySkipPackages.some(_package => item?.targetPath?.includes(`${_package}.js`))) { + continue; + } + var loadItem = { node_modules: {} }; @@ -2543,6 +2569,11 @@ class JsImage { for (const nmd of Object.values(nodeModulesDirectories)) { assert.strictEqual(typeof nmd.preferredBundlePath, "string"); + // Skip dev-only packages on build for production + if (devOnlySkipPackages.includes(nmd?.packageName)) { + continue; + } + // Skip calculating isPortable in 'meteor run' since the // modules are never rebuilt if (includeNodeModules !== 'symlink' && !nmd.isPortable()) { @@ -2558,17 +2589,6 @@ class JsImage { symlink: includeNodeModules === 'symlink' }; - const trySkipDevModule = global.currentCommand?.name === 'build' && buildMode === 'production'; - if (trySkipDevModule) { - const targets = global.meteorBundlerTargets || {}; - const isDevOnlyModule = ['client', 'server'].some(target => - targets[target]?.packageMap?.getInfo(nmd?.packageName)?.packageSource?.devOnly - ); - if (isDevOnlyModule) { - continue; - } - } - const prodPackagePredicate = // This condition essentially means we don't strip devDependencies // when running tests, which is important for use cases like the one