From 7aa7baf7e30661dab89a58695f55ebac4e6d06a7 Mon Sep 17 00:00:00 2001 From: Addy Osmani Date: Sun, 22 Jan 2017 18:27:10 -0800 Subject: [PATCH] Add support for dynamic chunk names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This POC adds support for preloading and prefetching JS chunks generated as part of code-splitting. Usage is as follows: // Preload dynamic chunks in the document dynamicChunks: { preload: true } // Prefetch chunks on the document dynamicChunks: { prefetch: true } // Preload chunks in the document dynamicChunks: { preload: true, position: ‘body’ } same goes for prefetch. --- index.js | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 2dd48b6..7e8ef30 100644 --- a/index.js +++ b/index.js @@ -117,6 +117,18 @@ const updateSrcElement = (options, tag) => { return tag; }; +const addCustomResourceHints = (options, scripts) => { + let hints = []; + scripts.forEach(script => { + if (options.dynamicChunks.preload) { + hints.push(createResourceHint('preload', null, script)); + } else if (options.dynamicChunks.prefetch) { + hints.push(createResourceHint('prefetch', null, script)); + } + }); + return hints; +}; + const addResourceHints = (options, tags) => { return tags .filter(hasScriptName) @@ -133,13 +145,13 @@ const addResourceHints = (options, tags) => { ); }; -const createResourceHint = (rel, tag) => { +const createResourceHint = (rel, tag, customPath) => { return { tagName: 'link', closeTag: true, attributes: { rel: rel, - href: getRawScriptName(tag), + href: customPath || getRawScriptName(tag), as: 'script' } }; @@ -176,6 +188,30 @@ class ScriptExtHtmlWebpackPlugin { addResourceHints(options, pluginArgs.body) ]); } + if (shouldUpdateElements(options)) { + if (options.dynamicChunks) { + const chunkRegEx = /^chunk[.]/; + // Get the paths to dynamic chunks + const extractedChunks = compilation + .chunks + .reduce((chunks, chunk) => chunks.concat(chunk.files), []) + .filter(chunk => chunkRegEx.test(chunk)); + // Default to 'head' as the position + if (options.dynamicChunks.position === 'body') { + debug(`${EVENT}: injecting resource hints`); + pluginArgs.body = concat([ + pluginArgs.body, + addCustomResourceHints(options, extractedChunks) + ]); + } else { + debug(`${EVENT}: injecting resource hints`); + pluginArgs.head = concat([ + pluginArgs.head, + addCustomResourceHints(options, extractedChunks) + ]); + } + } + } debug(`${EVENT}: completed`); callback(null, pluginArgs); } catch (err) {