bezoerb / inline-critical Goto Github PK
View Code? Open in Web Editor NEWInline critical path CSS and async load existing stylesheets
License: Other
Inline critical path CSS and async load existing stylesheets
License: Other
This library is being run via rollup-plugin-critical -> critical -> inline-critical
When trying to generate an inline stylesheet, the code falls over at https://github.com/bezoerb/inline-critical/blob/main/index.js#L80-L81 with an error of:
ERROR 'noscript)>[rel="stylesheet"]' is not a valid selector
at emit (node_modules/nwsapi/src/nwsapi.js:557:17)
at Object._matches [as match] (node_modules/nwsapi/src/nwsapi.js:1400:9)
at Array.Resolver (eval at compile (node_modules/nwsapi/src/nwsapi.js:760:17), <anonymous>:3:105)
at collect (node_modules/nwsapi/src/nwsapi.js:1552:21)
at _querySelectorAll (node_modules/nwsapi/src/nwsapi.js:1509:36)
at Object._querySelector [as first] (node_modules/nwsapi/src/nwsapi.js:1415:14)
at DocumentImpl.querySelector (node_modules/inline-critical/node_modules/jsdom/lib/jsdom/living/nodes/ParentNode-impl.js:69:44)
at Document.querySelector (node_modules/inline-critical/node_modules/jsdom/lib/jsdom/living/generated/Document.js:1026:58)
at Dom.querySelector (node_modules/inline-critical/src/dom.js:155:26)
at inline (node_modules/inline-critical/index.js:85:27)
This isn't the selector being passed in (that would be :not(noscript) > [rel="stylesheet"]
) but somewhere around the nwsapi
it gets mangled and comes out as a bad selector.
If I comment out these selectors in the code, it works. Adding a selector as an option has no effect as all selectors are evaluated.
I was looking at this code @bezoerb:
Line 93 in cfb8901
Array.isArray(o.replaceStylesheets) > 0
seems weird. Maybe we should expand the check to make it clearer?
Maybe:
!Boolean(o.replaceStylesheets) && Array.isArray(o.replaceStylesheets) && o.replaceStylesheets.length> 0
Or
!Boolean(o.replaceStylesheets) && o.replaceStylesheets.length> 0
PS. I hope I'm not overthinking this, it just seems weird to me :)
PPS. not sure if this affects the 4.x branch
Hi, just wanted to let you know that this line didn't work for me using npm3.
Because npm3 tries to make the node_modules folder flat, the fg-loadcss
module isn't in inline-critical/node_modules/fg-loadcss/
anymore.
I think it would be great if the inline-critical
takes an optional parameter to whether or not inject the loadCSS
function. This way the user of the module has more control of how they want to load the stylesheets.
I wanted to open an issue to see if this aligns with what the module is intended to do before I submit a pull request.
would be awesome
Could this be an option to inject <noscript>
s with stylesheet links to the bottom of the html page (in front of </body>
)? Why? Because Google PageSpeed still complains about css files that are blocking even if they are in noscripts..
Bump loadcss to the latest version.
Implies changing the tests here as well as the inline tests for critical
@bezoerb just part of the reduce dependencies motive. Not super important, but would be nice to have here too.
We need a way to expose the async loaded stylesheets to be used by the onloadCSS method provided by loadCSS.
See addyosmani/critical#110
Scenario: You have a SPA, say a VueJS one built with Vite. This app is to be deployed on a public path, say myapp
so it'd be www.example.com/myapp/.
When the SPA bundle is built, its assets links are of the format /myapp/assets/main.css
, but in the dist directory, the build is just dist/assets/main.css
It doesn't appear to be possible to get the extract option of inline-critical to function. https://github.com/bezoerb/inline-critical/blob/main/index.js#L165 is resolve(join(o.basePath || process.cwd, href));
which, with a basePath of "./dist"
resolves to /directory/dist/myapp/assets/main.css
which is incorrect.
It would be great if we could specify a publicPath
option that lets inline-critical know that there's a public path parameter that it should ignore/remove when trying to locate the CSS file.
Hi
After upgrading inline-critical to 1.0.0
we started receiving the loadCSS is not defined
error.
We are running an app using nw.js
. When inspected global
exists, so loadCSS gets assigned to it. This said it doesn't make it available globally and I don't think it's the object expected by inline-critical
. We temporally overcame this issue by overwriting global variable to point to window instance in the scope of the function that defines the loadCSS.
An insights ?
Working off of Critical v2.0.0-24, I'm seeing async CSS links being rewritten to a preload based strategy presumably based on the loadCSS project, but it looks like the currently recommended code favors media="print" instead of preload, and in doing so improves browser support greatly.
I think it's be worthwhile to move Critical 2.x to this print based approach, maybe optionally allowing for a declarative property to include the preload option as described further down in that article.
I was wondering, do we really need prettier? It's not a small dependency... https://packagephobia.now.sh/result?p=prettier
And this affects not only download size (https://packagephobia.now.sh/result?p=inline-critical) but also module load time. On my machine v4.x loads significantly faster:
C:\Users\xmr\Desktop\inline-critical>git branch
master
* v4.x
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 209.547ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 198.942ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 200.581ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 179.488ms
C:\Users\xmr\Desktop\inline-critical>git branch
* master
v4.x
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 713.050ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 702.322ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 715.274ms
C:\Users\xmr\Desktop\inline-critical>node load-time.js
Load time
Module: 684.928ms
The slowdown isn't only from prettier, but could be from jsdom too.
Why can't we just not minify the critical CSS if minify: false
? It should help a bit.
Ported from addyosmani/critical#552
If I understand #444 / 07be40bab23eb518bb689062b43f0db507c9a1f9 correctly, print stylesheets should be unaffected by the script. And that seems to actually be the case—the print stylesheet is not part of the extracted critical CSS.
However, the
<link>
tag still erroneously gets anonload
attribute, which does not make sense.Input HTML:
<link rel="stylesheet" href="css/print.css" media="print">
Expected output:
(unchanged)
Actual output:
<link rel="stylesheet" href="css/print.css" media="print" onload="this.media='print'">
@addyosmani I'm thinking about a way to implement the stylediff feature mentioned in addyosmani/critical#27 to inline critical.
Favored workflow at the moment:
filename-<hash>.css
to prevent conflicts with other pages which rely on the same sylesheets.Do you think this is ok or can you think of a more suitable approach?
Thanks
Fork of critical#39
Where should I hook this up? +@addyosmani
Npm is reporting a security issue with an old version of lodash
which is a dependency of cave
which is a dependency of this project. cave
was last updated 4 years ago, consider replacing it.
Inside loadCSS.js
the library always output "media='only x'" when the styles are loaded async. Would be really useful if the script could read the "media" attribute placed in the html like:
<link rel="stylesheet" href="styles.css" media="all">
and output:
// ...
o.rel="stylesheet",
o.href=e,
o.media="all", /* instead of "only x" */
i.parentNode.insertBefore(o,i)
// ...
Hi @bezoerb,
I too have to face the CSP problem, like: addyosmani/critical#480 so now I can't use the media
strategy (and also swap & polyfill).
But using the other strategies I get in my html:
Using default
strategy with extract=true
<head>
<style>
/* inlined */
</style>
<link href="css/index.518624788d8bb4e2cd8b.015276a2.css" rel="preload" as="style"> /* uncritical */
</head>
<body>
<link rel="stylesheet" href="./css/index.518624788d8bb4e2cd8b.css"> /* original css */
</body>
Problems: the css classes are duplicated, because the original stylesheet contains inlined & uncritical classes.
and generates in Chrome the message: The resource http://localhost:8080/css/index.518624788d8bb4e2cd8b.015276a2.css was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate as
value and it is preloaded intentionally.
Using body
strategy with extract=true
<head>
<style>
/* inlined */
</style>
/* missing uncritical */
</head>
<body>
<link rel="stylesheet" href="./css/index.518624788d8bb4e2cd8b.css"> /* original css */
</body>
Problems: uncritical file is missing, and inlined css classes are duplicated, because the original stylesheet contains inlined classes.
Expected behavior
Even if asynchronous loading of css doesn't work with CSP, I would at least get the inlining and loading of uncritical css, for example:
<head>
<style>
/* inlined */
</style>
<link rel="stylesheet" href="css/index.518624788d8bb4e2cd8b.015276a2.css"> /* uncritical */
</head>
<body>
/* no original css */
</body>
But at the moment this does not seem possible, and I have to give up using extract=true
.
Thanks
I ran inline-critical dist/style/index.css src/index.php
and in the output the entire <head>
was replaced inside with the <style>
tag. The output was something like this:
<?php
"some php code";
?>
<!DOCTYPE html>
<html>
<head><style>/* Inlined index.css */</style>
</head>
<body>
<!-- The body is fine, only head was affected -->
</body>
</html>
Is there a way to run the command without replacing the entire <head>
? I would like to keep my metadata:
<?php
"some php code";
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="description" content="Description">
<title>Title</title>
<style>/* Inlined index.css */</style>
</head>
<body>
<!-- The body is fine, only head was affected -->
</body>
</html>
My Go templates like
<li>Version: <a href="https://github.com/kaihendry/ltabus/commit/{{ getenv "UP_COMMIT" }}">{{ getenv "UP_COMMIT" }}</a></li>
get messed up to:
<li>Version: <a href="https://github.com/kaihendry/ltabus/commit/{{ getenv " up_commit"="" }}"="">{{ getenv "UP_COMMIT" }}</a></li>
Whilst using npx critical --inline templates/index.html.in > templates/index.html
.
Let me know if I can help.
Hello, is it working with 11ty which is building multiple urls? Thanks.
Seems like quotes around attributes are being normalised. This is causing problems when using single quotes:
<div data-test='"test informaiton"'>
becomes
<div data-test="" test="" informaiton""="">
When the HTML provided has not link, style or script tag it fails to inline the CSS. I checked to --selector option, but I didn't find a way to especify "before close head (before )".
When there is not link, style or script tag, just insert it before closing head tag</head>
critical -> inline-critical -> jsdom: WARN deprecated [email protected]: Use your platform's native DOMException instead
critical -> inline-critical -> jsdom -> data-urls: WARN deprecated [email protected]: Use your platform's native atob() and btoa() methods instead
critical -> inline-critical -> jsdom: WARN deprecated [email protected]: Use your platform's native atob() and btoa() methods instead
Remaining stylesheets are added with \
in path instead of /
eg:
<polygon fill="#DD7B27" points="55.92,7 91.96,61.76 20.24,61.76 "/>
Becomes:
<polygon fill="#DD7B27" points="55.92,7 91.96,61.76 20.24,61.76 "></polygon>
The type attribute for the style element <style type="text/css"> is not needed and should be omitted - validator.w3.org/nu
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.