Skip to content

Instantly share code, notes, and snippets.

@2j2e
Created December 11, 2015 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2j2e/9cd9e5e756c09a5d2fd1 to your computer and use it in GitHub Desktop.
Save 2j2e/9cd9e5e756c09a5d2fd1 to your computer and use it in GitHub Desktop.
postcss-media-image-preloader
/* Base hack */
@media only screen {
#app:after {
content: 'small';
}
}
@media only screen and (min-width: 30.063em) {
#app:after {
content: 'medium';
}
}
@media only screen and (min-width: 64em) {
#app:after {
content: 'large';
}
}
@media only screen and (min-width: 105em) {
#app:after {
content: 'wide';
}
}
var processor = postcss([
postcssImagePreload({
output: `./public/static/js/preload.js`,
rules: [
{name: 'small', value: ''},
{name: 'medium', value: '30.063'},
{name: 'large', value: '64', load: ['wide']},
{name: 'wide', value: '105', load: ['large']}
]
})
});
var fs = require('fs'),
path = require('path'),
postcss = require('postcss'),
valueParser = require('postcss-value-parser'),
helper = require('./common');
module.exports = postcss.plugin('postcss-image-preload', function (opts) {
opts = opts || {};
if (!Object.keys(opts).length)
return function () {
};
if (!opts.output)
throw new Error('[postcss-image-preload] `output` is required');
return function (css, result) {
var images = {};
var imageGroup = [];
var rule = null;
css.walk(function (node) {
if (node.type == 'atrule' && node.name == 'media') {
var minWidthRegex = /min-width: ([\d\.]+)/
var found = minWidthRegex.exec(node.params);
var newRule = opts.rules.find(x => x.value == (found ? found[1] : ''));
// save previous media rule images
if (imageGroup.length > 0 && rule != null) {
images[rule.name] = {urls: imageGroup, load: rule.load};
}
rule = newRule;
imageGroup = [];
}
if (node.type === 'decl' && node.prop == 'background-image') {
var nodeValue = valueParser(node.value);
nodeValue.walk(function (node) {
if (node.type !== 'function' || node.value !== 'url') {
return;
}
if (!node.nodes.length) {
node.warn(result, [`${node.value} should not be empty`]);
return;
}
if (node.nodes[0].type === 'string' && node.nodes[0].value.indexOf('data:') == -1) {
imageGroup.push(node.nodes[0].value);
}
});
}
});
// save last media rule images
if (imageGroup.length > 0 && rule != null) {
images[rule.name] = {urls: imageGroup, load: rule.load};
}
generateJs(opts.output, images);
};
function generateJs(output, images) {
var absTemplatePath = path.resolve(__dirname, 'postcss-image-reload-template.js');
var absOutputPath = path.resolve(output);
fs.readFile(absTemplatePath, 'utf8', function (errd, content) {
if (err) throw err;
var jsonResult = JSON.stringify(images);
content = content.replace('JSON.parse(\'[]\')', 'JSON.parse(\'' + jsonResult + '\')');
helper.createPath(absOutputPath);
fs.writeFile(absOutputPath, content, function (err) {
if (err) throw err;
console.log('Preloader file has been saved');
});
});
}
});
(function (win) {
var doc = win.document, el, media;
if (win.getComputedStyle && doc.querySelector) {
el = doc.querySelector('#app');
media = win.getComputedStyle(el, ':after').getPropertyValue('content');
media = media ? media.slice(1).slice(0, -1): '';
}
function preloader() {
if (!media)
return;
var images = JSON.parse('[]');
var current = images[media];
for (var i = 0; i < current.urls.length; i++) {
new Image().src = current.urls[i];
}
if (current.load) {
for (var i = 0; i < current.load.length; i++) {
var sideLoad = images[current.load[i]].urls;
for (var j = 0; j < sideLoad.length; j++) {
new Image().src = sideLoad[j];
}
}
}
}
this.onload = preloader;
})(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment