Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: order of imported styles #443

Merged
merged 9 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ if (content.locals) {

exported.use = function() {
if (!(refs++)) {
dispose = api(content, options);
var id = ${loaderUtils.stringifyRequest(this, `!!${request}`)};

dispose = api(id, content, options);
}

return exported;
Expand Down Expand Up @@ -248,7 +250,8 @@ var options = ${JSON.stringify(options)};
options.insert = ${insert};
options.singleton = ${isSingleton};

var update = api(content, options);
var id = ${loaderUtils.stringifyRequest(this, `!!${request}`)};
var update = api(id, content, options);

var exported = content.locals ? content.locals : {};

Expand Down
106 changes: 28 additions & 78 deletions src/runtime/injectStylesIntoStyleTag.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,70 +46,51 @@ const getTarget = (function getTarget() {
};
})();

function listToStyles(list, options) {
const styles = [];
const newStyles = {};
function addModulesToDom(id, list, options) {
id = options.base ? id + options.base : id;

if (!stylesInDom[id]) {
stylesInDom[id] = [];
}

for (let i = 0; i < list.length; i++) {
const item = list[i];
const id = options.base ? item[0] + options.base : item[0];
const css = item[1];
const media = item[2];
const sourceMap = item[3];
const part = { css, media, sourceMap };

if (!newStyles[id]) {
styles.push((newStyles[id] = { id, parts: [part] }));
const part = { css: item[1], media: item[2], sourceMap: item[3] };
const styleInDomById = stylesInDom[id];

if (styleInDomById[i]) {
styleInDomById[i].updater(part);
} else {
newStyles[id].parts.push(part);
styleInDomById.push({ updater: addStyle(part, options) });
}
}

return styles;
}

function addStylesToDom(styles, options) {
for (let i = 0; i < styles.length; i++) {
const item = styles[i];
const domStyle = stylesInDom[item.id];
let j = 0;

if (domStyle) {
domStyle.refs++;

for (; j < domStyle.parts.length; j++) {
domStyle.parts[j](item.parts[j]);
}
for (let j = list.length; j < stylesInDom[id].length; j++) {
stylesInDom[id][j].updater();
}

for (; j < item.parts.length; j++) {
domStyle.parts.push(addStyle(item.parts[j], options));
}
} else {
const parts = [];
stylesInDom[id].length = list.length;

for (; j < item.parts.length; j++) {
parts.push(addStyle(item.parts[j], options));
}

stylesInDom[item.id] = { id: item.id, refs: 1, parts };
}
if (stylesInDom[id].length === 0) {
delete stylesInDom[id];
}
}

function insertStyleElement(options) {
const style = document.createElement('style');
const attributes = options.attributes || {};

if (typeof options.attributes.nonce === 'undefined') {
if (typeof attributes.nonce === 'undefined') {
const nonce =
typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;

if (nonce) {
options.attributes.nonce = nonce;
attributes.nonce = nonce;
}
}

Object.keys(options.attributes).forEach((key) => {
style.setAttribute(key, options.attributes[key]);
Object.keys(attributes).forEach((key) => {
style.setAttribute(key, attributes[key]);
});

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

if (media) {
style.setAttribute('media', media);
} else {
style.removeAttribute('media');
}

if (sourceMap && btoa) {
Expand Down Expand Up @@ -243,51 +226,18 @@ function addStyle(obj, options) {
};
}

module.exports = (list, options) => {
module.exports = (id, list, options) => {
options = options || {};

options.attributes =
typeof options.attributes === 'object' ? options.attributes : {};

// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
// tags it will allow on a page
if (!options.singleton && typeof options.singleton !== 'boolean') {
options.singleton = isOldIE();
}

const styles = listToStyles(list, options);

addStylesToDom(styles, options);
addModulesToDom(id, list, options);

return function update(newList) {
const mayRemove = [];

for (let i = 0; i < styles.length; i++) {
const item = styles[i];
const domStyle = stylesInDom[item.id];

if (domStyle) {
domStyle.refs--;
mayRemove.push(domStyle);
}
}

if (newList) {
const newStyles = listToStyles(newList, options);

addStylesToDom(newStyles, options);
}

for (let i = 0; i < mayRemove.length; i++) {
const domStyle = mayRemove[i];

if (domStyle.refs === 0) {
for (let j = 0; j < domStyle.parts.length; j++) {
domStyle.parts[j]();
}

delete stylesInDom[domStyle.id];
}
}
addModulesToDom(id, newList || [], options);
};
};
7 changes: 6 additions & 1 deletion test/manual/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ <h3>Use/Unuse</h3>
</section>

<section>
<h3>Custom element</h3>
<h2>Order</h2>
<div class="order">BACKGROUND SHOULD BE RED</div>
</section>

<section>
<h2>Custom element</h2>
<custom-square l="100" c="red"></custom-square>
</section>

Expand Down
1 change: 1 addition & 0 deletions test/manual/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useUnse from './use-unuse.lazy.css';
import otherStyleLazy from './other-style.lazy.scss';
import componentLazy from './component.lazy.module.css';
import './style.link.css';
import './order.css';
import './custom-square';

console.log('___LOCALS___');
Expand Down
3 changes: 3 additions & 0 deletions test/manual/src/order-1.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.order {
background: red;
}
3 changes: 3 additions & 0 deletions test/manual/src/order-2.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.order {
background: blue;
}
13 changes: 13 additions & 0 deletions test/manual/src/order.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import url('./order-1.css');
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
@import url('./order-2.css');
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
@import url('./order-1.css');
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
@import url('./order-2.css') screen and (min-width: 2000px);
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');

.order {
width: 100%;
padding: 10px;
}
32 changes: 32 additions & 0 deletions test/runtime/__snapshots__/injectStylesIntoStyleTag.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,38 @@ exports[`addStyle should work with updates #11 1`] = `"<head><title>Title</title

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>"`;

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>"`;

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>"`;

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>"`;

exports[`addStyle should work with updates #12 4`] = `"<head><title>Title</title></head><body><h1>Hello world</h1></body>"`;

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>"`;

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>"`;

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>"`;

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>"`;

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>"`;

exports[`addStyle should work with updates #13 6`] = `"<head><title>Title</title><style>.blue { color: black }</style></head><body><h1>Hello world</h1></body>"`;

exports[`addStyle should work with updates #13 7`] = `"<head><title>Title</title></head><body><h1>Hello world</h1></body>"`;

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>"`;

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>"`;

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>"`;

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>"`;

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>"`;

exports[`addStyle should work with updates 1`] = `"<head><title>Title</title><style>.foo { color: red }</style></head><body><h1>Hello world</h1></body>"`;

exports[`addStyle should work with updates 2`] = `"<head><title>Title</title><style>.foo { color: blue }</style></head><body><h1>Hello world</h1></body>"`;
Loading