Skip to content

Commit 6717ea1

Browse files
committed
test: add test for lazy loading CSS using fetch and document.adoptedStyleSheets
1 parent 970f732 commit 6717ea1

13 files changed

Lines changed: 159 additions & 14 deletions

File tree

README.md

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ See [boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate)
527527
- [How to inline JS in HTML](#recipe-inline-js)
528528
- [How to inline SVG, PNG images in HTML](#recipe-inline-image)
529529
- [How to resolve source assets in an attribute containing JSON value](#recipe-resolve-attr-json)
530-
- [How to load CSS file dynamically](#recipe-dynamic-load-css)
530+
- [How to load CSS file dynamically](#recipe-dynamic-load-css) (lazy loading CSS)
531531
- [How to load JS and CSS from `node_modules` in template](#recipe-load-js-css-from-node-modules)
532532
- [How to import CSS or SCSS from `node_modules` in SCSS](#recipe-import-style-from-node-modules)
533533
- [How to process a PHP template](#recipe-preprocessor-php)
@@ -2417,7 +2417,7 @@ Possible values:
24172417
24182418
- `false` - disable minification
24192419
- `true` - enable minification with default options
2420-
- `auto` - in `development` mode disable minification, in `production` mode enable minification with default options,
2420+
- `'auto'` - in `development` mode disable minification, in `production` mode enable minification with default options,
24212421
use [minifyOptions](#option-minify-options) to customize options
24222422
- `{}` - enable minification with custom options, this object are merged with `default options`\
24232423
see [options reference](https://github.com/terser/html-minifier-terser#options-quick-reference)
@@ -2428,7 +2428,7 @@ Possible values:
24282428
24292429
Type: `Object` Default: `null`
24302430
2431-
When the [minify](#option-minify) option is set to `auto`, you can configure minification options using the `minifyOptions`.
2431+
When the [minify](#option-minify) option is set to `'auto'` or `true`, you can configure minification options using the `minifyOptions`.
24322432
24332433
#### [↑ back to contents](#contents)
24342434
@@ -5209,26 +5209,47 @@ The custom attribute will contains in the generated HTML the resolved output ass
52095209
## How to load CSS file dynamically
52105210
52115211
For dynamic file loading, we need the output filename of extracted CSS from a source style file.
5212-
To get the CSS output filename in JavaScript, you can use the `url` query in `require()` function:
5212+
To get the CSS output filename in JavaScript, you can use the `url` query:
52135213
```js
5214-
const cssFile = require('./style.scss?url');
5214+
import cssUrl from './style.scss?url';
5215+
// - OR -
5216+
const cssUrl = require('./style.scss?url');
52155217
```
52165218
Where the `./style.scss` is the source SCSS file relative to the JavaScript file.
52175219
5218-
To load a CSS file dynamically, you can use the function:
5220+
To load a CSS file dynamically, you can use following function:
52195221
```js
5220-
function loadCSS(file) {
5222+
import cssUrl from './style.scss?url';
5223+
5224+
function loadCSS(url) {
52215225
const style = document.createElement('link');
5222-
style.href = file;
5226+
style.href = url;
52235227
style.rel = 'stylesheet';
52245228
document.head.appendChild(style);
52255229
}
52265230

5227-
const cssFile = require('./style.scss?url');
5228-
loadCSS(cssFile);
5231+
loadCSS(cssUrl);
52295232
```
52305233
5231-
The CSS will be extracted into separate file and the `cssFile` variable will contains the CSS output filename.
5234+
The CSS will be extracted into separate file and the `cssUrl` variable will contains the CSS output filename.
5235+
5236+
Since 2023, many browsers support the modern way to add the stylesheets into DOM without creating the `link` tag.
5237+
5238+
```js
5239+
import cssUrl from './style.scss?url';
5240+
5241+
async function loadCSS(url) {
5242+
const response = await fetch(url);
5243+
const css = await response.text();
5244+
const sheet = new CSSStyleSheet();
5245+
sheet.replaceSync(css);
5246+
document.adoptedStyleSheets = [sheet];
5247+
}
5248+
5249+
loadCSS(cssUrl);
5250+
```
5251+
5252+
See the [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets#browser_compatibility).
52325253
52335254
#### [↑ back to contents](#contents)
52345255

test/cases/entry-multiple-chunks-same-filename/webpack.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ module.exports = {
1111
entry: {
1212
// Test case multiple chunks with same filename:
1313
// - the `main.css` file is defined here, in entry point
14-
// - the same `main.css` file is defined in `index.pug`
14+
// - the same `main.css` file is defined in `index.html`
1515

1616
// Note: this use case has no sense and should not be used!
17-
// Specify all scripts and styles directly in Pug.
17+
// Specify all scripts and styles directly in HTML.
1818

1919
index: './src/index.html',
2020

959 Bytes
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Test</title>
5+
<link href="favicon.edda23bf.png" rel="icon">
6+
<link href="style.7f152e84.css" rel="stylesheet" />
7+
<script src="main.js" defer></script>
8+
</head>
9+
<body>
10+
<h1>Hello World!</h1>
11+
<p class="lazy">Lazy load CSS</p>
12+
</body>
13+
</html>

test/cases/js-import-css-lazy-url-fetch/expected/main.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* extracted by HTMLBundler CSSLoader */.lazy{color:green}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
h1{color:red}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Test</title>
5+
<link href="@images/favicons/favicon.png" rel="icon">
6+
<link href="./style.scss" rel="stylesheet" />
7+
<script src="main.js" defer></script>
8+
</head>
9+
<body>
10+
<h1>Hello World!</h1>
11+
<p class="lazy">Lazy load CSS</p>
12+
</body>
13+
</html>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import cssUrl from './style-dynamic.scss?url';
2+
3+
// universal way
4+
function lazyLoad(url) {
5+
const style = document.createElement('link');
6+
style.rel = 'stylesheet';
7+
style.href = url;
8+
document.head.appendChild(style);
9+
console.log('lazyLoad: ', { cssUrl });
10+
}
11+
12+
// Using fetch and document.adoptedStyleSheets
13+
// Browser compatibility (since early 2023):
14+
// https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets#browser_compatibility
15+
16+
// modern way, using promise
17+
function lazyLoad2(url) {
18+
fetch(url).then((response) => {
19+
response.text().then((css) => {
20+
const sheet = new CSSStyleSheet();
21+
sheet.replaceSync(css);
22+
document.adoptedStyleSheets = [sheet];
23+
console.log('lazyLoad2: ', { cssUrl });
24+
});
25+
});
26+
}
27+
28+
// modern way, using async await
29+
async function lazyLoad3(url) {
30+
const response = await fetch(url);
31+
const css = await response.text();
32+
const sheet = new CSSStyleSheet();
33+
sheet.replaceSync(css);
34+
document.adoptedStyleSheets = [sheet];
35+
console.log('lazyLoad3: ', { cssUrl });
36+
}
37+
38+
//lazyLoad(cssUrl);
39+
//lazyLoad2(cssUrl);
40+
lazyLoad3(cssUrl);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$color: green;
2+
.lazy {
3+
color: $color;
4+
}

0 commit comments

Comments
 (0)