addyosmani / critical Goto Github PK
View Code? Open in Web Editor NEWExtract & Inline Critical-path CSS in HTML pages
License: Apache License 2.0
Extract & Inline Critical-path CSS in HTML pages
License: Apache License 2.0
The critical css generated by tools like Penthouse
in almost all case works well for all dimensions up to the dimension asked for - but not higher. This means that if you want to cover all grounds, you should ask for the highest possible dimensions you want to include styles for "above the fold" elements for. The downside then is that your critical css will include styles for elements not seen (above the fold) for the majority of your users, which is why Penthouse
's default takes the compromise at 1300x900
(yes, quite arbitrary choice).
critical
however uses 480x320
in it's examples - which would leave out styles needed for many non mobile viewports. I don't think this a sensible default - we should increase the dimensions specified to 1300x900
, or something around there.
> [email protected] test C:\Users\xmr\Desktop\critical
> mocha test.js --timeout 15000
\
....|
2 passing (2s)
6 failing
1) generates critical-path CSS successfully:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:33:9
at C:\Users\xmr\Desktop\critical\index.js:60:15
at C:\Users\xmr\Desktop\critical\node_modules\mocha\node_modules\glob\node_modules\graceful-fs\graceful-fs.js:104:5
at Object.oncomplete (fs.js:107:15)
2) generates minified critical-path CSS successfully:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:47:9
at C:\Users\xmr\Desktop\critical\index.js:63:13
at ChildProcess.<anonymous> (C:\Users\xmr\Desktop\critical\node_modules\penthouse\lib\index.js:43:13)
at ChildProcess.emit (events.js:98:17)
at Process.ChildProcess._handle.onexit (child_process.js:809:12)
3) generates critical-path CSS without writing to disk:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:60:9
at C:\Users\xmr\Desktop\critical\index.js:63:13
at ChildProcess.<anonymous> (C:\Users\xmr\Desktop\critical\node_modules\penthouse\lib\index.js:43:13)
at ChildProcess.emit (events.js:98:17)
at Process.ChildProcess._handle.onexit (child_process.js:809:12)
4) inlines critical-path CSS successfully:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:72:9
at C:\Users\xmr\Desktop\critical\index.js:92:9
at C:\Users\xmr\Desktop\critical\node_modules\mocha\node_modules\glob\node_modules\graceful-fs\graceful-fs.js:104:5
at Object.oncomplete (fs.js:107:15)
5) inlines critical-path CSS without writing to disk:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:83:9
at C:\Users\xmr\Desktop\critical\index.js:95:9
at fs.js:271:14
at C:\Users\xmr\Desktop\critical\node_modules\mocha\node_modules\glob\node_modules\graceful-fs\graceful-fs.js:104:5
at Object.oncomplete (fs.js:107:15)
6) inlines and minified critical-path CSS:
Uncaught AssertionError: false == true
at C:\Users\xmr\Desktop\critical\test.js:96:9
at C:\Users\xmr\Desktop\critical\index.js:92:9
at C:\Users\xmr\Desktop\critical\node_modules\mocha\node_modules\glob\node_modules\graceful-fs\graceful-fs.js:104:5
at Object.oncomplete (fs.js:107:15)
npm ERR! Test failed. See above for more details.
npm ERR! not ok code 0
I managed to fix one of the tests by forcing LF. 5 still fail though.
My use case is an inline svg, where critical removes the closing tag, which causes some problems
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 ">
Hi, my request is about the invalid url path that gets printed out after initialising the critical task. Here is an example of what I am referring to: Lets say I have a "background-image" with destination such as url('../img/someImage.jpg'). In the critical path this will look like url("/components/minified/img/someImage.jpg") which creates invalid request for the browser. The right output for the url should be url("../../public/components/minified/img/someImage.jpg"). My question is how can I get the right url, after starting the critical task ?
I'm not sure what's going on here but the docs and the index.js
have .stream
, but I just installed the latest from npm and it's not there. The rest of the exported methods are there. 0.5.7 is the version that was installed and that's the version in the package.json on GitHub.
Getting toString() errors on two lines, 138 and 219 in index.js
/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:95
throw res.e;
^
TypeError: Cannot call method 'toString' of undefined
at /Library/WebServer/Documents/WireCash-website/node_modules/critical/index.js:138:30
and once I removed the method on 138 I got the same for 219:
/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:95
throw res.e;
^
TypeError: Cannot call method 'toString' of undefined
at /Library/WebServer/Documents/WireCash-website/node_modules/critical/index.js:219:28
Removing toString() from 219, got rid of the error messages, however I'm not getting inlined critical css at all?
My Gulp configuration is below and this is with the latest 0.4.0 release of critical. I'll do some investigating on my end, but wanted to bring attention to the issue.
var gulp = require('gulp'),
critical = require('critical'),
fs = require('fs');
// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
critical.generateInline({
base: 'dist/',
src: 'index.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'index.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
critical.generateInline({
base: 'dist/',
src: 'about.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'about.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
});
I'm unable to get htmlTarget to output to a file at all? Seemingly only dest: will do so, though is sans the inline styles. Below is my very simple gulpfile.js. I realize there is a reference to a working sample project, however the gulpfile has a lot going especially for someone brand new to gulp, moving over from grunt and just trying to get a very simple working gulp task going. Thanks for your help
var gulp = require('gulp');
var critical = require('critical');
gulp.task('critical', function() {
critical.inline({
base: 'dist',
src: 'index.html',
//dest: 'dist/index.html',
styleTarget: 'stylesheets/styles.css',
htmlTarget: 'index-inlined.html',
width: 320,
height: 480
}, function (err, output){
// You now have HTML with inlined critical-path CSS
// Works with and without dest specified
// !! This output does not have inlined css? and err is null?
console.log(err);
console.log(output);
});
});
i have created a gulpfile.js within my working folder here, which contains:
// Include gulp
var gulp = require('gulp');
var critical = require('critical');
// Generate Critical-path CSS
gulp.task('critical', function (cb) {
critical.generate({
base: '/',
src: 'mypage.html',
dest: 'styles/main.css',
width: 320,
height: 480
});
});
and i have (as far as i am aware) correctly installed the github master project for critical, as well as gulp, node and npm.
i have just tested by adding the optional 'css' config variable into the critical task function too - though this didn't make any difference either.
i'm out of ideas here, does anyone know what i might be missing?
the output of the terminal is:
$ gulp critical
[11:04:36] Using gulpfile /mypath/critical-working/gulpfile.js
[11:04:36] Starting 'critical'...
Hello. my site is available at this URL - somedomain.com/sometext/my-site/, so when after work critical"
path to the picture is not correct. Tell me what can I do?
Since it grabs all link elements and inlines them, what if there was an option to include only specified css files you want inlined?
I use a noscript async fallback for css and critical inlines that :(
Love this module, however a lot of sites are sourced from templates. This means an additional step of curl-ing the rendered html to disk and then using that as the source for the module. This creates some added complexity that would prevent a lot of folks from using it. Since fs.readFile
is async anyhow, would you be open to allowing sourcing the html from the network as opposed to the disk? I can send in a PR if so.
Could be useful.
Line 22 in 704fb50
Looks like it's src
and base
.
We could use cave
to go through the stylesheets where the critical CSS is pulled from, and "diff" the two, removing critical CSS from the original stylesheets.
e.g:
critical = 'a{color:#f00}'
cave(stylesheet, { css: critical }, saveUpdates)
var critical = require('critical');
critical.generateInline({
// Your base directory
base: 'dist/',
// HTML source
src: 'index.html',
// Your CSS Files (optional)
// Viewport width
width: 320,
// Viewport height
height: 480,
// Target for final HTML output
htmlTarget: 'index.html',
// Target for generated critical-path CSS (which we inline)
//styleTarget: 'app.css',
// Minify critical-path CSS when inlining
minify: true,
// Extract inlined styles from referenced stylesheets
extract: true
});
The above results in code like:
(function(u){function loadCSS(e,t,n){"use strict";function r(){for(var t,i=0;i<d.length;i++)d[i].href&&d[i].href.indexOf(e)>-1&&(t=!0);t?o.media=n||"all":setTimeout(r)}var o=window.document.createElement("link"),i=t||window.document.getElementsByTagName("script")[0],d=window.document.styleSheets;return o.rel="stylesheet",o.href=e,o.media="only x",i.parentNode.insertBefore(o,i),r(),o}for(var i in u){loadCSS(u[i]);}}(['','','app.686313bf.css']));
When it should really be:
(function(u){function loadCSS(e,t,n){"use strict";function r(){for(var t,i=0;i<d.length;i++)d[i].href&&d[i].href.indexOf(e)>-1&&(t=!0);t?o.media=n||"all":setTimeout(r)}var o=window.document.createElement("link"),i=t||window.document.getElementsByTagName("script")[0],d=window.document.styleSheets;return o.rel="stylesheet",o.href=e,o.media="only x",i.parentNode.insertBefore(o,i),r(),o}for(var i in u){loadCSS(u[i]);}}(['//fonts.googleapis.com/css?family=Questrial','//fonts.googleapis.com/css?family=Sanchez:400italic,400','app.css']));
Turning extract to false solves the problem.
I've been using and loving grunt-critical, thank you!
I do have one issue that I can't quite figure out. I have a site that has critical CSS for all of the pages, and it works great... but for pages that have CSS animations on them in form of Twitter Bootstrap carousel animations it's not quite doing the trick.
Here's an example URL:
There some CSS in there that critical isn't picking up on, because PageSpeed Insights says:
"Approximately 19% of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.
http://cssjs.onlinelandusa.net/site_assets/css/site.combined.min.css"
Somehow critical isn't picking up on all of the CSS that needs to be rendered, so it has to wait to load the full CSS file before it can render the above-the-fold content. There is a similar result on an even simpler page:
http://www.onlinelandusa.com/site/about-us
...that just has one carousel animation on it, so I'm assuming that's what is doing it. You can see the extracted critical CSS here:
http://www.onlinelandusa.com/site/css/about_us_critical.min.css
Maybe I'm going about this incorrectly. I have the need to run critical against multiple files. I am using:
// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
critical.generateInline({
base: 'dist/',
src: 'index.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'index.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
critical.generateInline({
base: 'dist/',
src: 'about.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'about.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
});
From this I receive:
/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:93
throw res.e;
^
TypeError: Cannot call method 'toString' of undefined
at /Library/WebServer/Documents/WireCash-website/node_modules/critical/index.js:134:30
at tryCatch1 (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/util.js:43:21)
at Promise$_callHandler [as _callHandler] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:649:13)
at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:663:18)
at Promise$_settlePromiseAt [as _settlePromiseAt] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:826:14)
at Promise$_settlePromises [as _settlePromises] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:969:14)
at Async$_consumeFunctionBuffer [as _consumeFunctionBuffer] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:75:12)
at Async$consumeFunctionBuffer (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:38:14)
at process._tickCallback (node.js:419:13)
Apparently callback methods being passed the String variable criticalCSS
are undefined for all subsequent tasks after the first one which is a string as it should be.. Oddly enough all subsequent critical tasks appear to still work, they're just throwing those errors which I circumvented by removing the toString() from the critcialCSS string object which itself is already a string so I'm not sure why those methods were in place.
Is there a standard approach to running the critical task on multiple files? I think it'd be great to be able to run a pattern match like *.html with the htmlTarget by default assuming the same name for each file matched.
Currently all linked stylesheets are inlined.
This should only be done for the critical-path css.
Maybe the the module could also provide some functionality to diff the critrical-path css and the main css to create a css file with only the remaining css included
Since everything else is async it would be too bad to destroy the async with a sync call. Use fs.writeFile
/fs.readFile
instead.
Generated output for index-critical.html contain Unicode Hex Codes.
gulp critical ->
Instead "Test čeština" it returns "Test პština". Any idea?
Thanks for this project - awesome work.
I'm using gulp to inline the styles
gulp.task('critical', ['styles'], function () {
critical.generateInline({
base: 'dist/',
src: 'index.html',
styleTarget: 'css/site.css',
htmlTarget: 'index.html',
width: 320,
height: 480,
minify: true
});
});
but the load_css script block is also output into the head
style:none;margin-left:0;padding-left:0;margin-bottom:20px}.nav-pills>li>a{padding:8px;margin-top:2px;margin-bottom:2px;border-radius:5px;margin-right:2px;line-height:14px}.nav>li>a{display:block}.nav-map a{text-align:center;font-size:.9em}.nav-map a time{display:block;font-size:.8em;font-style:italic}
</style>
<script>
(function(u){function loadCSS(e,t,n){"use strict";function r(){for(var t,i=0;i<d.length;i++)d[i].href&&d[i].href.indexOf(e)>-1&&(t=!0);t?o.media=n||"all":setTimeout(r)}var o=window.document.createElement("link"),i=t||window.document.getElementsByTagName("script")[0],d=window.document.styleSheets;return o.rel="stylesheet",o.href=e,o.media="only x",i.parentNode.insertBefore(o,i),r(),o}for(var i in u){loadCSS(u[i]);}}(['css/style-8994d4f2.css','http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css']));
</script>
<noscript>
<link rel="stylesheet" href="css/style-8994d4f2.css">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css">
</noscript>
</head>
Do I need to do something else to get that script block into the bottom of the body tag?
Using this example from the README:
critical test/fixture/index.html --base test/fixture > critical.css
Error: path must be a string
Maybe I'm going about this incorrectly. I have the need to run critical against multiple files. I am using:
// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
critical.generateInline({
base: 'dist/',
src: 'index.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'index.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
critical.generateInline({
base: 'dist/',
src: 'about.html',
cssPath: 'stylesheets/',
styleTarget: 'stylesheets/critical.css',
htmlTarget: 'about.html',
width: 320,
height: 480,
minify: true,
maxInlineImageSize: 10240
});
});
From this I receive:
/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:93
throw res.e;
^
TypeError: Cannot call method 'toString' of undefined
at /Library/WebServer/Documents/WireCash-website/node_modules/critical/index.js:134:30
at tryCatch1 (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/util.js:43:21)
at Promise$_callHandler [as _callHandler] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:649:13)
at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:663:18)
at Promise$_settlePromiseAt [as _settlePromiseAt] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:826:14)
at Promise$_settlePromises [as _settlePromises] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/promise.js:969:14)
at Async$_consumeFunctionBuffer [as _consumeFunctionBuffer] (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:75:12)
at Async$consumeFunctionBuffer (/Library/WebServer/Documents/WireCash-website/node_modules/critical/node_modules/bluebird/js/main/async.js:38:14)
at process._tickCallback (node.js:419:13)
Apparently callback methods being passed the String variable criticalCSS
are undefined for all subsequent tasks after the first one which is a string as it should be.. Oddly enough all subsequent critical tasks appear to still work, they're just throwing those errors which I circumvented by removing the toString() from the critcialCSS string object which itself is already a string so I'm not sure why those methods were in place.
Is there a standard approach to running the critical task on multiple files? I think it'd be great to be able to run a pattern match like *.html with the htmlTarget by default assuming the same name for each file matched.
If anyone would like to help with the outstanding tasks, go for it :) Otherwise, I'll try to update them this weekend.
For the lazy. Find a good default value. Maybe the most popular screen resolution.
It appears that critical generates a tmp-.css
file in the base directory while it's running. Annoyingly for me, this file is getting picked up on tasks that run after (if chained as a dependency).
It's showing up in my cache manifest file :(
Is there any chance we can get it to generate inside a .tmp
folder? At least that way i can set gulp-manifest to ignore that folder.
Hello,
I have some css files in my /tmp folder
root@mail:~# ls /tmp/
01080730-bf29-482c-81e7-9df3642dffb0.css 33cdb8d7-060e-4f40-b133-61efaad69ad5.css 64664c26-8a37-41c4-b6ff-20331d5a4fea.css 96de35c2-3695-413a-bab2-1b1599161223.css d69647eb-83e6-41d1-845b-ea677008936d.css
01551406-a16c-4ee7-ae22-a11427a14dca.css 340654fc-2b29-41a0-ac6d-60a104c43145.css 64f3bb03-0114-42d1-a1e7-6190f37fec60.css 971fec66-98c5-419e-919c-4b2b30679c35.css d7034edd-a330-42cc-8231-3ed8d8560989.css
01c30a3f-befb-4ee3-be6e-6e45c5b2f894.css 34f5ebb6-be29-4af7-a86c-1be8d2a83cba.css 664cc58c-3f1d-4236-a1ad-eb4c20ac7433.css 97f54cd5-ef68-41df-ad73-e35017b79e9e.css d84dbd3b-5080-4576-b567-c8d4354fafae.css
036df2b0-426e-4f6f-b88a-90a03b3193f2.css 35b4087d-774d-4ad1-ad95-b6b4a7fc8976.css 68a4125f-787c-4430-a12d-be78d1fe6790.css 99fbb948-982f-4b70-a705-17fc6682adba.css da28124f-bf98-4852-9eb6-a52ae39c1bfc.css
0681cd05-4311-4569-974d-daf856c3f0f5.css 35bc1b74-9d5e-45c6-8c07-22c11e271b38.css 69ed739b-7914-402f-8351-b85b02f5f7ae.css 9a69c184-13fb-4aa9-b79d-13d03bba37bc.css daac51a4-0625-4885-ad78-56799841d247.css
07d70728-d26b-4579-befb-a7df2341b1e9.css 3677c1b0-19d6-4e7a-8f38-189258894cbf.css 6a88f85a-99f9-414e-969b-0bf25fd5f0f2.css 9afdaab9-3597-4c81-b192-a871e1cdd544.css dcee70de-e01c-43e0-8343-68ef1182e16a.css
0801a89c-85be-4e95-915c-6ace54e1ba62.css 377d6606-14d7-466b-ba8c-544cdff45b8d.css 6ab62dfc-c6b8-4c54-97e2-23d65e4025da.css 9b8551cb-9c7f-471b-a2da-76f98aeb67e4.css df07f38a-8eb4-4d16-b0c9-f208385c406f.css
088d78be-9db8-4505-8cf2-27906c268889.css 380b89f2-efc4-433e-849b-14da1767c184.css 6b07faa2-2152-487e-beed-10ea366e1ca3.css 9c2af0c7-2f0a-454e-9a53-4477aa288907.css df2f655a-fdb8-4bd2-9a2f-ce608f607b58.css
0ca9fdab-3e2c-4c14-bf5b-67724f330b3f.css 384d1fb3-b77e-4461-8c26-bcd2e052ed70.css 6b09cb4c-97fe-4cf7-8f85-133bc2d6443f.css 9e862b89-0d9e-46d7-962a-2367d918e412.css dfac82d5-752b-4dc1-baca-131924893e19.css
0d43e47a-305f-472f-9136-353308fd0555.css 393fb1dc-6f85-4e00-b816-dc8858851583.css 6bc4ba1a-9241-4575-88fd-7b9ecd3559c2.css a3562e0b-b552-49b9-b287-08b5b1a83c15.css dfb0b9fb-6914-43e4-9ccb-5f82c687b5f5.css
0d6e24bc-7ff5-4240-aa62-f30b64575896.css 3b34a247-933b-40e7-a1ae-700004dd4705.css 6bcbef7b-f201-473f-a06b-2475d3d9901f.css a376640f-41a7-46c1-a328-e935d79090be.css dfd62398-8482-4b0a-923d-628c7f9f3b72.css
0ff1f79e-7583-458c-a28b-74ac6ce542c0.css 3b879cdd-0e82-41e5-98a5-b9179350f3a0.css 6c3114a4-7115-4f58-874e-c5c1581eb392.css a4612a3e-b8d1-432a-a0f9-a5012d542f0f.css e0343b69-183a-4957-b0cc-802daca6d637.css
1075437e-d9e6-4641-8e27-6165a2831686.css 3c95d250-2a8e-4e2a-a25c-7a5590d4a019.css 6d4f87eb-41c2-49b8-b575-91e3a6b24574.css a468f4ff-dae8-46b9-a399-1aa380efcfd8.css e0707d4f-303f-420e-84c9-92d7cbc564e5.css
126a2063-faac-44e7-bd4e-8e206d42ba51.css 3cdd2581-6ff8-48e6-946b-2a1d1b6c9eeb.css 6d77088b-1878-4c7a-b826-3668b30d4705.css a58720e6-e6ee-4e47-bb29-7b6f24faff5b.css e2e0cc4b-93a7-4f43-ada5-949ec5d93fa3.css
13438749-317f-4e31-bd93-1176d5f05fd5.css 41330db0-7154-4969-bacc-1b588d2650a7.css 6f4b960f-a0bf-47eb-9afd-ddd6e79d14ca.css a6a0b07b-d80a-42d6-9e41-9dededcd7467.css e37a504b-6e35-424d-b192-3067890b5273.css
140eaa10-675b-4d6e-92c6-f04161426733.css 45df6ce7-71a1-4b14-b218-ae9835704349.css 72673975-50aa-4ed3-b7cc-95ee9dbe93ad.css a9a7254d-6df0-45d3-9afb-710dd8a97374.css e3e04264-4b7c-4d9b-b513-349cb3559c03.css
14373646-4260-4ad7-adfb-709a56f61e61.css 4778eb13-a5e8-4618-befd-57412702e1d0.css 73bb4ae3-25d3-4799-8e40-d006087e5737.css ab16b0ea-712d-407e-9e6e-9563873a12c4.css e4f07d8d-d8e7-4bf2-930b-6730ae5b40b7.css
14c7c7d4-26b9-41d3-bd46-c065277c6795.css 48d8c784-7721-4c9d-bc98-304a2d535ea1.css 754d8c4a-ddf6-41c4-ba50-1080f797a91e.css b123a410-bb7e-4f75-94ba-5b6206fce609.css e5384c69-feb6-416e-a26a-5c8ddcc1fa28.css
1a5a3fba-9267-40dd-b3e7-a2a4dcc0eccf.css 4974af60-f2b5-49fa-8f6f-b549232abf66.css 77dd51eb-1a5e-4455-b909-5afe2f8195e5.css b19560bf-c051-44c4-b58a-831374058682.css e754e5e0-ce82-451c-b192-6ebeededbe1f.css
1a6278b2-02e7-4e0f-ad5d-019aa5fcea2e.css 4adaacc5-e088-4b3e-9707-6d0faa911329.css 784eeee6-46db-43f3-a8fe-3fdc1a30d5fc.css b2519450-904d-43ff-a614-6a8c888466ba.css e7bbfe2d-bc39-4ca2-b0d6-7b3f6fd28608.css
1b21485d-c0a4-4bf2-a8fb-e8dfbd0d5146.css 4b1cd8f7-8037-4429-9bfb-1d9897636800.css 7a2d4ee9-6708-4a32-8ece-31e188845946.css b30ec9b2-0502-4421-8c6c-20077cf45633.css e85894cc-e4f5-43c7-ba13-f9b2e8b94b59.css
1c10918b-2089-4d96-8312-406944f6255b.css 4b5b1b5c-e74a-45d0-95c5-fc62644f7723.css 7bfdb4ca-cf2c-4159-8d1a-e4436a718ea3.css b3612811-9967-4198-9af7-063056e322b5.css ea45254b-2f35-4d18-9be3-eb07d78123e4.css
1c845e8d-8ed4-4f0b-9814-9ee85519d9c6.css 4cd50be3-ef67-40d0-8d86-d983f9f3667b.css 7cb35d0b-9671-424f-86ad-69349dc0bcb3.css b4427a2e-c0d9-48f6-920a-98e850781f64.css eaccae61-e6b3-43ce-845e-edb1478f1c63.css
1f6996a9-b44e-469f-bf18-d52e9a190b15.css 4d4bfc4e-a696-49bb-b976-54319a51fb60.css 7da79dbe-8a91-4367-bb65-1c66cd6181e5.css b71b2b5b-9071-4d2f-84b9-ec5b25c8ddc3.css ebc8c9a9-5703-4f87-b02f-c1a42eed392c.css
1fe41ccc-4d18-433e-b900-0a1edbe223f0.css 4d632c10-1d58-43d3-8820-3b75f6422e63.css 7ef027e5-1b88-4d33-8f0b-933c1ea421ac.css b905dd47-d209-417f-841b-3c2a7f2bc654.css ec35c6d9-f99b-465e-896e-e462376d6fda.css
20017106-21f9-4740-bebe-2b026a95e797.css 50fb8a1c-3f2e-4316-ae1f-7252cb29c6db.css 80c4d8b1-0f32-4d20-832c-0f0678ed7cca.css ba55ca0e-5e45-4f09-855b-02638b4f3951.css ec54012c-74ab-417a-ad23-49333dcbdb30.css
20e51be6-0240-4fa5-b30f-78f935a0732d.css 51750742-efd7-4d90-8a2b-382593e941ca.css 82e8ab48-835e-471c-a095-77ecb44bfae8.css ba59fce5-9f27-4139-ae90-2f654575c62b.css edf77080-f12a-4776-b065-e0a39bb8801d.css
24231637-94b4-467c-8f9d-a30bbe6aefee.css 53f7a7e1-0125-439f-af56-13b8a9657fc8.css 8490021c-f428-48b4-bef6-512a7f306327.css bad6928a-4538-467d-82a1-9e656156505d.css f0db0c9e-3545-4032-a8a5-2bfd409c7c2c.css
24a9ffd2-5aa4-45ef-98fe-754633fbd85b.css 54f629cb-c9e1-45cd-8787-4942590d44c1.css 8532f5e7-1b36-4e7b-8431-14a0a3a84122.css bbee8599-9b9b-4a5a-af18-4d48bb87e7a8.css f2df054d-dc76-4596-89f4-be56a3475c9b.css
257c820b-d0a3-4987-a801-3cea8badccd4.css 56b08d82-0932-4c13-8736-98f3362121a9.css 879a2563-9100-4106-a531-d355d5dbe4e0.css beb6398b-7383-4840-8255-49260b13d0de.css f397a0b8-2b0a-4543-be5c-c8ee8f011d81.css
27b4079d-d00c-4244-bc8b-ada48b93470b.css 56bb04c3-9994-42c9-985f-f594f377999b.css 8a1dc50a-00e9-4a94-8bbb-6e694f38f44d.css bfff8fa6-7cc2-4293-8e70-a37cf56cc17b.css f3af17d7-ca6c-463f-91d4-bade84a3ec1d.css
27c3ca62-c209-44b1-bcc5-0d7d7584b5ec.css 57ec21ba-d135-4fc7-9a92-be97714e4c18.css 8a7581b0-d3a5-4a9e-bc6e-9660ec41a22a.css c257c97a-6a5e-4e9d-aa9c-07b0a6421f25.css f4053034-6e46-45af-95a8-e9ca4543424c.css
28d04c61-623d-46a1-aa99-aeec8e3e6c12.css 58473dd7-898c-4572-9e34-28f890893f85.css 8aa78833-337a-4b05-aa21-85ae6042df61.css c5856c22-0ff4-4cea-8ed8-06fa945ff15c.css f5b78b0b-1d9f-4c93-90b6-730b7ceb25cc.css
2aa44d03-d44c-491f-a443-cdb7eae252ef.css 58daa896-8675-474b-83b7-1e3ab39dd2b7.css 8b35d01d-30a1-417f-9be7-de7f6f95e191.css c7439dc4-68aa-4ac3-b45c-5b56494f661d.css f953f748-6999-4c7f-b0be-d404ef1e688a.css
2ab58b8b-9755-4ccf-9a69-9caa7e17398f.css 5b048158-affc-41b1-95dc-a585acd33f47.css 8b375763-ebce-4a15-b364-db1ac2add5a4.css c98f6c1e-9828-4106-9efe-50c55387890e.css fc5cbf38-97d2-4f6d-8f10-a6568e235775.css
2bb31546-1c36-49d0-a93c-660c2a75fda5.css 5b642bd6-4f0f-4da7-9abf-04a4dcc239fb.css 8e347822-a3ee-42e8-9e64-1050627e4418.css cb730101-320b-4506-9e9e-5a2612366a07.css fc77811e-4890-4edd-8e61-58ddf8f38193.css
2cd4c771-838c-4611-a0c5-46cf63e51c9b.css 5b9e7b2b-8046-4da2-8acc-a6421d451d57.css 8e38e32c-828e-4925-910e-a8e026ba6ca1.css cdabb6d1-e8d6-42f4-b728-568ff03ba96d.css fdfbd6d0-878f-4121-a91e-b3270bd0bf0b.css
..
So I'm using critical to generate critical path CSS for my website, which I embed into web pages as embedded stylesheets. Then I load the full CSS later on via loadCSS(); All is great so far.
However, I'm using Bootstrap; so let's say there is a Bootstrap declaration such as:
.alert { border-radius: 5px; }
...which gets embedded into my webpage because it's used in the above the fold content.
Further down the page, in below the fold content, I have HTML that looks like this:
<div class="alert my_alert"></div>
...which the CSS style my_alert being:
.my_alert { border-radius: 15px; }
So the problem here is that the embedded CSS for "alert" is overriding the "my_alert" style that's applied via my async loaded CSS, so border-radius ends up staying set to 5px;
Is there a way to handle this reasonably?
Hello guys, awesome work and great plugin.
Is there any way for specifying multiple source files ?
Line 44 in 704fb50
The error should be passed as the first argument to cb, per Node convention.
I'm currently playing around with Critical and I ran into this problem, whenever I have a Google Webfonts in the header Critical crashes. I just straight copied from the first Gulp example and this is what I have in the header:
<link rel="stylesheet" href="/assets/stylesheets/screen.css">
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400" />
And when I then run the gulp critical
task I get this error:
❯ gulp critical site/git/master !
[23:20:42] Using gulpfile ~/path/to/site/gulpfile.js
[23:20:42] Starting 'copy:css'...
[23:20:42] Finished 'copy:css' after 19 ms
[23:20:42] Starting 'critical'...
[23:20:42] 'critical' errored after 209 ms
[23:20:42] Error: ENOENT, open 'site/fonts.googleapis.com/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400'
/path/to/site/node_modules/critical/node_modules/bluebird/js/main/async.js:93
throw res.e;
^
TypeError: Cannot call method 'toString' of undefined
Any kind of solution for this? Thanks!
NOTE - This was only tested with the new Stream functionality.
Example - Using the new Stream functionality and Extract:true, Gulp is globbing through several HTML files, and some are in subdirectories. In my HTML, my stylesheet path is "/assets/css/app.min.css" (note the slash at the beginning).
This does not work or result in generating multiple partial CSS files, and it doesn't append the appropriate filename to the LoadCSS snippet functions.
Removing the front slash to just "assets/css/app.min.css" MAKES THE WHOLE THING WORK. However, once the files are outputted, the loadCSS is pointing to a relative asset, and this breaks the pages that are inside a subdirectory, since it can't find the CSS there.
to recap - It does work with both absolute and relative paths, as long as you don't use the extract function (which creates its own unique stylesheet per page). If you use extract: true, then it only works with a relative path.
Also, with extract: true, the loadCSS function appends no path for the stylesheet.
Lastly, extract:true also gets hung up if an external stylesheet is defined in the markup.
Use path.join()
to concat path segments:
Line 41 in 704fb50
Right now there's no way to get the content in the callback without having it also written to disk.
Lines 40 to 42 in 49c9acd
When rebasing urls starting with ../
, backslash is used as a path separator.
For example background-image:url(../img/sprite.png);
in my original stylesheet is translated to background-image:url(\img\sprite.png);
, which results in an incorrect request for /imgsprite.png, instead of /img/sprite.png.
following the advice in the issue regarding the toString errors.. i chose to install the github master version of critical using:
sudo npm install http://github.com/addyosmani/critical/tarball/master
towards the end of the terminal output, i saw more errors:
Received 12854K total.
Extracting tar contents (via spawned process)
Removing /mypath/critical-working/node_modules/critical/node_modules/penthouse/node_modules/phantomjs/lib/phantom
Copying extracted folder /mypath/critical-working/node_modules/critical/node_modules/penthouse/node_modules/phantomjs/phantomjs/phantomjs-1.9.8-linux-x86_64.tar.bz2-extract-1416739729376/phantomjs-1.9.8-linux-x86_64 -> /mypath/critical-working/node_modules/critical/node_modules/penthouse/node_modules/phantomjs/lib/phantom
Removing /mypath/critical-working/node_modules/critical/node_modules/penthouse/node_modules/phantomjs/phantomjs/phantomjs-1.9.8-linux-x86_64.tar.bz2-extract-1416739729376
Writing location.js file
Done. Phantomjs binary available at /mypath/critical-working/node_modules/critical/node_modules/penthouse/node_modules/phantomjs/lib/phantom/bin/phantomjs
npm ERR! Error: ENOENT, chmod '/mypath/critical-working/node_modules/critical/bin/critical'
npm ERR! If you need help, you may report this log at:
npm ERR! <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR! <[email protected]>
npm ERR! System Linux 3.17.3-200.fc20.x86_64
npm ERR! command "node" "/bin/npm" "install" "http://github.com/addyosmani/critical/tarball/master"
npm ERR! cwd /mypath/critical-working
npm ERR! node -v v0.10.32
npm ERR! npm -v 1.3.6
npm ERR! path /mypath/critical-working/node_modules/critical/bin/critical
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /mypath/critical-working/npm-debug.log
npm ERR! not ok code 0
i looked into the debug log that is mentioned and did not see any info in there that was helpful to me in diagnosing the cause fo the errors.
@addyosmani
While implementing some tests for the CLI i've stumbled across parameter inconsistence between generate
and generateInline
. For generateInline
we use styleTarget
and htmlTarget
and for generate
we only use dest
. This could be a bit confusing.
Maybe we should consider deprecating the options styleTarget
and htmlTarget
in favor of just using dest
and and select the right task based upon the filetype
With this is mind we could also strip down generate
and generateInline
because then only one public method is needed for either generate and inline to produce html or for just generating the critical css. What do you think?
The test folder only contains fixtures, so should probably be named fixture
.
allow to read src from URL directly example http://localhost:3000 , rather than required to read from .html file
Since the last release of penthouse
(0.2.52) pocketjoso/penthouse@704c294 all tests are failing.
It looks like we get a totally different critical css now.
We should lock the last working penthouse version (0.2.51)
/cc @pocketjoso
Reusable modules put anything implicitly to the stdout/stderr. I you really needed it you could use events or the debug
module, but I don't really see the value here, so I would just drop them.
At this time only the first stylesheet gets processed. The critical CSS should be fetched from all linked stylesheets
We got an issue over at grunt-critical with conflicting versions of clean-css
. See bezoerb/grunt-critical#11
I think bumping clean-css
in critical
would be the most simple fix for this
Hello all,
I am having an interesting issue in my latest project. When I trigger Critical to inject the critical styles in my html (dest: '_site/index.html') it breaks my SVG logo image.
Here is the image before:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 563 87.9" enable-background="new 0 0 563 87.9" xml:space="preserve" width="167px" height="26px" fill="#fff">
<g>
<g>
<path d="M137.6,23.6h-15.7v-3.1h34.8v3.1H141v42h-3.3V23.6z"/>
<path d="M173.3,20.5h18.9c5.5,0,10,1.7,12.7,4.4c2.1,2.1,3.4,5.1,3.4,8.4v0.1c0,7.5-5.6,11.8-13.2,12.9L210,65.6h-4.2l-14.4-18.7h-0.1h-14.6v18.7h-3.3V20.5z M191.8,43.9c7.5,0,13.1-3.8,13.1-10.3v-0.1c0-6-4.8-9.8-12.9-9.8h-15.4v20.3H191.8z"/>
<path d="M225.6,46.9V20.5h3.3v26c0,10.6,5.7,16.7,15.3,16.7c9.1,0,15-5.5,15-16.4V20.5h3.3v25.9c0,12.9-7.5,19.8-18.5,19.8C233.2,66.3,225.6,59.5,225.6,46.9z"/>
<path d="M281.6,20.5h32.1v3.1H285v17.7h25.8v3.1H285v18.1h29v3.1h-32.4V20.5z"/>
<path d="M326.1,20.5H337l11.8,31.7l11.8-31.7h10.7L353,65.9h-8.8L326.1,20.5z"/>
<path d="M393.6,20.2h9.1l19.3,45.4h-10.4l-4.1-10.1h-19.1l-4.1,10.1h-10.1L393.6,20.2z M404.1,46.7l-6-14.6l-6,14.6H404.1z"/>
<path d="M433.2,46.3V20.5h9.9V46c0,7.3,3.7,11.1,9.7,11.1c6.1,0,9.7-3.7,9.7-10.8V20.5h9.9V46c0,13.6-7.7,20.3-19.8,20.3C440.6,66.3,433.2,59.5,433.2,46.3z"/>
<path d="M489,20.5h9.9v36h22.5v9H489V20.5z"/>
<path d="M539.3,29.7h-13.7v-9.1H563v9.1h-13.7v35.9h-9.9V29.7z"/>
</g>
<g>
<path d="M63.9,17.6H35.5L22.8,36.5l26.8,26.5l26.8-26.6L63.9,17.6z M60.1,41.1l-0.5,1l-0.4,0.6l-0.7-0.4l-6.7-3.7c-0.6,0.6-1.4,0.9-2.3,0.9c-0.9,0-1.7-0.3-2.3-0.9l-6.7,3.7L40,42.7l-0.4-0.6l-0.5-1l-0.4-0.7l0.7-0.4l6.9-3.8c0,0,0,0,0,0c0-1.3,0.8-2.5,2-3v-7v-0.7H49h1.1h0.7v0.7v7c1.2,0.5,2.1,1.7,2.1,3.1c0,0,0,0,0,0l6.9,3.8l0.7,0.4L60.1,41.1z"/>
<path d="M73.3,0H26.1L0,38.8l49.6,49.1L99,38.8L73.3,0zM49.6,67.8L18.5,37l15.3-22.7h31.9l15,22.6L49.6,67.8z"/>
</g>
</g>
</svg>
And here is the image after:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewbox="0 0 563 87.9" enable-background="new 0 0 563 87.9" xml:space="preserve" width="167px" height="26px" fill="#fff">
<g>
<g>
<path d="M137.6,23.6h-15.7v-3.1h34.8v3.1H141v42h-3.3V23.6z">
<path d="M173.3,20.5h18.9c5.5,0,10,1.7,12.7,4.4c2.1,2.1,3.4,5.1,3.4,8.4v0.1c0,7.5-5.6,11.8-13.2,12.9L210,65.6h-4.2l-14.4-18.7h-0.1h-14.6v18.7h-3.3V20.5z M191.8,43.9c7.5,0,13.1-3.8,13.1-10.3v-0.1c0-6-4.8-9.8-12.9-9.8h-15.4v20.3H191.8z">
<path d="M225.6,46.9V20.5h3.3v26c0,10.6,5.7,16.7,15.3,16.7c9.1,0,15-5.5,15-16.4V20.5h3.3v25.9c0,12.9-7.5,19.8-18.5,19.8C233.2,66.3,225.6,59.5,225.6,46.9z">
<path d="M281.6,20.5h32.1v3.1H285v17.7h25.8v3.1H285v18.1h29v3.1h-32.4V20.5z">
<path d="M326.1,20.5H337l11.8,31.7l11.8-31.7h10.7L353,65.9h-8.8L326.1,20.5z">
<path d="M393.6,20.2h9.1l19.3,45.4h-10.4l-4.1-10.1h-19.1l-4.1,10.1h-10.1L393.6,20.2z M404.1,46.7l-6-14.6l-6,14.6H404.1z">
<path d="M433.2,46.3V20.5h9.9V46c0,7.3,3.7,11.1,9.7,11.1c6.1,0,9.7-3.7,9.7-10.8V20.5h9.9V46c0,13.6-7.7,20.3-19.8,20.3C440.6,66.3,433.2,59.5,433.2,46.3z">
<path d="M489,20.5h9.9v36h22.5v9H489V20.5z">
<path d="M539.3,29.7h-13.7v-9.1H563v9.1h-13.7v35.9h-9.9V29.7z">
</g>
<g>
<path d="M63.9,17.6H35.5L22.8,36.5l26.8,26.5l26.8-26.6L63.9,17.6z M60.1,41.1l-0.5,1l-0.4,0.6l-0.7-0.4l-6.7-3.7c-0.6,0.6-1.4,0.9-2.3,0.9c-0.9,0-1.7-0.3-2.3-0.9l-6.7,3.7L40,42.7l-0.4-0.6l-0.5-1l-0.4-0.7l0.7-0.4l6.9-3.8c0,0,0,0,0,0c0-1.3,0.8-2.5,2-3v-7v-0.7H49h1.1h0.7v0.7v7c1.2,0.5,2.1,1.7,2.1,3.1c0,0,0,0,0,0l6.9,3.8l0.7,0.4L60.1,41.1z">
<path d="M73.3,0H26.1L0,38.8l49.6,49.1L99,38.8L73.3,0zM49.6,67.8L18.5,37l15.3-22.7h31.9l15,22.6L49.6,67.8z">
</g>
</g>
</svg>
Notice how by the end of each path element in the input we have a self closing tag "/>". However in the output the self closing tag is transformed to just ">", without the "/" and unfortunately the SVG is messed up :(
Can somebody help me?
Thanks in advance,
Kalo.
Relative image paths seem to also be an issue via declared CSS background
and background-image
properties which unchanged become invalid resources. I was able to get around this via a quick regex replace which, got rid of relative path references ../
. Not sure though if this works for all use cases and haven't thoroughly tested it.
Is there any way to ignore specific css or images/fonts in the inlined css.
For example, I have a font that gets inserted into the inlined critial css due to it being part of an icon in the header. I don't want the font to load at all, until the page has loaded.
Is there anyway to make criticalcss ignore specific files for include?
This seems to be an issue with the imageinliner module (I posted note there about this) - in my case, it looks like this that seems to cause the problem - "background-image: url("data:image/svg+xml;base64,PD94bW...")
for the moment, may be that you need to add an option to avoid the imageinliner (line 74 of index.js)
@bezoerb and I found this nasty little surprise this morning. Something that we should investigate and fix.
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.