Skip to content

Commit c22bfbd

Browse files
montogeekskipjack
authored andcommitted
chore(rebuild): populate page titles (#2040)
Utilize new `content-utils` to populate the `title` for static rendering as well as during client-side SPA rendering and routing.
1 parent 1bb7852 commit c22bfbd

File tree

5 files changed

+40
-5
lines changed

5 files changed

+40
-5
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
"prop-types": "^15.5.10",
112112
"react": "^16.2.0",
113113
"react-banner": "^1.0.0-rc.0",
114+
"react-document-title": "^2.0.3",
114115
"react-dom": "^16.2.0",
115116
"react-hot-loader": "^4.0.0-beta.12",
116117
"react-router": "^4.2.0",

src/components/Site/Site.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import React from 'react';
33
import { Switch, Route } from 'react-router-dom';
44
import { hot as Hot } from 'react-hot-loader';
5+
import DocumentTitle from 'react-document-title';
56

67
// Import Utilities
7-
import { ExtractPages, ExtractSections } from '../../utilities/content-utils';
8+
import { ExtractPages, ExtractSections, GetPageTitle } from '../../utilities/content-utils';
89

910
// Import Components
1011
import NotificationBar from '../NotificationBar/NotificationBar';
@@ -40,6 +41,8 @@ class Site extends React.Component {
4041

4142
return (
4243
<div className="site">
44+
<DocumentTitle title={ GetPageTitle(Content, location.pathname) } />
45+
4346
<NotificationBar />
4447

4548
<Navigation

src/server.jsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ import React from 'react';
33
import ReactDOMServer from 'react-dom/server';
44
import { StaticRouter, Route } from 'react-router-dom';
55

6+
// Import Utilities
7+
import { GetPageTitle } from './utilities/content-utils';
8+
69
// Import Components
710
import Site from './components/Site/Site';
811

912
// Import Images
1013
import Favicon from './favicon.ico';
1114

15+
// Import Content Tree
16+
import Content from './_content.json';
17+
1218
// Define bundles (previously used `Object.values(locals.assets)`) but
1319
// can't retrieve from there anymore due to separate compilation.
1420
const bundles = [
@@ -19,15 +25,16 @@ const bundles = [
1925
// Export method for `SSGPlugin`
2026
export default locals => {
2127
let { assets } = locals.webpackStats.compilation;
28+
let title = GetPageTitle(Content, locals.path)
2229

2330
return ReactDOMServer.renderToString(
24-
<StaticRouter location={ locals.path } context={{}}>
31+
<StaticRouter location={locals.path} context={{}}>
2532
<html>
2633
<head>
27-
<meta charSet="UTF-8" />
34+
<meta charset="utf-8" />
2835
<meta name="theme-color" content="#2B3A42" />
2936
<meta name="viewport" content="width=device-width, initial-scale=1" />
30-
<title>{/* TODO */} | webpack</title>
37+
<title>{title}</title>
3138
<meta name="description" content="webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset." />
3239
<link rel="icon" type="image/x-icon" href={ Favicon } />
3340
{ Object.keys(assets).filter(asset => /\.css$/.test(asset)).map(path => (

src/utilities/content-utils.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,27 @@ export const ExtractSections = tree => {
6363
export const ExtractPages = tree => {
6464
return FlattenContent(tree).filter(item => item.extension === '.md');
6565
};
66+
67+
/**
68+
* Retrieve the page title from the given `tree` based on the given `path`
69+
*
70+
* @param {object} tree - Any node in the content tree
71+
* @param {string} path - The pathname (aka route) for which to find a title
72+
* @return {string} - The title specified by that page or a fallback
73+
*/
74+
export const GetPageTitle = (tree, path) => {
75+
let page = FindInContent(tree, item => item.url === path);
76+
let title;
77+
78+
if ( !page ) {
79+
if ( !path.endsWith('/') ) path += '/';
80+
title = path.replace(/.*\/(.+)\//g, '$1');
81+
title = title.replace(/-/g, ' ');
82+
83+
} else if ( path === '/' ) {
84+
title = page.title;
85+
86+
} else title =`${page.title} | webpack`;
87+
88+
return title;
89+
};

webpack.prod.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ module.exports = env => [
7777
plugins: [
7878
new webpack.optimize.CommonsChunkPlugin({
7979
name: 'vendor',
80-
chunks: [ 'index' ]
80+
chunks: ['index']
8181
})
8282
]
8383
})

0 commit comments

Comments
 (0)