Skip to content

Commit

Permalink
Include in response only CSS variations that are needed (#41)
Browse files Browse the repository at this point in the history
* Initial optimization work

* Fix site slug resolution

* Ensures layout CSS appears

* workin

* Update media, styleguide tests so that they reflect the new changes

* Fix linting errors in styleguide test

* Never let getStyleFiles throw an error, complete branch coverage also
  • Loading branch information
cperryk authored and jonwinton committed May 29, 2018
1 parent 0d0ca97 commit c756672
Show file tree
Hide file tree
Showing 5 changed files with 470 additions and 230 deletions.
120 changes: 57 additions & 63 deletions lib/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const _ = require('lodash'),
files = require('nymag-fs'),
bluebird = require('bluebird'),
setup = require('./setup'),
styleguide = require('./styleguide'),
STYLE_TAG = 'style',
SCRIPT_TAG = 'scripts',
MEDIA_DIRECTORY = path.join(process.cwd(), 'public');
Expand Down Expand Up @@ -160,91 +159,86 @@ function injectTags(fileArray, site, tag) {

/**
* Gets a list of all css and js needed for the components listed.
*
* NOTE: the getStyles and getScripts are memoized using all arguments
*
* @param {Array} componentList
* @param {string} slug
* @param {Object} state
* @returns {{styles: Array, scripts: Array}}
*/
function getMediaMap({ _components:componentList, locals }) {
function getMediaMap(state) {
return {
styles: flatMap(componentList, (component) => module.exports.getStyles(component, locals.site)),
scripts: flatMap(componentList, (component) => module.exports.getScripts(component, locals.site))
styles: module.exports.getStyleFiles(state),
scripts: module.exports.getScriptFiles(state)
};
}

/**
* Get the proper scripts for the component
* Get the proper styles for the component. If a styleguide is configured, use
* that css. Defaults to the site slug
*
* @param {string} name
* @param {object} site
* @param {Object} state
* @returns {array}
*/
function getScripts(name, site) {
const slug = site.slug,
function getStyleFiles(state) {
const { site } = state.locals,
assetDir = site && site.assetDir || MEDIA_DIRECTORY,
assetPath = site && site.assetPath || '',
assetHost = site && site.assetHost || '';

return _.map(_.filter([
path.join(assetDir, 'js', `${name}.js`),
path.join(assetDir, 'js', `${name}.${slug}.js`),
path.join(assetDir, 'js', `${name}.client.js`)
], files.fileExists), pathJoin(assetHost, assetPath, assetDir));
}
assetHost = site && site.assetHost || '',
siteStyleguide = site && site.styleguide;
let cssFilePaths = [];

// legacy behavior: load <component>.css and <component>.<site>.css
if (!site.styleguide) {
const siteSlug = site && site.slug;

cssFilePaths = state._components
.reduce((acc, curr) => {
acc.push(
path.join(assetDir, 'css', `${curr}.css`),
path.join(assetDir, 'css', `${curr}.${siteSlug}.css`)
);
return acc;
}, []);
// modern behavior: compile all used variations
} else if (state._usedVariations) {
cssFilePaths = state._usedVariations
.map(variation => {
const styleguideVariationPath = path.join(assetDir, 'css', `${variation}.${siteStyleguide}.css`);

return files.fileExists(styleguideVariationPath) ?
styleguideVariationPath :
path.join(assetDir, 'css', `${variation}._default.css`);
});
}

/**
* @param {Array} list
* @param {function} fn
* @returns {Array}
*/
function flatMap(list, fn) {
return _.filter(_.flattenDeep(_.map(list, fn)), _.identity);
return cssFilePaths
.filter(files.fileExists)
.map(pathJoin(assetHost, assetPath, assetDir));
}

/**
* Get the proper styles for the component. If a styleguide is configured, use
* that css. Defaults to the site slug
* Get the proper scripts for the component
*
* @param {string} name
* @param {object} site
* @returns {array}
*/
function getStyles(name, site) {
const siteStyleguide = site && site.styleguide,
siteSlug = site && site.slug,

function getScriptFiles(state) {
const site = state.locals.site,
slug = site.slug,
assetDir = site && site.assetDir || MEDIA_DIRECTORY,
assetPath = site && site.assetPath || '',
assetHost = site && site.assetHost || '';

let availableVariations, styleguidePath, cssFilePaths;

if (!siteStyleguide) {
// legacy behavior: load <component>.css and <component>.<site>.css
cssFilePaths = [
path.join(assetDir, 'css', `${name}.css`),
path.join(assetDir, 'css', `${name}.${siteSlug}.css`)
];
} else {
// styleguides: load <component>.<styleguide>.css and <component>_<variation>.<styleguide>.css
// note: this also loads default styles if the site styleguide doesn't have styles for a certain component / variation
availableVariations = styleguide.getVariations(siteStyleguide);
styleguidePath = path.join(assetDir, 'css', `${name}.${siteStyleguide}.css`);
cssFilePaths = files.fileExists(styleguidePath) ? [styleguidePath] : [path.join(assetDir, 'css', `${name}._default.css`)]; // fall back to default styleguide

// if there are variations available for the component, add them to the list
// of file paths we want
if (availableVariations[name]) {
availableVariations[name].forEach((variation) => {
let styleguideVariationPath = path.join(assetDir, 'css', `${variation}.${siteStyleguide}.css`);

cssFilePaths.push(files.fileExists(styleguideVariationPath) ? styleguideVariationPath : path.join(assetDir, 'css', `${variation}._default.css`));
});
}
}

return _.map(_.filter(cssFilePaths, files.fileExists), pathJoin(assetHost, assetPath, assetDir));
return state._components
.reduce((prev, name) => {
prev.push(
path.join(assetDir, 'js', `${name}.js`),
path.join(assetDir, 'js', `${name}.${slug}.js`),
path.join(assetDir, 'js', `${name}.client.js`)
);
return prev;
}, [])
.filter(files.fileExists)
.map(pathJoin(assetHost, assetPath, assetDir));
}

/**
Expand Down Expand Up @@ -340,5 +334,5 @@ module.exports.editStylesTags = false;
module.exports.editScriptsTags = false;

// For testing
module.exports.getScripts = getScripts;
module.exports.getStyles = getStyles;
module.exports.getScriptFiles = getScriptFiles;
module.exports.getStyleFiles = getStyleFiles;
Loading

0 comments on commit c756672

Please sign in to comment.