From 1ccd1e7ad18af8e86e764c5281846134295a51ec Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Mon, 30 Mar 2020 12:02:54 -0400 Subject: [PATCH 1/2] order css chunks by filename - fixes #84 --- index.js | 4 +- test/deterministic-css/expected/bundle.css | 5 + .../deterministic-css/expected/bundle.css.map | 16 ++ test/deterministic-css/expected/bundle.js | 187 ++++++++++++++++++ test/deterministic-css/src/A.svelte | 7 + test/deterministic-css/src/App.svelte | 9 + test/deterministic-css/src/B.svelte | 7 + test/deterministic-css/src/C.svelte | 7 + test/deterministic-css/src/main.js | 5 + test/test.js | 37 ++++ 10 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 test/deterministic-css/expected/bundle.css create mode 100644 test/deterministic-css/expected/bundle.css.map create mode 100644 test/deterministic-css/expected/bundle.js create mode 100644 test/deterministic-css/src/A.svelte create mode 100644 test/deterministic-css/src/App.svelte create mode 100644 test/deterministic-css/src/B.svelte create mode 100644 test/deterministic-css/src/C.svelte create mode 100644 test/deterministic-css/src/main.js diff --git a/index.js b/index.js index cb9acb7..f7e1db2 100644 --- a/index.js +++ b/index.js @@ -302,7 +302,9 @@ module.exports = function svelte(options = {}) { const sources = []; const sourcesContent = []; - for (let chunk of cssLookup.values()) { + const chunks = Array.from(cssLookup.keys()).sort().map(key => cssLookup.get(key)); + + for (let chunk of chunks) { if (!chunk.code) continue; result += chunk.code + '\n'; diff --git a/test/deterministic-css/expected/bundle.css b/test/deterministic-css/expected/bundle.css new file mode 100644 index 0000000..5a6a07f --- /dev/null +++ b/test/deterministic-css/expected/bundle.css @@ -0,0 +1,5 @@ +.a.svelte-buqcoz{color:red} +.b.svelte-yjejia{color:green} +.c.svelte-1x2pp8k{color:blue} + +/*# sourceMappingURL=bundle.css.map */ \ No newline at end of file diff --git a/test/deterministic-css/expected/bundle.css.map b/test/deterministic-css/expected/bundle.css.map new file mode 100644 index 0000000..b3d668a --- /dev/null +++ b/test/deterministic-css/expected/bundle.css.map @@ -0,0 +1,16 @@ +{ + "version": 3, + "file": "bundle.css", + "sources": [ + "../src/A.html", + "../src/B.html", + "../src/C.html" + ], + "sourcesContent": [ + "

red

\n\n", + "

green

\n\n", + "

blue

\n\n" + ], + "names": [], + "mappings": "AAGC,EAAE,cAAC,CAAC,AACH,KAAK,CAAE,GAAG,AACX,CAAC;ACFD,EAAE,cAAC,CAAC,AACH,KAAK,CAAE,KAAK,AACb,CAAC;ACFD,EAAE,eAAC,CAAC,AACH,KAAK,CAAE,IAAI,AACZ,CAAC" +} \ No newline at end of file diff --git a/test/deterministic-css/expected/bundle.js b/test/deterministic-css/expected/bundle.js new file mode 100644 index 0000000..19efb41 --- /dev/null +++ b/test/deterministic-css/expected/bundle.js @@ -0,0 +1,187 @@ +(function (internal) { + 'use strict'; + + /* test/deterministic-css/src/A.html generated by Svelte v3.0.0-beta.5 */ + + function create_fragment(ctx) { + var p; + + return { + c() { + p = internal.createElement("p"); + p.textContent = "red"; + p.className = "a svelte-buqcoz"; + }, + + m(target, anchor) { + internal.insert(target, p, anchor); + }, + + p: internal.noop, + i: internal.noop, + o: internal.noop, + + d(detach) { + if (detach) { + internal.detachNode(p); + } + } + }; + } + + class A extends internal.SvelteComponent { + constructor(options) { + super(); + internal.init(this, options, null, create_fragment, internal.safe_not_equal); + } + } + + /* test/deterministic-css/src/B.html generated by Svelte v3.0.0-beta.5 */ + + function create_fragment$1(ctx) { + var p; + + return { + c() { + p = internal.createElement("p"); + p.textContent = "green"; + p.className = "b svelte-yjejia"; + }, + + m(target, anchor) { + internal.insert(target, p, anchor); + }, + + p: internal.noop, + i: internal.noop, + o: internal.noop, + + d(detach) { + if (detach) { + internal.detachNode(p); + } + } + }; + } + + class B extends internal.SvelteComponent { + constructor(options) { + super(); + internal.init(this, options, null, create_fragment$1, internal.safe_not_equal); + } + } + + /* test/deterministic-css/src/C.html generated by Svelte v3.0.0-beta.5 */ + + function create_fragment$2(ctx) { + var p; + + return { + c() { + p = internal.createElement("p"); + p.textContent = "blue"; + p.className = "c svelte-1x2pp8k"; + }, + + m(target, anchor) { + internal.insert(target, p, anchor); + }, + + p: internal.noop, + i: internal.noop, + o: internal.noop, + + d(detach) { + if (detach) { + internal.detachNode(p); + } + } + }; + } + + class C extends internal.SvelteComponent { + constructor(options) { + super(); + internal.init(this, options, null, create_fragment$2, internal.safe_not_equal); + } + } + + /* test/deterministic-css/src/App.html generated by Svelte v3.0.0-beta.5 */ + + function create_fragment$3(ctx) { + var text0, text1, current; + + var a = new A({}); + + var b = new B({}); + + var c = new C({}); + + return { + c() { + a.$$.fragment.c(); + text0 = internal.createText("\n"); + b.$$.fragment.c(); + text1 = internal.createText("\n"); + c.$$.fragment.c(); + }, + + m(target, anchor) { + internal.mount_component(a, target, anchor); + internal.insert(target, text0, anchor); + internal.mount_component(b, target, anchor); + internal.insert(target, text1, anchor); + internal.mount_component(c, target, anchor); + current = true; + }, + + p: internal.noop, + + i(local) { + if (current) return; + a.$$.fragment.i(local); + + b.$$.fragment.i(local); + + c.$$.fragment.i(local); + + current = true; + }, + + o(local) { + a.$$.fragment.o(local); + b.$$.fragment.o(local); + c.$$.fragment.o(local); + current = false; + }, + + d(detach) { + a.$destroy(detach); + + if (detach) { + internal.detachNode(text0); + } + + b.$destroy(detach); + + if (detach) { + internal.detachNode(text1); + } + + c.$destroy(detach); + } + }; + } + + class App extends internal.SvelteComponent { + constructor(options) { + super(); + internal.init(this, options, null, create_fragment$3, internal.safe_not_equal); + } + } + + new App({ + target: document.body + }); + +}(internal)); diff --git a/test/deterministic-css/src/A.svelte b/test/deterministic-css/src/A.svelte new file mode 100644 index 0000000..df7eeb0 --- /dev/null +++ b/test/deterministic-css/src/A.svelte @@ -0,0 +1,7 @@ +

