diff --git a/packages/babel-compiler/babel-compiler.js b/packages/babel-compiler/babel-compiler.js index f8d6217d54..f9ea38f32f 100644 --- a/packages/babel-compiler/babel-compiler.js +++ b/packages/babel-compiler/babel-compiler.js @@ -1,6 +1,8 @@ var semver = Npm.require("semver"); var JSON5 = Npm.require("json5"); var SWC = Npm.require("@swc/core"); +var fs = Npm.require('fs'); +var path = Npm.require('path'); /** * A compiler that can be instantiated with features and used inside @@ -51,7 +53,9 @@ BCp.processFilesForTarget = function (inputFiles) { // Returns an object suitable for passing to inputFile.addJavaScript, or // null to indicate there was an error, and nothing should be added. BCp.processOneFileForTarget = function (inputFile, source) { + var self = this; // capture context this._babelrcCache = this._babelrcCache || Object.create(null); + this._transformCache = this._transformCache || Object.create(null); if (typeof source !== "string") { // Other compiler plugins can call processOneFileForTarget with a @@ -122,23 +126,18 @@ BCp.processOneFileForTarget = function (inputFile, source) { }, }; - this.inferTypeScriptConfig( - features, inputFile, cacheOptions.cacheDeps); + this.inferTypeScriptConfig(features, inputFile, cacheOptions.cacheDeps); var babelOptions = Babel.getDefaultOptions(features); babelOptions.caller = { name: "meteor", arch }; - this.inferExtraBabelOptions( - inputFile, - babelOptions, - cacheOptions.cacheDeps - ); + this.inferExtraBabelOptions(inputFile, babelOptions, cacheOptions.cacheDeps); babelOptions.sourceMaps = true; babelOptions.filename = babelOptions.sourceFileName = packageName - ? "packages/" + packageName + "/" + inputFilePath - : inputFilePath; + ? "packages/" + packageName + "/" + inputFilePath + : inputFilePath; if (this.modifyBabelConfig) { this.modifyBabelConfig(babelOptions, inputFile); @@ -146,19 +145,38 @@ BCp.processOneFileForTarget = function (inputFile, source) { try { var result = profile('Babel.compile', function () { - let compilation; + // Determine if SWC should be used based on package and file criteria. + const packagesSkipSwc = []; + const fileSkipSwc = ['webapp_server.js']; // top level await + const shouldUseSwc = !packagesSkipSwc.includes(packageName) && + !fileSkipSwc.includes(inputFilePath); + + // Create a cache key based on the source hash and the compiler used. + const cacheKey = `${toBeAdded.hash}-${shouldUseSwc ? 'swc' : 'babel'}`; + + // Check RAM cache + let compilation = self._transformCache[cacheKey]; + // Check file system cache if enabled + if (!compilation && self.cacheDirectory) { + const cacheFilePath = path.join(self.cacheDirectory, 'compilation-cache', cacheKey + '.json'); + if (fs.existsSync(cacheFilePath)) { + try { + compilation = JSON.parse(fs.readFileSync(cacheFilePath, 'utf8')); + self._transformCache[cacheKey] = compilation; + } catch (e) { + // If reading/parsing the cache fails, ignore and continue. + } + } + } + // Return cached result if found. + if (compilation) { + return compilation; + } + + // Perform compilation try { - const packagesSkipSwc = []; - const fileSkipSwc = ['webapp_server.js']; // top level await - - // Determine if SWC should be used based on package and file criteria. - const shouldUseSwc = - !packagesSkipSwc.includes(packageName) && - !fileSkipSwc.includes(inputFilePath); - if (shouldUseSwc) { - const isTypescriptSyntax = - inputFilePath.endsWith('.ts') || inputFilePath.endsWith('.tsx'); + const isTypescriptSyntax = inputFilePath.endsWith('.ts') || inputFilePath.endsWith('.tsx'); const hasTSXSupport = inputFilePath.endsWith('.tsx'); const hasJSXSupport = inputFilePath.endsWith('.jsx'); @@ -190,6 +208,17 @@ BCp.processOneFileForTarget = function (inputFile, source) { compilation = Babel.compile(source, babelOptions, cacheOptions); } + // Save result in caches + self._transformCache[cacheKey] = compilation; + if (self.cacheDirectory) { + const cacheFilePath = path.join(self.cacheDirectory, 'compilation-cache', cacheKey + '.json'); + try { + fs.mkdirSync(path.dirname(cacheFilePath), { recursive: true }); + fs.writeFileSync(cacheFilePath, JSON.stringify(compilation), 'utf8'); + } catch (e) { + // If file caching fails, ignore the error. + } + } return compilation; }); } catch (e) {