Skip to content

Commit ba3e96e

Browse files
authored
Merge pull request #29 from jerekshoe/retain-order-during-watch
Nested import handling
2 parents b569df9 + eb2487e commit ba3e96e

16 files changed

+100
-23
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
"scripts": {
99
"build": "rollup -c",
1010
"dev": "rollup -cw",
11-
"test:simple": "cd test/simple && rm -f output.* && rollup -c && cmp output.js ../expected.js && cmp output.css expected.css && cd ../..",
12-
"test": "npm run test:simple",
11+
"test:nested": "cd test/nested && rm -rf output && rollup -c && cmp output/bundle.js expected/bundle.js && cmp output/bundle.css expected/bundle.css && cd ../..",
12+
"test:simple": "cd test/simple && rm -rf output && rollup -c && cmp output/output.js expected.js && cmp output/output.css expected.css && cd ../..",
13+
"test": "npm run test:simple && npm run test:nested",
1314
"lint": "prettier rollup.config.js src/**",
1415
"prepare": "npm run build",
1516
"prepublish": "npm run build"

src/index.js

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,43 @@
11
import { createFilter } from '@rollup/pluginutils'
22

3+
var arraysEqual = function(a, b) {
4+
if (a.length !== b.length) return false
5+
6+
for (let i = a.length; i--;) {
7+
if (a[i] !== b[i]) return false
8+
}
9+
10+
return true
11+
}
12+
313
export default function css(options = {}) {
414
const filter = createFilter(options.include || ['**/*.css'], options.exclude)
515
const styles = {}
6-
const order = []
716
let dest = options.output
8-
let changes = 0
17+
let hasChanged = false
18+
let prevIds = []
19+
20+
// Get all CSS modules in the order that they were imported
21+
const getCSSModules = (id, getModuleInfo, modules = new Set()) => {
22+
if (modules.has(id)) {
23+
return new Set()
24+
}
25+
26+
if (filter(id)) modules.add(id)
27+
28+
// Recursively retrieve all of imported CSS modules
29+
getModuleInfo(id).importedIds.forEach(importId => {
30+
modules = new Set([].concat(Array.from(modules), Array.from(getCSSModules(importId, getModuleInfo, modules))))
31+
});
32+
33+
return modules
34+
};
935

1036
return {
1137
name: 'css',
38+
buildStart() {
39+
hasChanged = false
40+
},
1241
transform(code, id) {
1342
if (!filter(id)) {
1443
return
@@ -22,32 +51,37 @@ export default function css(options = {}) {
2251
}
2352
}
2453

25-
// Track the order that each stylesheet is imported.
26-
if (!order.includes(id)) {
27-
order.push(id)
28-
}
29-
3054
// Keep track of every stylesheet
3155
// Check if it changed since last render
56+
// NOTE: If we are in transform block, we can assume styles[id] !== code, right?
3257
if (styles[id] !== code && (styles[id] || code)) {
3358
styles[id] = code
34-
changes++
59+
hasChanged = true
3560
}
3661

3762
return ''
3863
},
3964
generateBundle(opts, bundle) {
40-
// No stylesheet needed
41-
if (!changes || options.output === false) {
42-
return
65+
const ids = []
66+
67+
// Determine import order of files
68+
for (const file in bundle) {
69+
const root = bundle[file].facadeModuleId
70+
const modules = getCSSModules(root, this.getModuleInfo)
71+
ids.push(...Array.from(modules))
4372
}
44-
changes = 0
4573

46-
// Combine all stylesheets, respecting import order
74+
// If the files are imported in the same order and there are no changes
75+
// or options.output is false, there is no work to be done
76+
if (arraysEqual(prevIds, ids) && !hasChanged || options.output === false) return
77+
prevIds = ids
78+
4779
let css = ''
48-
for (let x = 0; x < order.length; x++) {
49-
const id = order[x]
50-
css += styles[id] || ''
80+
81+
// Combine all stylesheets, respecting import order
82+
for (const index in ids) {
83+
let id = ids[index]
84+
css += styles[id] + '\n' || ''
5185
}
5286

5387
// Emit styles through callback

test/nested/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## Test Case
2+
This is to test that nested imports are bundled in the proper order

test/nested/css/b.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
background-color: blue;
3+
}

test/nested/css/g.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
background-color: green;
3+
}

test/nested/css/r.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
background-color: red;
3+
}

test/nested/expected/bundle.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
body {
2+
background-color: blue;
3+
}
4+
body {
5+
background-color: red;
6+
}
7+
body {
8+
background-color: green;
9+
}

test/nested/expected/bundle.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
console.log('This should happen first');
2+
3+
console.log('This should happen second');

test/nested/input.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import './js/b.js';
2+
import './css/r.css';
3+
import './css/g.css';
4+
5+
console.log('This should happen second');

test/nested/js/b.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import '../css/b.css';
2+
3+
console.log('This should happen first');

test/nested/rollup.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import css from '../../src/index.js'
2+
3+
export default {
4+
input: 'input.js',
5+
output: {
6+
file: 'output/bundle.js',
7+
format: 'esm'
8+
},
9+
plugins: [
10+
css({ output: 'bundle.css' })
11+
]
12+
}
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
.rollup {
22
color: green;
33
user-select: none;
4-
}
4+
}
File renamed without changes.

test/simple/output.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/simple/rollup.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import css from '../../src/index.js'
22

33
export default {
4-
input: '../input.js',
4+
input: 'input.js',
55
output: {
6-
file: 'output.js',
6+
file: 'output/output.js',
77
format: 'esm'
88
},
99
plugins: [
10-
css()
10+
css({ output: 'output.css' })
1111
]
1212
}

0 commit comments

Comments
 (0)