Skip to content

Commit

Permalink
_headers & _redirects generation (GoogleChromeLabs#240)
Browse files Browse the repository at this point in the history
* Generate `_headers` and `_redirects` by passing assets through ejs templates.

* PR feedback

* Excluding service worker stuff from prerender

* Build SW in dev

* Let's give this a try

* lol

* Is this how it works?
  • Loading branch information
developit authored and jakearchibald committed Nov 9, 2018
1 parent 9b572f9 commit 6994cc3
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 2 deletions.
15 changes: 15 additions & 0 deletions _headers.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Long-term cache by default.
/*
Cache-Control: max-age=31536000

# And here are the exceptions:
/
Cache-Control: no-cache

/serviceworker.js
Cache-Control: no-cache

# URLs in /assets do not include a hash and are mutable.
# But it isn't a big deal if the user gets an old version.
/assets/*
Cache-Control: must-revalidate, max-age=3600
47 changes: 47 additions & 0 deletions config/asset-template-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const path = require('path');
const fs = require('fs');
const ejs = require('ejs');
const AssetsPlugin = require('assets-webpack-plugin');

module.exports = class AssetTemplatePlugin extends AssetsPlugin {
constructor(options) {
options = options || {};
if (!options.template) throw Error('AssetTemplatePlugin: template option is required.');
super({
useCompilerPath: true,
filename: options.filename,
processOutput: files => this._processOutput(files)
});
this._template = path.resolve(process.cwd(), options.template);
const ignore = options.ignore || /(manifest\.json|\.DS_Store)$/;
this._ignore = typeof ignore === 'function' ? ({ test: ignore }) : ignore;
}

_processOutput(files) {
const mapping = {
all: [],
byType: {},
entries: {}
};
for (const entryName in files) {
// non-entry-point-derived assets are collected under an empty string key
// since that's a bit awkward, we'll call them "assets"
const name = entryName === '' ? 'assets' : entryName;
const listing = files[entryName];
const entry = mapping.entries[name] = {
all: [],
byType: {}
};
for (let type in listing) {
const list = [].concat(listing[type]).filter(file => !this._ignore.test(file));
if (!list.length) continue;
mapping.all = mapping.all.concat(list);
mapping.byType[type] = (mapping.byType[type] || []).concat(list);
entry.all = entry.all.concat(list);
entry.byType[type] = (entry.byType[type] || []).concat(list);
}
}
mapping.files = mapping.all;
return ejs.render(fs.readFileSync(this._template, 'utf8'), mapping);
}
};
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@types/pretty-bytes": "^5.1.0",
"@types/webassembly-js-api": "0.0.1",
"@webcomponents/custom-elements": "^1.2.1",
"assets-webpack-plugin": "^3.9.7",
"babel-loader": "^7.1.5",
"babel-plugin-jsx-pragmatic": "^1.0.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
Expand All @@ -36,6 +37,7 @@
"copy-webpack-plugin": "^4.5.3",
"critters-webpack-plugin": "^2.0.1",
"css-loader": "^0.28.11",
"ejs": "^2.6.1",
"exports-loader": "^0.7.0",
"file-drop-element": "^0.0.9",
"file-loader": "^1.1.11",
Expand Down
3 changes: 3 additions & 0 deletions src/lib/offliner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ async function updateReady(reg: ServiceWorkerRegistration): Promise<void> {

/** Set up the service worker and monitor changes */
export async function offliner(showSnack: SnackBarElement['showSnackbar']) {
// This needs to be a typeof because Webpack.
if (typeof PRERENDER === 'boolean') return;

if (process.env.NODE_ENV === 'production') {
navigator.serviceWorker.register('../sw');
}
Expand Down
8 changes: 6 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl
const WorkerPlugin = require('worker-plugin');
const AutoSWPlugin = require('./config/auto-sw-plugin');
const CrittersPlugin = require('critters-webpack-plugin');
const AssetTemplatePlugin = require('./config/asset-template-plugin');

function readJson (filename) {
return JSON.parse(fs.readFileSync(filename));
Expand Down Expand Up @@ -238,8 +239,11 @@ module.exports = function (_, env) {
compile: true
}),

new AutoSWPlugin({
version: VERSION
new AutoSWPlugin({ version: VERSION }),

isProd && new AssetTemplatePlugin({
template: path.join(__dirname, '_headers.ejs'),
filename: '_headers',
}),

new ScriptExtHtmlPlugin({
Expand Down

0 comments on commit 6994cc3

Please sign in to comment.