Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding fingerprint to compiled css #694

Closed
wants to merge 14 commits into from
Closed
12 changes: 11 additions & 1 deletion lib/__tests__/build-files.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const fs = require('fs-extra');
const glob = require('glob-promise');
const rimraf = require('rimraf');
const shell = require('shelljs');
const path = require('path');
const {fingerprintCss} = require('../server/utils.js');

const CWD = process.cwd();

Expand Down Expand Up @@ -88,10 +90,18 @@ test('Generated table of contents', function() {
});

test('Concatenated CSS files', function() {
const secureHash = fingerprintCss(
path.join(CWD, 'website', 'static', 'css', '*.css')
);
return Promise.all([
glob(staticCSSDir + '/*.css'),
fs.readFile(
buildDir + '/' + siteConfig.projectName + '/css/main.css',
buildDir +
'/' +
siteConfig.projectName +
'/css/main.' +
secureHash +
'.css',
'utf8'
),
]).then(function(results) {
Expand Down
1 change: 1 addition & 0 deletions lib/core/BlogPageLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class BlogPageLayout extends React.Component {
<Site
title="Blog"
language="en"
hash={this.props.hash}
config={this.props.config}
metadata={{blog: true, blogListing: true}}>
<div className="docMainWrapper wrapper">
Expand Down
1 change: 1 addition & 0 deletions lib/core/BlogPostLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class BlogPostLayout extends React.Component {
return (
<Site
className="sideNavVisible"
hash={this.props.hash}
url={'blog/' + post.path}
title={this.props.metadata.title}
language={'en'}
Expand Down
1 change: 1 addition & 0 deletions lib/core/DocsLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class DocsLayout extends React.Component {
config={this.props.config}
className="sideNavVisible doc"
title={title}
hash={this.props.hash}
description={content.trim().split('\n')[0]}
language={metadata.language}
version={metadata.version}
Expand Down
6 changes: 5 additions & 1 deletion lib/core/Head.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ class Head extends React.Component {
{/* Site defined code. Keep these at the end to avoid overriding. */}
<link
rel="stylesheet"
href={this.props.config.baseUrl + 'css/main.css'}
href={
this.props.hash
? `${this.props.config.baseUrl}css/main.${this.props.hash}.css`
: `${this.props.config.baseUrl}css/main.css`
}
/>
</head>
);
Expand Down
1 change: 1 addition & 0 deletions lib/core/Redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Redirect extends React.Component {
<html>
<Head
config={this.props.config}
hash={this.props.hash}
description={description}
title={title}
url={url}
Expand Down
1 change: 1 addition & 0 deletions lib/core/Site.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Site extends React.Component {
<Head
config={this.props.config}
description={description}
hash={this.props.hash}
title={title}
url={url}
/>
Expand Down
27 changes: 22 additions & 5 deletions lib/server/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ async function execute() {
const imageminOptipng = require('imagemin-optipng');
const imageminSvgo = require('imagemin-svgo');
const imageminGifsicle = require('imagemin-gifsicle');
const {fingerprintCss} = require('./utils.js');
const secureHash = fingerprintCss(join(CWD, 'static', 'css', '*.css'));

commander.option('--skip-image-compression').parse(process.argv);

Expand Down Expand Up @@ -192,7 +194,11 @@ async function execute() {
);

const docComp = (
<DocsLayout metadata={metadata} language={language} config={siteConfig}>
<DocsLayout
hash={secureHash}
metadata={metadata}
language={language}
config={siteConfig}>
{rawContent}
</DocsLayout>
);
Expand All @@ -212,6 +218,7 @@ async function execute() {
const redirectComp = (
<Redirect
metadata={metadata}
hash={secureHash}
language={language}
config={siteConfig}
redirect={siteConfig.baseUrl + redirectlink}
Expand Down Expand Up @@ -277,6 +284,7 @@ async function execute() {
let language = 'en';
const blogPostComp = (
<BlogPostLayout
hash={secureHash}
metadata={metadata}
language={language}
config={siteConfig}>
Expand All @@ -296,6 +304,7 @@ async function execute() {
const metadata = {page: page, perPage: perPage};
const blogPageComp = (
<BlogPageLayout
hash={secureHash}
metadata={metadata}
language={language}
config={siteConfig}
Expand Down Expand Up @@ -458,7 +467,8 @@ async function execute() {
preset: 'default',
}
);
fs.writeFileSync(mainCss, css);
fs.unlinkSync(mainCss);
fs.writeFileSync(join(buildDir, 'css/', 'main.' + secureHash + '.css'), css);

// compile/copy pages from user
let pagesArr = [];
Expand Down Expand Up @@ -511,6 +521,7 @@ async function execute() {
<Site
language={language}
config={siteConfig}
hash={secureHash}
title={ReactComp.title}
description={ReactComp.description}
metadata={{id: pageID}}>
Expand All @@ -529,9 +540,10 @@ async function execute() {
translate.setLanguage(language);
const str = renderToStaticMarkupWithDoctype(
<Site
title={ReactComp.title}
hash={secureHash}
language={language}
config={siteConfig}
title={ReactComp.title}
description={ReactComp.description}
metadata={{id: pageID}}>
<ReactComp language={language} />
Expand All @@ -547,9 +559,10 @@ async function execute() {
translate.setLanguage(language);
const str = renderToStaticMarkupWithDoctype(
<Site
title={ReactComp.title}
hash={secureHash}
language={language}
config={siteConfig}
title={ReactComp.title}
description={ReactComp.description}
metadata={{id: pageID}}>
<ReactComp language={language} />
Expand All @@ -566,7 +579,11 @@ async function execute() {
const parts = normalizedFile.split('pages');
const targetFile = join(buildDir, parts[1]);
const str = renderToStaticMarkupWithDoctype(
<Site language="en" config={siteConfig} metadata={{id: pageID}}>
<Site
hash={secureHash}
language="en"
config={siteConfig}
metadata={{id: pageID}}>
<div
dangerouslySetInnerHTML={{
__html: fs.readFileSync(normalizedFile, {encoding: 'utf8'}),
Expand Down
21 changes: 20 additions & 1 deletion lib/server/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/
const path = require('path');
const escapeStringRegexp = require('escape-string-regexp');
const env = require('./env.js');
const fs = require('fs-extra');
const glob = require('glob');
const crypto = require('crypto');

// Return the subdirectory path from a reference directory
// Example:
Expand All @@ -29,6 +31,7 @@ function getLanguage(file, refDir) {
const match = regexSubFolder.exec(file);

// Avoid misinterpreting subdirectory as language
const env = require('./env.js');
if (match && env.translation.enabled) {
const enabledLanguages = env.translation
.enabledLanguages()
Expand All @@ -40,7 +43,23 @@ function getLanguage(file, refDir) {
return null;
}

// create hash based on css content from static folder
function fingerprintCss(cssPath) {
let cssForHashing = fs.readFileSync(
path.join(__dirname, '../static/css', 'main.css')
);
glob.sync(cssPath).forEach(file => {
const normalizedFile = path.normalize(file);
cssForHashing += fs.readFileSync(normalizedFile, 'utf8');
});
return crypto
.createHash('sha1')
.update(cssForHashing, 'utf8')
.digest('hex');
}

module.exports = {
getSubDir,
getLanguage,
fingerprintCss,
};