Skip to content
Permalink
Browse files

feat: bundle specific ref-counting (#467)

* per-bundle ref counting for css dependencies

Fixes  #466
  • Loading branch information...
tivac committed Aug 10, 2018
1 parent 1a1c878 commit 3d38d46d1d4df68e618c50d5340ac92c7a4679be

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -36,6 +36,7 @@
"lerna": "^3.0.0-rc.0",
"modular-css-core": "file:./packages/core",
"pegjs": "^0.10.0",
"read-dir-deep": "^1.0.4",
"rollup": "^0.63.5",
"rollup-plugin-svelte": "^4.2.1",
"shelljs": "^0.8.1",
@@ -177,18 +177,16 @@ module.exports = function(opts) {
}

// First pass is used to calculate JS usage of CSS dependencies
Object.keys(bundles).forEach((entry) => {
Object.entries(bundles).forEach(([ entry, bundle ]) => {
const file = makeFile({
entry,
css : [],
css : new Set(),
});

// Get CSS files being used by each entry point
const css = Object.keys(bundles[entry].modules).filter(filter);
const { modules } = bundle;

if(!css.length) {
return;
}
// Get CSS files being used by each entry point
const css = Object.keys(modules).filter(filter);

// Get dependency chains for each file
css.forEach((start) => {
@@ -197,10 +195,14 @@ module.exports = function(opts) {
start,
];

file.css.push(...used);

used.forEach((dep) => {
usage.set(dep, (usage.get(dep) || 0) + 1);
file.css.add(dep);

if(!usage.has(dep)) {
usage.set(dep, new Set());
}

usage.get(dep).add(entry);
});
});

@@ -209,22 +211,22 @@ module.exports = function(opts) {

if(files.length === 1) {
// Only one entry file means we only need one bundle.
files[0].css = processor.dependencies();
files[0].css = new Set(processor.dependencies());
} else {
// Multiple bundles means ref-counting to find the shared deps
// Second pass removes any dependencies appearing in multiple bundles
files.forEach((file) => {
const { css } = file;

file.css = css.filter((dep) => {
if(usage.get(dep) > 1) {
file.css = new Set([ ...css ].filter((dep) => {
if(usage.get(dep).size > 1) {
common.set(dep, true);

return false;
}

return true;
});
}));
});

// Add any other files that weren't part of a bundle to the common chunk
@@ -238,25 +240,24 @@ module.exports = function(opts) {
if(common.size) {
files.push(makeFile({
entry : options.common,
css : [ ...common.keys() ],
css : new Set([ ...common.keys() ]),
}));
}
}

await Promise.all(
files
.filter(({ css }) => css.length)
.map(async (details) => {
const { base, name, css } = details;
.filter(({ css }) => css.size)
.map(async ({ base, name, css }) => {
const id = this.emitAsset(`${base}.css`);

const result = await processor.output({
to : to.replace(/\[(name|extname)\]/g, (match, field) =>
(field === "name" ? name : ".css")
),
files : css,
files : [ ...css ],
});

this.setAssetSource(id, result.css);

if(options.json) {
@@ -1,115 +1,166 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`/rollup.js code splitting should support dynamic imports 1`] = `
"/* packages/rollup/test/specimens/dynamic-imports/a.css */
Array [
Object {
"file": "a.css",
"text": "/* packages/rollup/test/specimens/dynamic-imports/a.css */
.a {

color: aqua;
}
"
`;

exports[`/rollup.js code splitting should support dynamic imports 2`] = `
"/* packages/rollup/test/specimens/dynamic-imports/b.css */
",
},
Object {
"file": "b.css",
"text": "/* packages/rollup/test/specimens/dynamic-imports/b.css */
.b {
color: blue;
}
"
`;

exports[`/rollup.js code splitting should support dynamic imports 3`] = `
"/* packages/rollup/test/specimens/dynamic-imports/c.css */
",
},
Object {
"file": "c.css",
"text": "/* packages/rollup/test/specimens/dynamic-imports/c.css */
.c {

color: cyan;
}
"
`;

exports[`/rollup.js code splitting should support dynamic imports 4`] = `
"/* packages/rollup/test/specimens/dynamic-imports/d.css */
",
},
Object {
"file": "common.css",
"text": "/* packages/rollup/test/specimens/dynamic-imports/d.css */
.d {
color: darkred;
}
"
",
},
]
`;

exports[`/rollup.js code splitting should support manual chunks 1`] = `
"/* packages/rollup/test/specimens/manual-chunks/a.css */
Array [
Object {
"file": "a.css",
"text": "/* packages/rollup/test/specimens/manual-chunks/a.css */
.a {

color: red;
}
"
`;

exports[`/rollup.js code splitting should support manual chunks 2`] = `
"/* packages/rollup/test/specimens/manual-chunks/b.css */
",
},
Object {
"file": "b.css",
"text": "/* packages/rollup/test/specimens/manual-chunks/b.css */
.b {

color: blue;
}
"
`;

exports[`/rollup.js code splitting should support manual chunks 3`] = `
"/* packages/rollup/test/specimens/manual-chunks/d.css */
",
},
Object {
"file": "common.css",
"text": "/* packages/rollup/test/specimens/manual-chunks/d.css */
/* packages/rollup/test/specimens/manual-chunks/c.css */
.c {
color: green;
background: darkred;
}
"
",
},
]
`;

exports[`/rollup.js code splitting should support splitting up CSS files 1`] = `
"/* packages/rollup/test/specimens/simple.css */
Array [
Object {
"file": "common.css",
"text": "/* packages/rollup/test/specimens/simple.css */
.fooga {
color: red;
}
"
`;

exports[`/rollup.js code splitting should support splitting up CSS files 2`] = `
"/* packages/rollup/test/specimens/dependencies.css */
",
},
Object {
"file": "dependencies.css",
"text": "/* packages/rollup/test/specimens/dependencies.css */
.wooga {

background: blue;
}
"
",
},
]
`;

exports[`/rollup.js code splitting should support splitting up CSS files w/ shared assets 1`] = `
"/* packages/rollup/test/specimens/css-chunks/a.css */
Array [
Object {
"file": "a.css",
"text": "/* packages/rollup/test/specimens/css-chunks/a.css */
.a {

color: aqua;
}
"
`;

exports[`/rollup.js code splitting should support splitting up CSS files w/ shared assets 2`] = `
"/* packages/rollup/test/specimens/css-chunks/b.css */
",
},
Object {
"file": "b.css",
"text": "/* packages/rollup/test/specimens/css-chunks/b.css */
.b {

color: blue;
}
"
`;

exports[`/rollup.js code splitting should support splitting up CSS files w/ shared assets 3`] = `
"/* packages/rollup/test/specimens/css-chunks/c.css */
",
},
Object {
"file": "chunk.css",
"text": "/* packages/rollup/test/specimens/css-chunks/c.css */
.c {

color: cyan;
}
"
",
},
Object {
"file": "common.css",
"text": "/* packages/rollup/test/specimens/css-chunks/shared.css */
.shared {
color: snow;
}
",
},
]
`;

exports[`/rollup.js code splitting should support splitting up CSS files w/ shared assets 4`] = `
"/* packages/rollup/test/specimens/css-chunks/shared.css */
exports[`/rollup.js code splitting shouldn't put bundle-specific CSS in common.css 1`] = `
Array [
Object {
"file": "a.css",
"text": "/* packages/rollup/test/specimens/common-splitting/shared.css */
.shared {
color: snow;
}
"
/* packages/rollup/test/specimens/common-splitting/a.css */
.a {

color: aqua;
}
/* packages/rollup/test/specimens/common-splitting/b.css */
.b {

color: blue;
}
",
},
Object {
"file": "c.css",
"text": "/* packages/rollup/test/specimens/common-splitting/c.css */
.c {
color: cyan;
}
",
},
]
`;
@@ -0,0 +1,5 @@
.a {
composes: shared from "./shared.css";

color: aqua;
}
@@ -0,0 +1,4 @@
import css from "./a.css";
import js from "./b.js";

console.log(css, js);
@@ -0,0 +1,5 @@
.b {
composes: shared from "./shared.css";

color: blue;
}
@@ -0,0 +1,5 @@
import css from "./b.css";

console.log(css);

export default "b.js";
@@ -0,0 +1,3 @@
.c {
color: cyan;
}
@@ -0,0 +1,3 @@
import css from "./c.css";

export default css;
@@ -0,0 +1,3 @@
.shared {
color: snow;
}
Oops, something went wrong.

0 comments on commit 3d38d46

Please sign in to comment.
You can’t perform that action at this time.