Skip to content
This repository has been archived by the owner on Sep 15, 2020. It is now read-only.

Add grunt-critical. #84

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
/node_modules
/npm-debug.log
/source/.jekyll-metadata
/source/assets/css/critical.css
44 changes: 43 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,20 @@ module.exports = function(grunt) {
}
},

critical: {
dist: {
options: {
base: '<%= dirs.dest %>',
css: ['<%= concat.css.dest %>'],
extract: true,
width: 1300,
height: 900
},
src: '<%= dirs.dest %>/index.html',
dest: '<%= dirs.src %>/assets/css/critical.css'
}
},

cssmin: {
minify: {
options: {
Expand Down Expand Up @@ -204,9 +218,13 @@ module.exports = function(grunt) {
options: {
assetsDirs: [
'<%= dirs.dest %>/',
'<%= dirs.dest %>/assets/css/',
'<%= dirs.dest %>/assets/img/'
],
patterns: {
html: [
[/loadCSS\(['"]([^"']+)['"]\)/gm, 'Replacing reference to CSS within `loadCSS`']
],
js: [
[/navigator\.serviceWorker\.register\(["'](\/sw\.min\.js)["']/gm, 'Replacing reference to sw.min.js']
]
Expand All @@ -225,6 +243,7 @@ module.exports = function(grunt) {
options: {
base: 'https://cdn.mpc-hc.org/',
html: {
'link[rel="preload"]': 'href',
'meta[itemprop="image"]': 'content',
'meta[property="og:image:secure_url"]': 'content',
'input[type="image"]': 'src'
Expand All @@ -239,6 +258,20 @@ module.exports = function(grunt) {
}
},

staticinline: {
dist: {
options: {
basepath: '<%= dirs.src %>/'
},
files: [{
expand: true,
cwd: '<%= dirs.dest %>/',
src: '**/*.{html,php}',
dest: '<%= dirs.dest %>/'
}]
}
},

connect: {
options: {
hostname: 'localhost',
Expand Down Expand Up @@ -297,6 +330,11 @@ module.exports = function(grunt) {
},

htmllint: {
options: {
ignore: [
'A "link" element with an "integrity" attribute must have a "rel" attribute that contains the value "stylesheet".'
]
},
src: '<%= dirs.dest %>/**/*.html'
},

Expand Down Expand Up @@ -384,6 +422,8 @@ module.exports = function(grunt) {
'concat',
'autoprefixer',
'uncss',
'critical',
'staticinline',
'cssmin',
'uglify',
'filerev',
Expand All @@ -398,7 +438,7 @@ module.exports = function(grunt) {
var envCI = process.env.CI || process.env.ci;

if (envCI && envCI.toLowerCase() === 'true') {
buildTasks.splice(12, 1);
buildTasks.splice(14, 1);
}

grunt.registerTask('build', buildTasks);
Expand All @@ -417,6 +457,8 @@ module.exports = function(grunt) {
'useminPrepare',
'concat',
'autoprefixer',
'critical',
'staticinline',
'filerev',
'usemin',
'generate-sri',
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
"grunt-contrib-htmlmin": "^2.0.0",
"grunt-contrib-uglify": "^2.0.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-critical": "^0.2.2",
"grunt-eslint": "^19.0.0",
"grunt-filerev": "^2.3.1",
"grunt-html": "^8.4.0",
"grunt-include-replace": "^5.0.0",
"grunt-jekyll": "^0.4.2",
"grunt-static-inline": "^0.1.9",
"grunt-uncss": "^0.6.0",
"grunt-usemin": "^3.1.1",
"load-grunt-tasks": "^3.4.0",
Expand Down
8 changes: 7 additions & 1 deletion source/_includes/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
<meta name="description" content="{{ meta_description }}">
<meta name="generator" content="Jekyll v{{ jekyll.version }}">

<link rel="stylesheet" href="/assets/css/pack.css" integrity="@@packCssIntegrity" crossorigin="anonymous">
<link rel="stylesheet" href="/assets/css/critical.css" inline="true">
<link rel="preload" href="/assets/css/pack.css" as="style" onload="this.rel='stylesheet'" integrity="@@packCssIntegrity" crossorigin="anonymous">

<noscript>
<link rel="stylesheet" href="/assets/css/pack.css" integrity="@@packCssIntegrity" crossorigin="anonymous">
</noscript>

<link rel="apple-touch-icon" href="/assets/img/favicons/apple-touch-icon.png" sizes="180x180">
<link rel="icon" href="/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
Expand Down Expand Up @@ -64,6 +69,7 @@

{% feed_meta %}

<script src="/assets/js/vendor/loadCSS.js" inline="true"></script>
</head>

{% capture body_class %}{{ page.layout }}{% if page.body_class %} page-{{ page.body_class }}{% elsif page.slug %} page-{{ page.slug | slugify }}{% endif %}{% endcapture %}
Expand Down
124 changes: 124 additions & 0 deletions source/assets/js/vendor/loadCSS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
(function(w){
"use strict";
/* exported loadCSS */
var loadCSS = function( href, before, media ){
// Arguments explained:
// `href` [REQUIRED] is the URL for your CSS file.
// `before` [OPTIONAL] is the element the script should use as a reference for injecting our stylesheet <link> before
// By default, loadCSS attempts to inject the link after the last stylesheet or script in the DOM. However, you might desire a more specific location in your document.
// `media` [OPTIONAL] is the media type or query of the stylesheet. By default it will be 'all'
var doc = w.document;
var ss = doc.createElement( "link" );
var ref;
if( before ){
ref = before;
}
else {
var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
ref = refs[ refs.length - 1];
}

var sheets = doc.styleSheets;
ss.rel = "stylesheet";
ss.href = href;
// temporarily set media to something inapplicable to ensure it'll fetch without blocking render
ss.media = "only x";

// wait until body is defined before injecting link. This ensures a non-blocking load in IE11.
function ready( cb ){
if( doc.body ){
return cb();
}
setTimeout(function(){
ready( cb );
});
}
// Inject link
// Note: the ternary preserves the existing behavior of "before" argument, but we could choose to change the argument to "after" in a later release and standardize on ref.nextSibling for all refs
// Note: `insertBefore` is used instead of `appendChild`, for safety re: http://www.paulirish.com/2011/surefire-dom-element-insertion/
ready( function(){
ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
});
// A method (exposed on return object for external use) that mimics onload by polling document.styleSheets until it includes the new sheet.
var onloadcssdefined = function( cb ){
var resolvedHref = ss.href;
var i = sheets.length;
while( i-- ){
if( sheets[ i ].href === resolvedHref ){
return cb();
}
}
setTimeout(function() {
onloadcssdefined( cb );
});
};

function loadCB(){
if( ss.addEventListener ){
ss.removeEventListener( "load", loadCB );
}
ss.media = media || "all";
}

// once loaded, set link's media back to `all` so that the stylesheet applies once it loads
if( ss.addEventListener ){
ss.addEventListener( "load", loadCB);
}
ss.onloadcssdefined = onloadcssdefined;
onloadcssdefined( loadCB );
return ss;
};
// commonjs
if( typeof exports !== "undefined" ){
exports.loadCSS = loadCSS;
}
else {
w.loadCSS = loadCSS;
}
}( typeof global !== "undefined" ? global : this ));

/*! loadCSS rel=preload polyfill. [c]2017 Filament Group, Inc. MIT License */
(function( w ){
// rel=preload support test
if( !w.loadCSS ){
return;
}
var rp = loadCSS.relpreload = {};
rp.support = function(){
try {
return w.document.createElement( "link" ).relList.supports( "preload" );
} catch (e) {
return false;
}
};

// loop preload links and fetch using loadCSS
rp.poly = function(){
var links = w.document.getElementsByTagName( "link" );
for( var i = 0; i < links.length; i++ ){
var link = links[ i ];
if( link.rel === "preload" && link.getAttribute( "as" ) === "style" ){
w.loadCSS( link.href, link, link.getAttribute( "media" ) );
link.rel = null;
}
}
};

// if link[rel=preload] is not supported, we must fetch the CSS manually using loadCSS
if( !rp.support() ){
rp.poly();
var run = w.setInterval( rp.poly, 300 );
if( w.addEventListener ){
w.addEventListener( "load", function(){
rp.poly();
w.clearInterval( run );
} );
}
if( w.attachEvent ){
w.attachEvent( "onload", function(){
w.clearInterval( run );
} )
}
}
}( this ));