From a57cddffc1ef4bad15ecccadd8725c1042a9039f Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Wed, 11 Sep 2019 00:11:56 -0700 Subject: [PATCH] feat(rollup-rewriter): let loader option be a function (#667) Allows for picking a file out of the bundle to be used, even if the output name is hashed by rollup. --- packages/rollup-rewriter/README.md | 4 +- packages/rollup-rewriter/formats/amd.js | 4 +- packages/rollup-rewriter/formats/es.js | 2 +- packages/rollup-rewriter/formats/system.js | 4 +- packages/rollup-rewriter/rewriter.js | 6 +- .../test/__snapshots__/rewriter.test.js.snap | 288 ++++++++++++++++++ .../rollup-rewriter/test/rewriter.test.js | 29 ++ 7 files changed, 329 insertions(+), 8 deletions(-) diff --git a/packages/rollup-rewriter/README.md b/packages/rollup-rewriter/README.md index c3148f8a7..336a26a1a 100644 --- a/packages/rollup-rewriter/README.md +++ b/packages/rollup-rewriter/README.md @@ -84,9 +84,9 @@ export default { ## Options -### `loader` (string) +### `loader` (string|function) -The `loader` option can be set if you want the plugin to inject a reference to a CSS loader that returns a promise (I like [`lazyload-css`](https://npmjs.com/lazyload-css)). This loader must be available statically, so this option is most useful in `es`/`esm` mode where it can be loaded via `import`. +The `loader` option can be set if you want the plugin to inject a reference to a CSS loader that returns a promise (I like [`lazyload-css`](https://npmjs.com/lazyload-css)). This loader must be available statically, so this option is most useful in `es`/`esm` mode where it can be loaded via `import`. If given a function instead of a string that function will be called once per chunk being modified, it gets passed a single argument of the form `{ chunks }` where `chunks` is the raw rollup output chunks. ### `loadfn` (string) diff --git a/packages/rollup-rewriter/formats/amd.js b/packages/rollup-rewriter/formats/amd.js index 36ffbd8f7..612484609 100644 --- a/packages/rollup-rewriter/formats/amd.js +++ b/packages/rollup-rewriter/formats/amd.js @@ -17,7 +17,7 @@ exports.regex = (deps) => { ); }; -exports.loader = (options, str) => { +exports.loader = ({ content, str }) => { const s = str.toString(); const i = s.indexOf(search); @@ -28,7 +28,7 @@ exports.loader = (options, str) => { // + 1 is for the newline... str.appendRight( i + search.length + 1, - `${options.loader}\n` + `${content}\n` ); }; diff --git a/packages/rollup-rewriter/formats/es.js b/packages/rollup-rewriter/formats/es.js index 390edc8ae..d22834797 100644 --- a/packages/rollup-rewriter/formats/es.js +++ b/packages/rollup-rewriter/formats/es.js @@ -11,7 +11,7 @@ exports.regex = (deps) => { ); }; -exports.loader = (options, str) => str.prepend(`${options.loader}\n`); +exports.loader = ({ content, str }) => str.prepend(`${content}\n`); exports.load = (options, imports, statement) => ` Promise.all([ diff --git a/packages/rollup-rewriter/formats/system.js b/packages/rollup-rewriter/formats/system.js index a3b2e597b..544495d93 100644 --- a/packages/rollup-rewriter/formats/system.js +++ b/packages/rollup-rewriter/formats/system.js @@ -13,7 +13,7 @@ exports.regex = (deps) => { ); }; -exports.loader = (options, str) => { +exports.loader = ({ content, str }) => { const s = str.toString(); const i = s.indexOf(search); @@ -24,7 +24,7 @@ exports.loader = (options, str) => { // + 1 is for the newline... str.appendRight( i + search.length + 1, - `${options.loader}\n` + `${content}\n` ); }; diff --git a/packages/rollup-rewriter/rewriter.js b/packages/rollup-rewriter/rewriter.js index 155afe2cf..3e0a95c75 100644 --- a/packages/rollup-rewriter/rewriter.js +++ b/packages/rollup-rewriter/rewriter.js @@ -75,7 +75,11 @@ module.exports = (opts) => { const str = new MagicString(code); if(options.loader) { - loader(options, str); + const content = typeof options.loader === "function" ? + options.loader({ chunks, options }) : + options.loader; + + loader({ content, str }); } // Yay stateful regexes diff --git a/packages/rollup-rewriter/test/__snapshots__/rewriter.test.js.snap b/packages/rollup-rewriter/test/__snapshots__/rewriter.test.js.snap index 225a2d175..ae6a96e42 100644 --- a/packages/rollup-rewriter/test/__snapshots__/rewriter.test.js.snap +++ b/packages/rollup-rewriter/test/__snapshots__/rewriter.test.js.snap @@ -1031,6 +1031,294 @@ System.register([], function (exports) { } `; +exports[`rollup-rewriter should support loader being a function ("amd") 1`] = ` +Object { + "a": " +define(['require'], function (require) { 'use strict'; +import chunkCountIs8 from \\"./css.js\\"; + + var css = { + \\"a\\": \\"a\\" + }; + + function a() { + console.log(css); + + new Promise(function (resolve, reject) { Promise.all([ + lazyload(\\"./assets/c.css\\"), + new Promise(function (resolve, reject) { require(['./c'], resolve, reject) }) +]) +.then((results) => resolve(results[results.length - 1])) +.catch(reject) }).then(console.log); + } + + return a; + +}); +", + "b": " +define(['require'], function (require) { 'use strict'; +import chunkCountIs8 from \\"./css.js\\"; + + var css = { + \\"b\\": \\"b\\" + }; + + function b() { + console.log(css); + + new Promise(function (resolve, reject) { Promise.all([ + lazyload(\\"./assets/d.css\\"), + new Promise(function (resolve, reject) { require(['./d'], resolve, reject) }) +]) +.then((results) => resolve(results[results.length - 1])) +.catch(reject) }).then(console.log); + } + + return b; + +}); +", + "c": " +define(['exports'], function (exports) { 'use strict'; + + var css = { + \\"c\\": \\"c\\" + }; + + console.log(css); + + exports.default = css; + +}); +", + "d": " +define(['exports'], function (exports) { 'use strict'; + + var css = { + \\"d\\": \\"d\\" + }; + + console.log(css); + + exports.default = css; + +}); +", +} +`; + +exports[`rollup-rewriter should support loader being a function ("es") 1`] = ` +Object { + "a": " +import chunkCountIs8 from \\"./css.js\\"; +var css = { + \\"a\\": \\"a\\" +}; + +function a() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/c.css\\"), + import('./c.js') +]) +.then((results) => results[results.length - 1]).then(console.log); +} + +export default a; +", + "b": " +import chunkCountIs8 from \\"./css.js\\"; +var css = { + \\"b\\": \\"b\\" +}; + +function b() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/d.css\\"), + import('./d.js') +]) +.then((results) => results[results.length - 1]).then(console.log); +} + +export default b; +", + "c": " +var css = { + \\"c\\": \\"c\\" +}; + +console.log(css); + +export default css; +", + "d": " +var css = { + \\"d\\": \\"d\\" +}; + +console.log(css); + +export default css; +", +} +`; + +exports[`rollup-rewriter should support loader being a function ("esm") 1`] = ` +Object { + "a": " +import chunkCountIs8 from \\"./css.js\\"; +var css = { + \\"a\\": \\"a\\" +}; + +function a() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/c.css\\"), + import('./c.js') +]) +.then((results) => results[results.length - 1]).then(console.log); +} + +export default a; +", + "b": " +import chunkCountIs8 from \\"./css.js\\"; +var css = { + \\"b\\": \\"b\\" +}; + +function b() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/d.css\\"), + import('./d.js') +]) +.then((results) => results[results.length - 1]).then(console.log); +} + +export default b; +", + "c": " +var css = { + \\"c\\": \\"c\\" +}; + +console.log(css); + +export default css; +", + "d": " +var css = { + \\"d\\": \\"d\\" +}; + +console.log(css); + +export default css; +", +} +`; + +exports[`rollup-rewriter should support loader being a function ("system") 1`] = ` +Object { + "a": " +System.register([], function (exports, module) { + 'use strict'; +import chunkCountIs8 from \\"./css.js\\"; + return { + execute: function () { + + exports('default', a); + + var css = { + \\"a\\": \\"a\\" + }; + + function a() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/c.css\\"), + module.import('./c.js') +]) +.then((results) => results[results.length - 1]).then(console.log); + } + + } + }; +}); +", + "b": " +System.register([], function (exports, module) { + 'use strict'; +import chunkCountIs8 from \\"./css.js\\"; + return { + execute: function () { + + exports('default', b); + + var css = { + \\"b\\": \\"b\\" + }; + + function b() { + console.log(css); + + Promise.all([ + lazyload(\\"./assets/d.css\\"), + module.import('./d.js') +]) +.then((results) => results[results.length - 1]).then(console.log); + } + + } + }; +}); +", + "c": " +System.register([], function (exports) { + 'use strict'; + return { + execute: function () { + + var css = { + \\"c\\": \\"c\\" + }; + + console.log(css); + exports('default', css); + + } + }; +}); +", + "d": " +System.register([], function (exports) { + 'use strict'; + return { + execute: function () { + + var css = { + \\"d\\": \\"d\\" + }; + + console.log(css); + exports('default', css); + + } + }; +}); +", +} +`; + exports[`rollup-rewriter shouldn't require a loader ("amd") 1`] = ` Object { "a.js": " diff --git a/packages/rollup-rewriter/test/rewriter.test.js b/packages/rollup-rewriter/test/rewriter.test.js index 6274097ad..c8e16b7d5 100644 --- a/packages/rollup-rewriter/test/rewriter.test.js +++ b/packages/rollup-rewriter/test/rewriter.test.js @@ -111,6 +111,35 @@ describe("rollup-rewriter", () => { expect(result).toMatchRollupSnapshot(); }); + + it.each(formats)("should support loader being a function (%p)", async (format) => { + const bundle = await rollup({ + input : [ + require.resolve("./specimens/dynamic-imports/a.js"), + require.resolve("./specimens/dynamic-imports/b.js"), + ], + plugins : [ + css({ + namer, + map, + }), + rewriter({ + loader : ({ chunks }) => `import chunkCountIs${Object.keys(chunks).length} from "./css.js";`, + loadfn : "lazyload", + }), + ], + }); + + const result = await bundle.generate({ + format, + sourcemap, + + assetFileNames, + chunkFileNames, + }); + + expect(result).toMatchRollupCodeSnapshot(); + }); it.each(formats)("should only rewrite when necessary (%p)", async (format) => { const bundle = await rollup({