Skip to content

Commit 8ac2325

Browse files
John Baimgol
authored andcommitted
refactor: use inline styles even in sourcemap-enabled setups
Fixes broken relative and protocol-relative url() use in stylesheets when source maps are enabled. Chrome >=57 and Firefox >=50.1 support loading source maps when sourceMapURL directive is dynamically added to a new or existing style element in the DOM. This means that style-loader can simply add the styles and sourceMapURL directive as text inside a style element and the source map will be loaded by the browser. Given the simpler insertion method, the relative and protocol-relative urls in stylesheets will not break.
1 parent 084b2f8 commit 8ac2325

File tree

5 files changed

+16
-361
lines changed

5 files changed

+16
-361
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ By default, the style-loader inserts the `<style>` elements into the `<head>` ta
7373

7474
If defined, the style-loader will re-use a single `<style>` element, instead of adding/removing individual elements for each required module. **Note:** this option is on by default in IE9, which has strict limitations on the number of style tags allowed on a page. You can enable or disable it with the singleton query parameter (`?singleton` or `?-singleton`).
7575

76-
#### `convertToAbsoluteUrls`
77-
78-
If convertToAbsoluteUrls and sourceMaps are both enabled, relative urls will be converted to absolute urls right before the css is injected into the page. This resolves [an issue](https://github.com/webpack/style-loader/pull/96) where relative resources fail to load when source maps are enabled. You can enable it with the convertToAbsoluteUrls query parameter (`?convertToAbsoluteUrls`).
79-
8076
#### `attrs`
8177

8278
If defined, style-loader will attach given attributes with their values on `<style>` / `<link>` element.
@@ -113,8 +109,11 @@ So the recommended configuration for webpack is:
113109
{
114110
test: /\.useable\.css$/,
115111
use: [
116-
{
117-
loader: "style-loader/useable"
112+
{
113+
loader: "style-loader",
114+
options: {
115+
useable: true
116+
},
118117
},
119118
{ loader: "css-loader" },
120119
],
@@ -124,7 +123,6 @@ So the recommended configuration for webpack is:
124123
}
125124
```
126125

127-
**Note** about source maps support and assets referenced with `url`: when style loader is used with ?sourceMap option, the CSS modules will be generated as `Blob`s, so relative paths don't work (they would be relative to `chrome:blob` or `chrome:devtools`). In order for assets to maintain correct paths setting `output.publicPath` property of webpack configuration must be set, so that absolute paths are generated. Alternatively you can enable the `convertToAbsoluteUrls` option mentioned above.
128126

129127
<h2 align="center">Contributing</h2>
130128

addStyles.js

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var stylesInDom = {},
1313
isOldIE = memoize(function() {
1414
// Test for IE <= 9 as proposed by Browserhacks
1515
// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
16-
// Tests for existence of standard globals is to allow style-loader
16+
// Tests for existence of standard globals is to allow style-loader
1717
// to operate correctly into non-standard environments
1818
// @see https://github.com/webpack-contrib/style-loader/issues/177
1919
return window && document && document.all && !window.atob;
@@ -31,8 +31,7 @@ var stylesInDom = {},
3131
}),
3232
singletonElement = null,
3333
singletonCounter = 0,
34-
styleElementsInsertedAtTop = [],
35-
fixUrls = require("./fixUrls");
34+
styleElementsInsertedAtTop = [];
3635

3736
module.exports = function(list, options) {
3837
if(typeof DEBUG !== "undefined" && DEBUG) {
@@ -157,20 +156,10 @@ function createStyleElement(options) {
157156
return styleElement;
158157
}
159158

160-
function createLinkElement(options) {
161-
var linkElement = document.createElement("link");
162-
options.attrs.type = "text/css";
163-
options.attrs.rel = "stylesheet";
164-
165-
attachTagAttrs(linkElement, options.attrs);
166-
insertStyleElement(options, linkElement);
167-
return linkElement;
168-
}
169-
170159
function attachTagAttrs(element, attrs) {
171-
Object.keys(attrs).forEach(function (key) {
172-
element.setAttribute(key, attrs[key]);
173-
});
160+
Object.keys(attrs).forEach(function (key) {
161+
element.setAttribute(key, attrs[key]);
162+
});
174163
}
175164

176165
function addStyle(obj, options) {
@@ -181,19 +170,6 @@ function addStyle(obj, options) {
181170
styleElement = singletonElement || (singletonElement = createStyleElement(options));
182171
update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
183172
remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
184-
} else if(obj.sourceMap &&
185-
typeof URL === "function" &&
186-
typeof URL.createObjectURL === "function" &&
187-
typeof URL.revokeObjectURL === "function" &&
188-
typeof Blob === "function" &&
189-
typeof btoa === "function") {
190-
styleElement = createLinkElement(options);
191-
update = updateLink.bind(null, styleElement, options);
192-
remove = function() {
193-
removeStyleElement(styleElement);
194-
if(styleElement.href)
195-
URL.revokeObjectURL(styleElement.href);
196-
};
197173
} else {
198174
styleElement = createStyleElement(options);
199175
update = applyToTag.bind(null, styleElement);
@@ -244,6 +220,12 @@ function applyToSingletonTag(styleElement, index, remove, obj) {
244220
function applyToTag(styleElement, obj) {
245221
var css = obj.css;
246222
var media = obj.media;
223+
var sourceMap = obj.sourceMap;
224+
225+
if (sourceMap) {
226+
css += "\n/*# sourceMappingURL=data:application/json;base64," +
227+
btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
228+
}
247229

248230
if(media) {
249231
styleElement.setAttribute("media", media)
@@ -258,33 +240,3 @@ function applyToTag(styleElement, obj) {
258240
styleElement.appendChild(document.createTextNode(css));
259241
}
260242
}
261-
262-
function updateLink(linkElement, options, obj) {
263-
var css = obj.css;
264-
var sourceMap = obj.sourceMap;
265-
266-
/* If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
267-
and there is no publicPath defined then lets turn convertToAbsoluteUrls
268-
on by default. Otherwise default to the convertToAbsoluteUrls option
269-
directly
270-
*/
271-
var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;
272-
273-
if (options.convertToAbsoluteUrls || autoFixUrls){
274-
css = fixUrls(css);
275-
}
276-
277-
if(sourceMap) {
278-
// http://stackoverflow.com/a/26603875
279-
css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
280-
}
281-
282-
var blob = new Blob([css], { type: "text/css" });
283-
284-
var oldSrc = linkElement.href;
285-
286-
linkElement.href = URL.createObjectURL(blob);
287-
288-
if(oldSrc)
289-
URL.revokeObjectURL(oldSrc);
290-
}

fixUrls.js

Lines changed: 0 additions & 89 deletions
This file was deleted.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"files": [
2424
"addStyles.js",
2525
"addStyleUrl.js",
26-
"fixUrls.js",
2726
"index.js",
2827
"url.js",
2928
"useable.js"

0 commit comments

Comments
 (0)