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

Use webpack chunkhash to enable long-term caching #597

Merged
merged 2 commits into from
Nov 3, 2016
Merged
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
20 changes: 11 additions & 9 deletions src/server/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import path from 'path';
import fs from 'fs';
import chalk from 'chalk';
import shelljs from 'shelljs';
import uuid from 'uuid';
import packageJson from '../../package.json';
import getBaseConfig from './config/webpack.config.prod';
import loadConfig from './config';
Expand Down Expand Up @@ -73,19 +72,22 @@ if (program.staticDir) {
});
}

const cacheKey = uuid.v4();
// Write both the storybook UI and IFRAME HTML files to destination path.
const headHtml = getHeadHtml(configDir);
const publicPath = config.output.publicPath;
fs.writeFileSync(path.resolve(outputDir, 'index.html'), getIndexHtml(publicPath, cacheKey));
fs.writeFileSync(path.resolve(outputDir, 'iframe.html'), getIframeHtml(headHtml, publicPath, cacheKey));

// compile all resources with webpack and write them to the disk.
logger.log('Building storybook ...');
webpack(config).run(function (err) {
webpack(config).run(function (err, stats) {
if (err) {
logger.error('Failed to build the storybook');
logger.error(err.message);
process.exit(1);
}

const data = {
publicPath: config.output.publicPath,
assets: stats.toJson().assetsByChunkName,
};
const headHtml = getHeadHtml(configDir);

// Write both the storybook UI and IFRAME HTML files to destination path.
fs.writeFileSync(path.resolve(outputDir, 'index.html'), getIndexHtml(data));
fs.writeFileSync(path.resolve(outputDir, 'iframe.html'), getIframeHtml({ ...data, headHtml }));
});
2 changes: 1 addition & 1 deletion src/server/config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function () {
devtool: '#cheap-module-source-map',
entry: entries,
output: {
filename: 'static/[name].bundle.js',
filename: 'static/[name].[chunkhash].bundle.js',
// Here we set the publicPath to ''.
// This allows us to deploy storybook into subpaths like GitHub pages.
// This works with css and image loaders too.
Expand Down
42 changes: 39 additions & 3 deletions src/server/iframe.html.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,42 @@
import url from 'url';

export default function (headHtml, publicPath, cacheKey) {
const previewUrl = cacheKey ? `static/preview.bundle.js?${cacheKey}` : 'static/preview.bundle.js';
// assets.preview will be:
// - undefined
// - string e.g. 'static/preview.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// [ 'static/preview.9adbb5ef965106be1cc3.bundle.js',
// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css',
// 'static/preview.9adbb5ef965106be1cc3.bundle.js.map',
// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css.map' ]
const previewUrlsFromAssets = (assets) => {
if (!assets) {
return {
js: 'static/preview.bundle.js',
};
}

if (typeof assets.preview === 'string') {
return {
js: assets.preview,
};
}

return {
js: assets.preview.find(filename => filename.match(/\.js$/)),
css: assets.preview.find(filename => filename.match(/\.css$/)),
};
};

export default function (data) {
const { assets, headHtml, publicPath } = data;

const previewUrls = previewUrlsFromAssets(assets);

let previewCssTag;
if (previewUrls.css) {
previewCssTag = `<link rel='stylesheet' type='text/css' href='${url.resolve(publicPath, previewUrls.css)}'>`;
}

return `
<!DOCTYPE html>
<html>
Expand All @@ -15,11 +50,12 @@ export default function (headHtml, publicPath, cacheKey) {
</script>
<title>React Storybook</title>
${headHtml}
${previewCssTag}
</head>
<body>
<div id="root"></div>
<div id="error-display"></div>
<script src="${url.resolve(publicPath, previewUrl)}"></script>
<script src="${url.resolve(publicPath, previewUrls.js)}"></script>
</body>
</html>
`;
Expand Down
35 changes: 32 additions & 3 deletions src/server/index.html.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
import url from 'url';

export default function (publicPath, cacheKey) {
const managerUrl = cacheKey ? `static/manager.bundle.js?${cacheKey}` : 'static/manager.bundle.js';
// assets.manager will be:
// - undefined
// - string e.g. 'static/manager.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// assets.manager will be something like:
// [ 'static/manager.c6e6350b6eb01fff8bad.bundle.js',
// 'static/manager.c6e6350b6eb01fff8bad.bundle.js.map' ]
const managerUrlsFromAssets = (assets) => {
if (!assets) {
return {
js: 'static/manager.bundle.js',
};
}

if (typeof assets.manager === 'string') {
return {
js: assets.manager,
};
}

return {
js: assets.manager.find(filename => filename.match(/\.js$/)),
css: assets.manager.find(filename => filename.match(/\.css$/)),
};
};

export default function (data) {
const { assets, publicPath } = data;

const managerUrls = managerUrlsFromAssets(assets);

return `
<!DOCTYPE html>
<html>
Expand Down Expand Up @@ -41,7 +70,7 @@ export default function (publicPath, cacheKey) {
</head>
<body style="margin: 0;">
<div id="root"></div>
<script src="${url.resolve(publicPath, managerUrl)}"></script>
<script src="${url.resolve(publicPath, managerUrls.js)}"></script>
</body>
</html>
`;
Expand Down