Skip to content

Commit c7d6e3a

Browse files
fix: order of imported styles (#443)
1 parent a283b30 commit c7d6e3a

9 files changed

+301
-104
lines changed

src/index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ if (content.locals) {
159159
160160
exported.use = function() {
161161
if (!(refs++)) {
162-
dispose = api(content, options);
162+
var id = ${loaderUtils.stringifyRequest(this, `!!${request}`)};
163+
164+
dispose = api(id, content, options);
163165
}
164166
165167
return exported;
@@ -248,7 +250,8 @@ var options = ${JSON.stringify(options)};
248250
options.insert = ${insert};
249251
options.singleton = ${isSingleton};
250252
251-
var update = api(content, options);
253+
var id = ${loaderUtils.stringifyRequest(this, `!!${request}`)};
254+
var update = api(id, content, options);
252255
253256
var exported = content.locals ? content.locals : {};
254257

src/runtime/injectStylesIntoStyleTag.js

+28-78
Original file line numberDiff line numberDiff line change
@@ -46,70 +46,51 @@ const getTarget = (function getTarget() {
4646
};
4747
})();
4848

49-
function listToStyles(list, options) {
50-
const styles = [];
51-
const newStyles = {};
49+
function addModulesToDom(id, list, options) {
50+
id = options.base ? id + options.base : id;
51+
52+
if (!stylesInDom[id]) {
53+
stylesInDom[id] = [];
54+
}
5255

5356
for (let i = 0; i < list.length; i++) {
5457
const item = list[i];
55-
const id = options.base ? item[0] + options.base : item[0];
56-
const css = item[1];
57-
const media = item[2];
58-
const sourceMap = item[3];
59-
const part = { css, media, sourceMap };
60-
61-
if (!newStyles[id]) {
62-
styles.push((newStyles[id] = { id, parts: [part] }));
58+
const part = { css: item[1], media: item[2], sourceMap: item[3] };
59+
const styleInDomById = stylesInDom[id];
60+
61+
if (styleInDomById[i]) {
62+
styleInDomById[i].updater(part);
6363
} else {
64-
newStyles[id].parts.push(part);
64+
styleInDomById.push({ updater: addStyle(part, options) });
6565
}
6666
}
6767

68-
return styles;
69-
}
70-
71-
function addStylesToDom(styles, options) {
72-
for (let i = 0; i < styles.length; i++) {
73-
const item = styles[i];
74-
const domStyle = stylesInDom[item.id];
75-
let j = 0;
76-
77-
if (domStyle) {
78-
domStyle.refs++;
79-
80-
for (; j < domStyle.parts.length; j++) {
81-
domStyle.parts[j](item.parts[j]);
82-
}
68+
for (let j = list.length; j < stylesInDom[id].length; j++) {
69+
stylesInDom[id][j].updater();
70+
}
8371

84-
for (; j < item.parts.length; j++) {
85-
domStyle.parts.push(addStyle(item.parts[j], options));
86-
}
87-
} else {
88-
const parts = [];
72+
stylesInDom[id].length = list.length;
8973

90-
for (; j < item.parts.length; j++) {
91-
parts.push(addStyle(item.parts[j], options));
92-
}
93-
94-
stylesInDom[item.id] = { id: item.id, refs: 1, parts };
95-
}
74+
if (stylesInDom[id].length === 0) {
75+
delete stylesInDom[id];
9676
}
9777
}
9878

9979
function insertStyleElement(options) {
10080
const style = document.createElement('style');
81+
const attributes = options.attributes || {};
10182

102-
if (typeof options.attributes.nonce === 'undefined') {
83+
if (typeof attributes.nonce === 'undefined') {
10384
const nonce =
10485
typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;
10586

10687
if (nonce) {
107-
options.attributes.nonce = nonce;
88+
attributes.nonce = nonce;
10889
}
10990
}
11091

111-
Object.keys(options.attributes).forEach((key) => {
112-
style.setAttribute(key, options.attributes[key]);
92+
Object.keys(attributes).forEach((key) => {
93+
style.setAttribute(key, attributes[key]);
11394
});
11495

11596
if (typeof options.insert === 'function') {
@@ -179,6 +160,8 @@ function applyToTag(style, options, obj) {
179160

180161
if (media) {
181162
style.setAttribute('media', media);
163+
} else {
164+
style.removeAttribute('media');
182165
}
183166

184167
if (sourceMap && btoa) {
@@ -243,51 +226,18 @@ function addStyle(obj, options) {
243226
};
244227
}
245228

246-
module.exports = (list, options) => {
229+
module.exports = (id, list, options) => {
247230
options = options || {};
248231

249-
options.attributes =
250-
typeof options.attributes === 'object' ? options.attributes : {};
251-
252232
// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
253233
// tags it will allow on a page
254234
if (!options.singleton && typeof options.singleton !== 'boolean') {
255235
options.singleton = isOldIE();
256236
}
257237

258-
const styles = listToStyles(list, options);
259-
260-
addStylesToDom(styles, options);
238+
addModulesToDom(id, list, options);
261239

262240
return function update(newList) {
263-
const mayRemove = [];
264-
265-
for (let i = 0; i < styles.length; i++) {
266-
const item = styles[i];
267-
const domStyle = stylesInDom[item.id];
268-
269-
if (domStyle) {
270-
domStyle.refs--;
271-
mayRemove.push(domStyle);
272-
}
273-
}
274-
275-
if (newList) {
276-
const newStyles = listToStyles(newList, options);
277-
278-
addStylesToDom(newStyles, options);
279-
}
280-
281-
for (let i = 0; i < mayRemove.length; i++) {
282-
const domStyle = mayRemove[i];
283-
284-
if (domStyle.refs === 0) {
285-
for (let j = 0; j < domStyle.parts.length; j++) {
286-
domStyle.parts[j]();
287-
}
288-
289-
delete stylesInDom[domStyle.id];
290-
}
291-
}
241+
addModulesToDom(id, newList || [], options);
292242
};
293243
};

test/manual/index.html

+6-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ <h3>Use/Unuse</h3>
6666
</section>
6767

6868
<section>
69-
<h3>Custom element</h3>
69+
<h2>Order</h2>
70+
<div class="order">BACKGROUND SHOULD BE RED</div>
71+
</section>
72+
73+
<section>
74+
<h2>Custom element</h2>
7075
<custom-square l="100" c="red"></custom-square>
7176
</section>
7277

test/manual/src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import useUnse from './use-unuse.lazy.css';
88
import otherStyleLazy from './other-style.lazy.scss';
99
import componentLazy from './component.lazy.module.css';
1010
import './style.link.css';
11+
import './order.css';
1112
import './custom-square';
1213

1314
console.log('___LOCALS___');

test/manual/src/order-1.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.order {
2+
background: red;
3+
}

test/manual/src/order-2.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.order {
2+
background: blue;
3+
}

test/manual/src/order.css

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@import url('./order-1.css');
2+
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
3+
@import url('./order-2.css');
4+
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
5+
@import url('./order-1.css');
6+
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
7+
@import url('./order-2.css') screen and (min-width: 2000px);
8+
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
9+
10+
.order {
11+
width: 100%;
12+
padding: 10px;
13+
}

test/runtime/__snapshots__/injectStylesIntoStyleTag.test.js.snap

+32
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,38 @@ exports[`addStyle should work with updates #11 1`] = `"<head><title>Title</title
9191
9292
exports[`addStyle should work with updates #11 2`] = `"<head><title>Title</title><style>.foo { color: black }</style><style>.bar { color: white }</style><script src=\\"https://example.com/script.js\\" id=\\"id\\"></script></head><body><h1>Hello world</h1></body>"`;
9393
94+
exports[`addStyle should work with updates #12 1`] = `"<head><title>Title</title><style>.order { color: red }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style>.order { color: blue }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style>.order { color: red }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style media=\\"screen and (min-width: 2000px)\\">.order { color: blue }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style></head><body><h1>Hello world</h1></body>"`;
95+
96+
exports[`addStyle should work with updates #12 2`] = `"<head><title>Title</title><style>.order { color: orange }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style>.order { color: blue }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style>.order { color: orange }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style><style media=\\"screen and (min-width: 2000px)\\">.order { color: blue }</style><style>.@import url(\\"https://fonts.googleapis.com/css?family=Roboto&display=swap\\");</style></head><body><h1>Hello world</h1></body>"`;
97+
98+
exports[`addStyle should work with updates #12 3`] = `"<head><title>Title</title><style>.foo { color: red }</style><style>.bar { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
99+
100+
exports[`addStyle should work with updates #12 4`] = `"<head><title>Title</title></head><body><h1>Hello world</h1></body>"`;
101+
102+
exports[`addStyle should work with updates #13 1`] = `"<head><title>Title</title><style>.red { color: red }</style><style>.green { color: green }</style><style>.blue { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
103+
104+
exports[`addStyle should work with updates #13 2`] = `"<head><title>Title</title><style>.red { color: black }</style><style>.green { color: green }</style><style>.blue { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
105+
106+
exports[`addStyle should work with updates #13 3`] = `"<head><title>Title</title><style>.red { color: black }</style><style>.green { color: black }</style><style>.blue { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
107+
108+
exports[`addStyle should work with updates #13 4`] = `"<head><title>Title</title><style>.red { color: black }</style><style>.green { color: black }</style><style>.blue { color: black }</style></head><body><h1>Hello world</h1></body>"`;
109+
110+
exports[`addStyle should work with updates #13 5`] = `"<head><title>Title</title><style>.green { color: black }</style><style>.blue { color: black }</style></head><body><h1>Hello world</h1></body>"`;
111+
112+
exports[`addStyle should work with updates #13 6`] = `"<head><title>Title</title><style>.blue { color: black }</style></head><body><h1>Hello world</h1></body>"`;
113+
114+
exports[`addStyle should work with updates #13 7`] = `"<head><title>Title</title></head><body><h1>Hello world</h1></body>"`;
115+
116+
exports[`addStyle should work with updates #14 1`] = `"<head><title>Title</title><style>.red { color: red }</style><style>.green { color: green }</style><style>.blue { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
117+
118+
exports[`addStyle should work with updates #14 2`] = `"<head><title>Title</title><style>.red { color: red }</style><style>.green { color: black }</style><style>.blue { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
119+
120+
exports[`addStyle should work with updates #14 3`] = `"<head><title>Title</title><style>.red { color: red }</style><style>.green { color: black }</style><style>.blue { color: blue }</style><style>.white { color: white }</style></head><body><h1>Hello world</h1></body>"`;
121+
122+
exports[`addStyle should work with updates #14 4`] = `"<head><title>Title</title><style>.green { color: black }</style><style>.blue { color: blue }</style><style>.white { color: white }</style></head><body><h1>Hello world</h1></body>"`;
123+
124+
exports[`addStyle should work with updates #14 5`] = `"<head><title>Title</title><style>.green { color: black }</style><style>.white { color: white }</style></head><body><h1>Hello world</h1></body>"`;
125+
94126
exports[`addStyle should work with updates 1`] = `"<head><title>Title</title><style>.foo { color: red }</style></head><body><h1>Hello world</h1></body>"`;
95127
96128
exports[`addStyle should work with updates 2`] = `"<head><title>Title</title><style>.foo { color: blue }</style></head><body><h1>Hello world</h1></body>"`;

0 commit comments

Comments
 (0)