red

+ + \ No newline at end of file diff --git a/test/deterministic-css/src/App.svelte b/test/deterministic-css/src/App.svelte new file mode 100644 index 0000000..996e7d7 --- /dev/null +++ b/test/deterministic-css/src/App.svelte @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/test/deterministic-css/src/B.svelte b/test/deterministic-css/src/B.svelte new file mode 100644 index 0000000..1235cc9 --- /dev/null +++ b/test/deterministic-css/src/B.svelte @@ -0,0 +1,7 @@ +

green

+ + \ No newline at end of file diff --git a/test/deterministic-css/src/C.svelte b/test/deterministic-css/src/C.svelte new file mode 100644 index 0000000..664b2d1 --- /dev/null +++ b/test/deterministic-css/src/C.svelte @@ -0,0 +1,7 @@ +

blue

+ + \ No newline at end of file diff --git a/test/deterministic-css/src/main.js b/test/deterministic-css/src/main.js new file mode 100644 index 0000000..12b47b2 --- /dev/null +++ b/test/deterministic-css/src/main.js @@ -0,0 +1,5 @@ +import App from './App.svelte'; + +new App({ + target: document.body +}); \ No newline at end of file diff --git a/test/test.js b/test/test.js index 1f84095..8441a2f 100644 --- a/test/test.js +++ b/test/test.js @@ -1,3 +1,4 @@ +const fs = require('fs'); const path = require('path'); const sander = require('sander'); const assert = require('assert'); @@ -255,4 +256,40 @@ describe('rollup-plugin-svelte', () => { assert.deepEqual(warnings.map(w => w.code), ['a11y-hidden', 'a11y-distracting-elements']); assert.deepEqual(handled.map(w => w.code), ['a11y-hidden']); }); + + it('bundles CSS deterministically', async () => { + sander.rimrafSync('test/deterministic-css/dist'); + sander.mkdirSync('test/deterministic-css/dist'); + + let css; + + const bundle = await rollup.rollup({ + input: 'test/deterministic-css/src/main.js', + plugins: [ + { + resolveId: async (id) => { + if (/A\.svelte/.test(id)) { + await new Promise(f => setTimeout(f, 50)); + } + } + }, + plugin({ + css: value => { + css = value; + css.write('test/deterministic-css/dist/bundle.css'); + } + }) + ] + }); + + await bundle.write({ + format: 'iife', + file: 'test/deterministic-css/dist/bundle.js' + }); + + assert.equal( + fs.readFileSync('test/deterministic-css/dist/bundle.css', 'utf-8'), + fs.readFileSync('test/deterministic-css/expected/bundle.css', 'utf-8') + ); + }); }); From a9d9fcbb80f83684c923b79b04aab26bd77a66e6 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Mon, 30 Mar 2020 12:08:52 -0400 Subject: [PATCH 2/2] remove unnecessary files --- .../deterministic-css/expected/bundle.css.map | 16 -- test/deterministic-css/expected/bundle.js | 187 ------------------ 2 files changed, 203 deletions(-) delete mode 100644 test/deterministic-css/expected/bundle.css.map delete mode 100644 test/deterministic-css/expected/bundle.js diff --git a/test/deterministic-css/expected/bundle.css.map b/test/deterministic-css/expected/bundle.css.map deleted file mode 100644 index b3d668a..0000000 --- a/test/deterministic-css/expected/bundle.css.map +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": 3, - "file": "bundle.css", - "sources": [ - "../src/A.html", - "../src/B.html", - "../src/C.html" - ], - "sourcesContent": [ - "

