Socket
Socket
Sign inDemoInstall

critical

Package Overview
Dependencies
126
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.3 to 0.1.4

175

index.js

@@ -10,8 +10,8 @@ /*

'use strict';
var oust = require('oust');
var fs = require('fs');
var path = require('path');
var penthouse = require('penthouse');
var fs = require('fs');
var path = require('path');
var inliner = require('./inline-styles');
var CleanCSS = require('clean-css');
var CleanCSS = require('clean-css');
var oust = require('oust');
var inliner = require('./inline-styles');

@@ -26,7 +26,6 @@ /**

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.src || !opts.base) {
throw new Error('A valid source and base path are required.');
}

@@ -41,32 +40,48 @@

}
var url = path.join(process.cwd(), opts.base + opts.src);
fs.readFile(url, function (err, html){
if (err) throw err;
// Oust extracts a list of your stylesheets
var hrefs = oust(html, 'stylesheets');
// Penthouse then determines your critical
// path CSS using these as input.
penthouse({
url : url,
css : path.join(process.cwd(), opts.base + hrefs[0]),
// What viewports do you care about?
width : opts.width, // viewport width
height : opts.height // viewport height
}, function (err, criticalCSS) {
if(opts.minify === true){
var minimized = new CleanCSS().minify(criticalCSS);
criticalCSS = minimized;
}
if(opts.dest){
// Write critical-path CSS
fs.writeFile(path.join(process.cwd(), opts.base + opts.dest), criticalCSS, function (err){
cb(err, criticalCSS)
});
} else {
cb(err, criticalCSS);
}
});
});
}
var url = path.join(opts.base, opts.src);
fs.readFile(url, function (err, html) {
if (err) {
cb(err);
return;
}
// Oust extracts a list of your stylesheets
var hrefs = oust(html, 'stylesheets');
// Penthouse then determines your critical
// path CSS using these as input.
penthouse({
url: url,
css: path.join(opts.base, hrefs[0]),
// What viewports do you care about?
width: opts.width, // viewport width
height: opts.height // viewport height
}, function (err, criticalCSS) {
if (err) {
cb(err);
return;
}
if (opts.minify === true) {
criticalCSS = new CleanCSS().minify(criticalCSS);
}
if (opts.dest) {
// Write critical-path CSS
fs.writeFile(path.join(opts.base, opts.dest), criticalCSS, function (err) {
if (err) {
cb(err);
return;
}
cb(null, criticalCSS.toString());
});
} else {
cb(null, criticalCSS.toString());
}
});
});
};
/**

@@ -79,27 +94,34 @@ * Critical path CSS inlining

exports.inline = function (opts, cb) {
opts = opts || {};
cb = cb || function () {};
opts = opts || {};
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
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(process.cwd(), opts.base + opts.dest), out, function (err) {
cb(err, out);
});
} else {
cb(err, out);
if (!opts.src || !opts.base) {
throw new Error('A valid source and base path are required.');
}
});
}
// Inline the critical path CSS
fs.readFile(path.join(opts.base, opts.src), function (err, data) {
if (err) {
cb(err);
return;
}
var out = inliner(data, opts.base, opts.minify);
if (opts.dest) {
// Write HTML with inlined CSS to dest
fs.writeFile(path.join(opts.base, opts.dest), out, function (err) {
if (err) {
cb(err);
return;
}
cb(null, out.toString());
});
} else {
cb(null, out.toString());
}
});
};
/**

@@ -112,16 +134,23 @@ * Generate and inline critical-path CSS

exports.generateInline = function (opts, cb) {
opts = opts || {};
cb = cb || function () {};
if (!opts.styleTarget && !opts.htmlTarget) {
cb(new Error('Valid style and HTML targets are required.'));
return;
}
var genOpts = opts, inlineOpts = opts;
genOpts.dest = opts.styleTarget;
exports.generate(genOpts, function (err, output) {
if (err) cb(err);
inlineOpts.dest = opts.htmlTarget;
exports.inline(inlineOpts);
});
}
opts = opts || {};
cb = cb || function () {};
if (!opts.styleTarget || !opts.htmlTarget) {
throw new Error('Valid style and HTML targets are required.');
}
var genOpts = opts;
var inlineOpts = opts;
genOpts.dest = opts.styleTarget;
exports.generate(genOpts, function (err, output) {
if (err) {
cb(err);
return;
}
inlineOpts.dest = opts.htmlTarget;
exports.inline(inlineOpts);
});
};

@@ -1,39 +0,39 @@

var cheerio = require('cheerio')
var path = require('path')
var cheerio = require('cheerio');
var path = require('path');
// Fork of inline-styles with minification support
var fs = require('fs')
var url = require('url')
var inliner = require('imageinliner')
var CleanCSS = require('clean-css')
var fs = require('fs');
var url = require('url');
var inliner = require('imageinliner');
var CleanCSS = require('clean-css');
module.exports = function(html, base, minify) {
base = base || process.cwd()
var dom = cheerio.load(String(html))
injectStyles(dom)
return new Buffer(dom.html())
base = base || process.cwd();
var dom = cheerio.load(String(html));
injectStyles(dom);
return new Buffer(dom.html());
function injectStyles(dom) {
var styles = [];
dom('link').each(function(idx, el) {
el = dom(el)
var href = el.attr('href')
el = dom(el);
var href = el.attr('href');
if (el.attr('rel') === 'stylesheet' && isLocal(href)) {
var dir = path.dirname(href)
var file = path.join(base, href)
var style = fs.readFileSync(file)
var inlined = inliner.css(style.toString(), { cssBasePath: dir })
var inlinedStyles = inlined.toString()
if(minify) {
inlinedStyles = new CleanCSS().minify(inlinedStyles)
var dir = path.dirname(href);
var file = path.join(base, href);
var style = fs.readFileSync(file);
var inlined = inliner.css(style.toString(), { cssBasePath: dir });
var inlinedStyles = inlined.toString();
if (minify) {
inlinedStyles = new CleanCSS().minify(inlinedStyles);
}
var inlinedTag = "<style>\n" + inlinedStyles + '\n</style>'
el.replaceWith(inlinedTag)
var inlinedTag = "<style>\n" + inlinedStyles + '\n</style>';
el.replaceWith(inlinedTag);
}
})
}
function isLocal(href) {
return href && !url.parse(href).hostname;
}
}
};
{
"name": "critical",
"version": "0.1.3",
"description": "Critical-path CSS generation & inlining",
"main": "index.js",
"version": "0.1.4",
"description": "Extract & Inline Critical-path CSS from HTML",
"author": "Addy Osmani",
"license": "Apache-2.0",
"repository": "addyosmani/critical",
"scripts": {

@@ -22,14 +24,12 @@ "test": "mocha test.js --timeout 15000"

},
"author": "Addy Osmani",
"license": "Apache2",
"dependencies": {
"oust": "0.1.1",
"penthouse": "^0.2.1",
"clean-css": "~2.2.4",
"cheerio": "^0.17.0",
"imageinliner": "^0.2.2"
"clean-css": "^2.2.4",
"imageinliner": "^0.2.2",
"oust": "^0.2.0",
"penthouse": "^0.2.1"
},
"devDependencies": {
"mocha": "^1.20.1"
"mocha": "*"
}
}

@@ -1,12 +0,14 @@

critical
========
# critical [![Build Status](https://travis-ci.org/addyosmani/critical.svg?branch=master)](https://travis-ci.org/addyosmani/critical)
> Critical Path CSS generation &amp; inlining
> Extract & Inline Critical-path CSS from HTML
## Installation
A module by [@addyosmani](http://github.com/addyosmani) and [@sindresorhus](http://github.com/sindresorhus)
## Install
```sh
$ npm install --save critical
```
npm install -g critical
```
## Usage

@@ -16,7 +18,7 @@

```sh
```js
var critical = require('critical');
```
###Generate and inline critical-path CSS
### Generate and inline critical-path CSS

@@ -35,3 +37,3 @@ ```js

###Generate critical-path CSS
### Generate critical-path CSS

@@ -42,8 +44,8 @@ Basic usage:

critical.generate({
base: 'test/',
src: 'index.html',
dest: 'styles/main.css',
width: 320,
height: 480,
});
base: 'test/',
src: 'index.html',
dest: 'styles/main.css',
width: 320,
height: 480
});
```

@@ -55,9 +57,9 @@

critical.generate({
base: 'test/',
src: 'index.html',
width: 320,
dest: 'styles/styles.min.css',
minify: true,
height: 480
});
base: 'test/',
src: 'index.html',
dest: 'styles/styles.min.css',
minify: true,
width: 320,
height: 480
});
```

@@ -69,13 +71,13 @@

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
});
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 `<style>` / critical CSS from generation
### Inline `<style>` / critical CSS from generation

@@ -86,6 +88,6 @@ Basic usage:

critical.inline({
base: 'test/',
src: 'index-critical.html',
dest: 'inlined.html'
});
base: 'test/',
src: 'index-critical.html',
dest: 'inlined.html'
});
```

@@ -97,7 +99,7 @@

critical.inline({
base: 'test/',
src: 'index-critical.html',
dest: 'inlined-minified.html',
minify: true
});
base: 'test/',
src: 'index-critical.html',
dest: 'inlined-minified.html',
minify: true
});
```

@@ -109,52 +111,24 @@

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
});
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
### Options
####base
Type: `String`
| Name | Type | Description |
| ------------- | ------------- | ------------- |
| base | `string` | Base directory in which the source and destination are to be written |
| src | `string` | Location of the HTML source to be operated against |
| dest | `string` | Location of where to save the output of an operation |
| width | `integer` | (Generation only) Width of the target viewport |
| height | `integer` | (Generation only) Height of the target viewport |
| minify | `boolean` | Enable minification of CSS output |
| styleTarget | `string` | (`generateInline` only) Destination for critical-path styles |
| htmlTarget | `string` | (`generateInline` only) Destination for (critical-path CSS) style-inlined HTML |
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
####styleTarget
Type: `string`
(generateInline only) Destination for critical-path styles
####htmlTarget
Type: `string`
(generateInline only) Destination for (critical-path CSS) style-inlined HTML
## Why?

@@ -164,14 +138,31 @@

> CSS is required to construct the render tree for your pages and JavaScript will often block on CSS during initial construction of the page. You should ensure that any non-essential CSS is marked as non-critical (e.g. print and other media queries), and that the amount of critical CSS and the time to deliver it is as small as possible.
> CSS is required to construct the render tree for your pages and JavaScript
will often block on CSS during initial construction of the page.
You should ensure that any non-essential CSS is marked as non-critical
(e.g. print and other media queries), and that the amount of critical CSS
and the time to deliver it is as small as possible.
### Why should critical-path CSS be inlined?
> 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.
> 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
### Are there any sample projects available using Critical?
Why, yes!. Take a look at [this](https://github.com/addyosmani/critical-path-css-demo) Gulp project
which demonstrates using Critical to generate and inline critical-path CSS.
### 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.
I recommend using [Penthouse](http://npmjs.org/package/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

@@ -181,3 +172,1 @@

Copyright 2014 Google Inc
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc