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

Added multiroute prerendering #192

Merged
merged 4 commits into from
Jul 5, 2017
Merged
Show file tree
Hide file tree
Changes from 3 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: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ $ preact build
--less, -l Build and compile LESS files [default: false]
--sass, -s Build and compile SASS files [default: false]
--prerender Pre-render static app content. [default: true]
--prerenderUrls Path to pre-render routes configuration. [default "prerender-urls.json"]
--clean Clear output directory before building. [default: true]
--json Generate build statistics for analysis. [default: false]
--config, -c Path to custom CLI config.
Expand Down Expand Up @@ -142,6 +143,25 @@ export default function (config, env, helpers) {
```
See [WebpackConfigHelpers] docs for more info on ```helpers``` argument.

#### Prerender multiple routes

The `--prerender` flag will prerender by default only the root of your application.
If you want to prerender other routes you can create a `prerender-urls.json` file, which contains the set of routes you want to render.
The format required for defining your routes is an array of objects with a `url` key and an optional `title` key.
```js
// prerender-urls.json
[{
"url": "/",
"title": "Homepage"
}, {
"url": "/route/random"
}]
```

You can customise the path of `prerender-urls.json` by using the flag `--prerenderUrls`.
```
preact build --prerenderUrls src/prerender-urls.json
```

[preact]: https://github.com/developit/preact
[preact-router]: https://github.com/developit/preact-router
Expand Down
4 changes: 4 additions & 0 deletions src/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export default asyncCommand({
description: 'Pre-render static app content.',
default: true
},
prerenderUrls: {
description: 'Path to pre-render routes configuration.',
default: 'prerender-urls.json'
},
clean: {
description: 'Clear output directory before building.',
default: true
Expand Down
2 changes: 1 addition & 1 deletion src/lib/webpack/webpack-base-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function exists(file) {
return false;
}

function readJson(file) {
export function readJson(file) {
if (file in readJson.cache) return readJson.cache[file];
let ret;
try { ret = JSON.parse(readFileSync(file)); }
Expand Down
31 changes: 18 additions & 13 deletions src/lib/webpack/webpack-client-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ScriptExtHtmlWebpackPlugin from 'script-ext-html-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import SWPrecacheWebpackPlugin from 'sw-precache-webpack-plugin';
import PushManifestPlugin from './push-manifest';
import baseConfig, { exists, helpers } from './webpack-base-config';
import baseConfig, { exists, readJson, helpers } from './webpack-base-config';
import prerender from './prerender';

export default env => {
Expand Down Expand Up @@ -164,9 +164,9 @@ const production = config => addPlugins([
})
]);

const htmlPlugin = (config, outputDir) => addPlugins([
new HtmlWebpackPlugin({
filename: 'index.html',
const htmlPlugin = (config, outputDir) => {
const htmlWebpackConfig = ({ url, title }) => ({
filename: resolve(outputDir, url.substring(1), 'index.html'),
template: `!!ejs-loader!${config.template || resolve(__dirname, '../../resources/template.html')}`,
minify: config.production && {
collapseWhitespace: true,
Expand All @@ -180,16 +180,21 @@ const htmlPlugin = (config, outputDir) => addPlugins([
inject: true,
compile: true,
preload: config.preload===true,
title: config.title || config.manifest.name || config.manifest.short_name || (config.pkg.name || '').replace(/^@[a-z]\//, '') || 'Preact App',
title: title || config.title || config.manifest.name || config.manifest.short_name || (config.pkg.name || '').replace(/^@[a-z]\//, '') || 'Preact App',
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
config,
ssr(params) {
return config.prerender ? prerender(outputDir, params) : '';
return config.prerender ? prerender(outputDir, { ...params, url }) : '';
}
}),
new HtmlWebpackExcludeAssetsPlugin(),
new ScriptExtHtmlWebpackPlugin({
// inline: 'bundle.js',
defaultAttribute: 'defer'
})
]);
});
const pages = readJson(resolve(config.cwd, config.prerenderUrls || '')) || [{ url: "/" }];
return addPlugins(pages
.map((page) => new HtmlWebpackPlugin(htmlWebpackConfig(page)))
.concat([
new HtmlWebpackExcludeAssetsPlugin(),
new ScriptExtHtmlWebpackPlugin({
// inline: 'bundle.js',
defaultAttribute: 'defer'
})
]));
};
20 changes: 20 additions & 0 deletions tests/build.snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,23 @@ export const withCustomTemplate = `
</body>
</html>
`;

export const multiplePrerenderingHome = `
<body>
<div id="app">
<div>Home</div>
</div>
<script defer="defer" src="/bundle.js"></script>
{{ ... }}
</body>
`;

export const multiplePrerenderingRoute = `
<body>
<div id="app">
<div>Route66</div>
</div>
<script defer="defer" src="/bundle.js"></script>
{{ ... }}
</body>
`;
14 changes: 13 additions & 1 deletion tests/build.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import htmlLooksLike from 'html-looks-like';
import { create, build } from './lib/cli';
import lsr from './lib/lsr';
import { setup, fromSubject } from './lib/output';
import expectedOutputs, { sassPrerendered, withCustomTemplate } from './build.snapshot';
import expectedOutputs, { sassPrerendered, withCustomTemplate, multiplePrerenderingHome, multiplePrerenderingRoute } from './build.snapshot';
import filesMatchSnapshot from './lib/filesMatchSnapshot';

describe('preact build', () => {
Expand Down Expand Up @@ -40,6 +40,18 @@ describe('preact build', () => {
expect(async () => await build(app)).not;
});

it(`should prerender the routes provided with prerenderUrls.`, async () => {
let app = await fromSubject('multiple-prerendering');
await build(app);

let output = await fs.readFile(resolve(app, './build/index.html'), 'utf-8');
let html = output.match(/<body>.*<\/body>/)[0];
htmlLooksLike(html, multiplePrerenderingHome);
output = await fs.readFile(resolve(app, './build/route66/index.html'), 'utf-8');
html = output.match(/<body>.*<\/body>/)[0];
htmlLooksLike(html, multiplePrerenderingRoute);
});

it(`should use custom preact.config.js.`, async () => {
// app with custom template set via preact.config.js
let app = await fromSubject('custom-webpack');
Expand Down
23 changes: 23 additions & 0 deletions tests/subjects/multiple-prerendering/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { h, Component } from 'preact';
import { Router } from 'preact-router';

const Home = () => <div>Home</div>;

const Route66 = () => <div>Route66</div>;

export default class App extends Component {
handleRoute = e => {
this.currentUrl = e.url;
};

render() {
return (
<div id="app">
<Router onChange={this.handleRoute}>
<Home path="/" />
<Route66 path="/route66" />
</Router>
</div>
);
}
}
16 changes: 16 additions & 0 deletions tests/subjects/multiple-prerendering/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "preact-app",
"version": "0.0.1",
"private": true,
"dependencies": {
"preact": "latest",
"preact-compat": "latest",
"preact-router": "latest"
},
"devDependencies": {
"eslint": "^4.1.1",
"eslint-config-synacor": "^1.0.1",
"if-env": "^1.0.0",
"preact-cli": "file:../../../"
}
}
1 change: 1 addition & 0 deletions tests/subjects/multiple-prerendering/prerender-urls.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{ "url": "/" }, { "url": "/route66", "title": "Route66"}]