red

\n\n", - "

green

\n\n", - "

blue

\n\n" - ], - "names": [], - "mappings": "AAGC,EAAE,cAAC,CAAC,AACH,KAAK,CAAE,GAAG,AACX,CAAC;ACFD,EAAE,cAAC,CAAC,AACH,KAAK,CAAE,KAAK,AACb,CAAC;ACFD,EAAE,eAAC,CAAC,AACH,KAAK,CAAE,IAAI,AACZ,CAAC" -} \ No newline at end of file diff --git a/test/deterministic-css/expected/bundle.js b/test/deterministic-css/expected/bundle.js deleted file mode 100644 index 19efb41..0000000 --- a/test/deterministic-css/expected/bundle.js +++ /dev/null @@ -1,187 +0,0 @@ -(function (internal) { - 'use strict'; - - /* test/deterministic-css/src/A.html generated by Svelte v3.0.0-beta.5 */ - - function create_fragment(ctx) { - var p; - - return { - c() { - p = internal.createElement("p"); - p.textContent = "red"; - p.className = "a svelte-buqcoz"; - }, - - m(target, anchor) { - internal.insert(target, p, anchor); - }, - - p: internal.noop, - i: internal.noop, - o: internal.noop, - - d(detach) { - if (detach) { - internal.detachNode(p); - } - } - }; - } - - class A extends internal.SvelteComponent { - constructor(options) { - super(); - internal.init(this, options, null, create_fragment, internal.safe_not_equal); - } - } - - /* test/deterministic-css/src/B.html generated by Svelte v3.0.0-beta.5 */ - - function create_fragment$1(ctx) { - var p; - - return { - c() { - p = internal.createElement("p"); - p.textContent = "green"; - p.className = "b svelte-yjejia"; - }, - - m(target, anchor) { - internal.insert(target, p, anchor); - }, - - p: internal.noop, - i: internal.noop, - o: internal.noop, - - d(detach) { - if (detach) { - internal.detachNode(p); - } - } - }; - } - - class B extends internal.SvelteComponent { - constructor(options) { - super(); - internal.init(this, options, null, create_fragment$1, internal.safe_not_equal); - } - } - - /* test/deterministic-css/src/C.html generated by Svelte v3.0.0-beta.5 */ - - function create_fragment$2(ctx) { - var p; - - return { - c() { - p = internal.createElement("p"); - p.textContent = "blue"; - p.className = "c svelte-1x2pp8k"; - }, - - m(target, anchor) { - internal.insert(target, p, anchor); - }, - - p: internal.noop, - i: internal.noop, - o: internal.noop, - - d(detach) { - if (detach) { - internal.detachNode(p); - } - } - }; - } - - class C extends internal.SvelteComponent { - constructor(options) { - super(); - internal.init(this, options, null, create_fragment$2, internal.safe_not_equal); - } - } - - /* test/deterministic-css/src/App.html generated by Svelte v3.0.0-beta.5 */ - - function create_fragment$3(ctx) { - var text0, text1, current; - - var a = new A({}); - - var b = new B({}); - - var c = new C({}); - - return { - c() { - a.$$.fragment.c(); - text0 = internal.createText("\n"); - b.$$.fragment.c(); - text1 = internal.createText("\n"); - c.$$.fragment.c(); - }, - - m(target, anchor) { - internal.mount_component(a, target, anchor); - internal.insert(target, text0, anchor); - internal.mount_component(b, target, anchor); - internal.insert(target, text1, anchor); - internal.mount_component(c, target, anchor); - current = true; - }, - - p: internal.noop, - - i(local) { - if (current) return; - a.$$.fragment.i(local); - - b.$$.fragment.i(local); - - c.$$.fragment.i(local); - - current = true; - }, - - o(local) { - a.$$.fragment.o(local); - b.$$.fragment.o(local); - c.$$.fragment.o(local); - current = false; - }, - - d(detach) { - a.$destroy(detach); - - if (detach) { - internal.detachNode(text0); - } - - b.$destroy(detach); - - if (detach) { - internal.detachNode(text1); - } - - c.$destroy(detach); - } - }; - } - - class App extends internal.SvelteComponent { - constructor(options) { - super(); - internal.init(this, options, null, create_fragment$3, internal.safe_not_equal); - } - } - - new App({ - target: document.body - }); - -}(internal));