critical
Advanced tools
Comparing version 0.0.1 to 0.1.0
62
index.js
@@ -14,3 +14,4 @@ /* | ||
var path = require('path'); | ||
var inliner = require('inline-styles'); | ||
var inliner = require('./inline-styles'); | ||
var CleanCSS = require('clean-css'); | ||
@@ -25,7 +26,20 @@ /** | ||
opts = opts || {}; | ||
cb = cb || function () {}; | ||
cb = cb || function () {}; | ||
if (!opts.src && !opts.base) { | ||
cb(new Error('A valid source and base path are required.')); | ||
return; | ||
} | ||
if (!opts.height) { | ||
opts.height = 320; | ||
} | ||
if (!opts.width) { | ||
opts.width = 480; | ||
} | ||
var url = opts.base + opts.src; | ||
// Oust extracts a list of your stylesheets | ||
oust({ src: url }, function (hrefs){ | ||
console.log('List of stylesheets extracted.'); | ||
// Penthouse then determines your critical | ||
@@ -40,7 +54,14 @@ // path CSS using these as input. | ||
}, function (err, criticalCSS) { | ||
console.log('Critical-path CSS generated.'); | ||
// Write critical-path CSS | ||
fs.writeFileSync(opts.base + opts.dest, criticalCSS); | ||
console.log('Output written to: ' + opts.base + opts.dest); | ||
cb(criticalCSS); | ||
if(opts.minify === true){ | ||
var minimized = new CleanCSS().minify(criticalCSS); | ||
criticalCSS = minimized; | ||
} | ||
if(opts.dest){ | ||
// Write critical-path CSS | ||
fs.writeFile(path.join(__dirname, opts.base + opts.dest), criticalCSS, function (err){ | ||
cb(err, criticalCSS) | ||
}); | ||
} else { | ||
cb(err, criticalCSS); | ||
} | ||
}); | ||
@@ -59,12 +80,23 @@ }); | ||
cb = cb || function () {}; | ||
if (!opts.src && !opts.base) { | ||
cb(new Error('A valid source and base path are required.')); | ||
return; | ||
} | ||
var url = opts.base + opts.src; | ||
// Inline the critical path CSS | ||
var html = fs.readFileSync(url); | ||
var out = inliner(html, opts.base); | ||
// Write HTML with inlined CSS to dest | ||
fs.writeFileSync(opts.base + opts.dest, out); | ||
console.log('Critical-path CSS inlined.'); | ||
console.log('Output written to ' + opts.base + opts.dest); | ||
cb(out); | ||
fs.readFile(url, function (err, data){ | ||
if (err) throw err; | ||
var out = inliner(data, opts.base, opts.minify); | ||
if (opts.dest){ | ||
// Write HTML with inlined CSS to dest | ||
fs.writeFile(path.join(__dirname, opts.base + opts.dest), out, function (err) { | ||
cb(err, out); | ||
}); | ||
} else { | ||
cb(err, out); | ||
} | ||
}); | ||
} | ||
{ | ||
"name": "critical", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"description": "Critical-path CSS generation & inlining", | ||
@@ -26,3 +26,5 @@ "main": "index.js", | ||
"penthouse": "^0.2.1", | ||
"inline-styles": "^1.0.0" | ||
"clean-css": "~2.2.4", | ||
"cheerio": "^0.17.0", | ||
"imageinliner": "^0.2.2" | ||
}, | ||
@@ -29,0 +31,0 @@ "devDependencies": { |
107
README.md
@@ -22,2 +22,4 @@ critical | ||
Basic usage: | ||
``` | ||
@@ -28,11 +30,38 @@ critical.generate({ | ||
dest: 'styles/main.css', | ||
width: '320', | ||
height: '480', | ||
}, function(output){ | ||
width: 320, | ||
height: 480, | ||
}); | ||
``` | ||
Generate and minify critical-path CSS: | ||
``` | ||
critical.generate({ | ||
base: 'test/', | ||
src: 'index.html', | ||
width: 320, | ||
dest: 'styles/styles.min.css', | ||
minify: true, | ||
height: 480 | ||
}); | ||
``` | ||
Generate and return output via a callback: | ||
``` | ||
critical.generate({ | ||
base: 'test/', | ||
src: 'index.html', | ||
width: 320, | ||
height: 480, | ||
}, function (err, output){ | ||
// You now have critical-path CSS | ||
// Works with and without dest specified | ||
}); | ||
``` | ||
###Inline critical-path CSS | ||
###Inline `<style>` / critical CSS from generation | ||
Basic usage: | ||
``` | ||
@@ -42,8 +71,61 @@ critical.inline({ | ||
src: 'index-critical.html', | ||
dest: 'critical.html' | ||
}, function(output){ | ||
dest: 'inlined.html' | ||
}); | ||
``` | ||
Minify and inline stylesheets: | ||
``` | ||
critical.inline({ | ||
base: 'test/', | ||
src: 'index-critical.html', | ||
dest: 'inlined-minified.html', | ||
minify: true | ||
}); | ||
``` | ||
Inline and return output via a callback: | ||
``` | ||
critical.inline({ | ||
base: 'test/', | ||
src: 'index-critical.html', | ||
}, function (err, output){ | ||
// You now have HTML with inlined critical-path CSS | ||
// Works with and without dest specified | ||
}); | ||
``` | ||
###Options | ||
####base | ||
Type: `String` | ||
Base directory in which the source and destination are to be written. | ||
####src | ||
Type: `String` | ||
Location of the HTML source to be operated against. | ||
####dest | ||
Type: `String` | ||
Location of where to save the output of an operation. | ||
####width | ||
Type: `integer` | ||
(Generation only) Width of the target viewport. | ||
####height | ||
Type: `integer` | ||
(Generation only) Height of the target viewport. | ||
####minify | ||
Type: `boolean` | ||
Enable minification of CSS output | ||
## Why? | ||
@@ -58,1 +140,14 @@ | ||
> For best performance, you may want to consider inlining the critical CSS directly into the HTML document. This eliminates additional roundtrips in the critical path and if done correctly can be used to deliver a “one roundtrip” critical path length where only the HTML is a blocking resource. | ||
## FAQ | ||
### When should I just use Penthouse directly? | ||
I recommend using Penthouse directly if your app has a large number of styles or stylesheets being dynamically injected into the DOM. Critical is best used when your page uses a fixed set of stylesheets as we can automatically scrape this for you, avoiding the overhead of passing known styles yourself manually to Penthouse. | ||
## License | ||
Apache 2.0 | ||
Copyright 2014 Google Inc | ||
6255
88
150
5
+ Addedcheerio@^0.17.0
+ Addedclean-css@~2.2.4
+ Addedimageinliner@^0.2.2
+ Addedclean-css@2.2.23(transitive)
+ Addedcommander@2.2.0(transitive)
- Removedinline-styles@^1.0.0
- Removedinline-styles@1.0.0(transitive)