From 358f4541d9167fbf51854dedbe985c5ca3945af7 Mon Sep 17 00:00:00 2001 From: zodern Date: Mon, 4 Feb 2019 11:35:21 -0600 Subject: [PATCH 1/4] Update source-map to 0.5.7. --- scripts/dev-bundle-tool-package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index f3f5e2bf92..0d79515abf 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -34,7 +34,7 @@ var packageJson = { fstream: "https://github.com/meteor/fstream/tarball/cf4ea6c175355cec7bee38311e170d08c4078a5d", tar: "2.2.1", kexec: "3.0.0", - "source-map": "0.5.3", + "source-map": "0.5.7", chalk: "0.5.1", sqlite3: "3.1.8", netroute: "1.0.2", From 7b2adcb9dab97a97460309f7eb418a738a784741 Mon Sep 17 00:00:00 2001 From: zodern Date: Tue, 5 Feb 2019 10:35:37 -0600 Subject: [PATCH 2/4] Cache stringified prelinked output for dynamic files. --- tools/isobuild/linker.js | 42 ++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 697460fcf3..159be29748 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -21,6 +21,10 @@ const APP_PRELINK_CACHE = new LRU({ return prelinked.source.length + sourceMapLength(prelinked.sourceMap); } }); +// Caches code with source map for dynamic files +const DYNAMIC_PRELINKED_OUTPUT_CACHE = new LRU({ + max: Math.pow(2, 11) +}); var packageDot = function (name) { if (/^[a-zA-Z][a-zA-Z0-9]*$/.exec(name)) { @@ -271,11 +275,7 @@ _.extend(Module.prototype, { if (file.isDynamic()) { const servePath = files.pathJoin("dynamic", file.absModuleId); const { code: source, map } = - file.getPrelinkedOutput({ - sourceWidth: sourceWidth, - }).toStringWithSourceMap({ - file: servePath, - }); + getOutputWithSourceMapCached(file, servePath, { sourceWidth }) results.push({ source, @@ -812,12 +812,15 @@ const getPrelinkedOutputCached = require("optimism").wrap( } return new sourcemap.SourceNode(null, null, null, chunks); - }, { // Store at most 4096 Files worth of prelinked output in this cache. max: Math.pow(2, 12), makeCacheKey(file, options) { + if (options.disableCache) { + return; + } + return JSON.stringify({ hash: file._inputHash, arch: file.module.bundleArch, @@ -829,6 +832,33 @@ const getPrelinkedOutputCached = require("optimism").wrap( } ); +function getOutputWithSourceMapCached (file,servePath, options) { + const key = JSON.stringify({ + hash: file._inputHash, + arch: file.module.bundleArch, + bare: file.bare, + servePath: file.servePath, + dynamic: file.isDynamic(), + options, + }); + + if (DYNAMIC_PRELINKED_OUTPUT_CACHE.has(key)) { + return DYNAMIC_PRELINKED_OUTPUT_CACHE.get(key); + } + + + const result = file.getPrelinkedOutput({ + ...options, + disableCache: true + }) + .toStringWithSourceMap({ + file: servePath, + }); + DYNAMIC_PRELINKED_OUTPUT_CACHE.set(key, result); + + return result; +} + // Given a list of lines (not newline-terminated), returns a string placing them // in a pretty banner of width bannerWidth. All lines must have length at most // (bannerWidth - 6); if bannerWidth is not provided, the smallest width that From 95a1f54ccef068327c37dc5aba97b8b25189dcb7 Mon Sep 17 00:00:00 2001 From: zodern Date: Tue, 5 Feb 2019 11:12:14 -0600 Subject: [PATCH 3/4] Skip regenerating main bundle when only a dynamic file changed. --- tools/isobuild/linker.js | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 159be29748..a385838cd1 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -26,6 +26,11 @@ const DYNAMIC_PRELINKED_OUTPUT_CACHE = new LRU({ max: Math.pow(2, 11) }); +// Caches main bundle for client architectures that have dynamic imports +const PRELINKED_MAIN_CACHE = new LRU({ + max: Math.pow(2, 3) +}); + var packageDot = function (name) { if (/^[a-zA-Z][a-zA-Z0-9]*$/.exec(name)) { return "Package." + name; @@ -209,6 +214,54 @@ _.extend(Module.prototype, { }); } + // Caching is only useful when there are dynamic files. + const canCache = results.find(result => result.dynamic) && self.useGlobalNamespace; + let inputHash; + let key; + + // When only dynamic files changed, reuse the main result from + // the last time it was generated + if (canCache) { + const files = []; + + self.files.forEach(file => { + if (file.bare || !file.isDynamic()) { + files.push({ + hash: file._inputHash, + meteorInstallOptions: file.meteorInstallOptions, + sourceMap: !!file.sourceMap, + mainModule: file.imported, + alias: file.alias, + lazy: file.lazy, + bare: file.bare + }); + } + }); + inputHash = watch.sha1(JSON.stringify({ + useGlobalNamespace: this.useGlobalNamespace, + combinedServePath: this.combinedServePath, + name: self.name, + files + })); + key = `${self.bundleArch}-${self.name}`; + + // By using a more general key only the latest result is stored + // The inputHash is used to know when the cache is stale + if (PRELINKED_MAIN_CACHE.has(key)) { + let { + inputHash: cachedInputHash, + result: cachedResult + } = PRELINKED_MAIN_CACHE.get(key); + + if (cachedInputHash === inputHash) { + result.source = cachedResult.source; + result.sourceMap = cachedResult.sourceMap; + + return results; + } + } + } + var node = new sourcemap.SourceNode(null, null, null, chunks); Profile.time( @@ -232,6 +285,13 @@ _.extend(Module.prototype, { } ); + if (canCache) { + PRELINKED_MAIN_CACHE.set(key, { + inputHash, + result + }); + } + return results; }), From bb564dd93f31d40456966cc7de4b67a90ba9a808 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 28 Feb 2019 14:41:14 -0500 Subject: [PATCH 4/4] Address my own (minor) review feedback. --- tools/isobuild/linker.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index a385838cd1..4f115190fc 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -215,11 +215,11 @@ _.extend(Module.prototype, { } // Caching is only useful when there are dynamic files. - const canCache = results.find(result => result.dynamic) && self.useGlobalNamespace; + const canCache = self.useGlobalNamespace && results.find(result => result.dynamic); + const key = `${self.bundleArch}-${self.name}`; let inputHash; - let key; - // When only dynamic files changed, reuse the main result from + // When only dynamic files changed, reuse the main result from // the last time it was generated if (canCache) { const files = []; @@ -237,13 +237,13 @@ _.extend(Module.prototype, { }); } }); + inputHash = watch.sha1(JSON.stringify({ useGlobalNamespace: this.useGlobalNamespace, combinedServePath: this.combinedServePath, name: self.name, files })); - key = `${self.bundleArch}-${self.name}`; // By using a more general key only the latest result is stored // The inputHash is used to know when the cache is stale @@ -892,7 +892,7 @@ const getPrelinkedOutputCached = require("optimism").wrap( } ); -function getOutputWithSourceMapCached (file,servePath, options) { +function getOutputWithSourceMapCached(file, servePath, options) { const key = JSON.stringify({ hash: file._inputHash, arch: file.module.bundleArch, @@ -906,14 +906,13 @@ function getOutputWithSourceMapCached (file,servePath, options) { return DYNAMIC_PRELINKED_OUTPUT_CACHE.get(key); } - const result = file.getPrelinkedOutput({ ...options, disableCache: true - }) - .toStringWithSourceMap({ - file: servePath, - }); + }).toStringWithSourceMap({ + file: servePath, + }); + DYNAMIC_PRELINKED_OUTPUT_CACHE.set(key, result); return result;