thgh / rollup-plugin-css-only

Rollup plugin that bundles imported css
MIT License
116 stars 27 forks source link

CSS output is not deterministic #42

Closed nmattia closed 2 years ago

nmattia commented 2 years ago

Hi,

I'm working on a Svelte app and using this plugin with rollup. I had the following setup:

...,
css({ output: "bundle.css" }),

which does create bundle.css, but unfortunately the output changes on every run. Here I diff the output between two runs, after having inserted newlines between the CSS blocks:

diff bundle1.clean.css bundle2.clean.css
87,90d86
< div.svelte-1vldqp5.svelte-1vldqp5{display:inline-grid;grid-template-columns:repeat(2, auto);grid-gap:5px;align-items:baseline}
< div.svelte-1vldqp5 span.svelte-1vldqp5:first-of-type{font-weight:700;font-size:var(--icp-font-size, var(--font-size-h3));color:var(--gray-50)}
< @media(min-width: 768px){div.svelte-1vldqp5.svelte-1vldqp5{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-end;grid-gap:0}
< }
140a137,140
> div.svelte-1vldqp5.svelte-1vldqp5{display:inline-grid;grid-template-columns:repeat(2, auto);grid-gap:5px;align-items:baseline}
> div.svelte-1vldqp5 span.svelte-1vldqp5:first-of-type{font-weight:700;font-size:var(--icp-font-size, var(--font-size-h3));color:var(--gray-50)}
> @media(min-width: 768px){div.svelte-1vldqp5.svelte-1vldqp5{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-end;grid-gap:0}
> }
152,153c152,155
< small.svelte-1w6ak3{word-break:break-all}
< p.svelte-1w6ak3{margin:0}
---
> .filter.svelte-1f2mdt{display:flex;justify-content:space-between;align-items:flex-start;background:var(--gray-600);padding:var(--padding);margin-bottom:calc(2 * var(--padding));border-radius:var(--border-radius)}
> .filter.svelte-1f2mdt:active,.filter.svelte-1f2mdt:focus,.filter.svelte-1f2mdt:hover{background:rgba(var(--light-background-rgb), 0.3)}
> .options.svelte-1f2mdt{display:flex;flex-wrap:wrap}
> .expand.svelte-1f2mdt{min-width:30px;min-height:30px}
168,171d169
< .filter.svelte-1f2mdt{display:flex;justify-content:space-between;align-items:flex-start;background:var(--gray-600);padding:var(--padding);margin-bottom:calc(2 * var(--padding));border-radius:var(--border-radius)}
< .filter.svelte-1f2mdt:active,.filter.svelte-1f2mdt:focus,.filter.svelte-1f2mdt:hover{background:rgba(var(--light-background-rgb), 0.3)}
< .options.svelte-1f2mdt{display:flex;flex-wrap:wrap}
< .expand.svelte-1f2mdt{min-width:30px;min-height:30px}
182c180,181
< button.svelte-meaks2{justify-self:flex-end}
---
> small.svelte-1w6ak3{word-break:break-all}
> p.svelte-1w6ak3{margin:0}
185a185
> button.svelte-meaks2{justify-self:flex-end}

Now I'm working around the issue by sorting first:

css({ output: (styles, stylesNodes) => {
    // stylesNodes is a map from filename (e.g.
    // 'src/lib/components/ui/FiltersCard.css') to css content (e.g.
    // '.filter.svelte-1f2mdt{display:flex;justify-content:space-between;...').
    if(!fs.existsSync("public/build")) {
        fs.mkdirSync("public/build");
    }
    fs.writeFileSync("public/build/bundle.css", Object.values(stylesNodes).sort().join(''));
}}),

(somewhat related: is there a way I could simply return a string here? then I wouldn't need to re-add public/build which is the directory I specify with output.file = "public/build/bundle.js")

Thanks!

thgh commented 2 years ago

Deterministic output has been added in v4 🎉