Skip to content

Commit 2ef88be

Browse files
authored
Update build/deps/improve perf (#66)
* Add babelrc presets * Ignore build artifacts generated by nwb * Bump all dependencies & wire appropriately. There are workarounds here for web app manifests no longer being copied over to the right location now that dist is canonical output dir. * Drop vendor/app writing - handle this in Webpack now * sw-precache: work against the dist dir now * server: update to latest babel register, dist * Mixins: fix a new linting issue * Update routing to work with latest dependencies * App.js: fix a new linting issue * HNServiceRest: fix a new linting issue * Switch to route-based chunking 🔥 We also polyfill require.ensure() so this continues to work on the server fine. * Shave 60KB off size. Switch to new Firebase && only use what we need. We’re only using database so we can drop storage and authentication use that’s included by default in the mega bundle Firebase make available to folks. * Webpack: hookup CommonsChunkPlugin & HtmlWebpackPlugin - Needed for writing up final chunks to our EJS template & static HTML - Commons chunks necessary for ensuring runtime pieces common to each chunk are included in the right places. * Fix router history implementation
1 parent 9b469d4 commit 2ef88be

File tree

14 files changed

+131
-68
lines changed

14 files changed

+131
-68
lines changed

.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["es2015", "stage-0", "react"]
3+
}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/public/build
22
/node_modules
3-
/public/sw-toolbox.js
3+
/public/sw-toolbox.js
4+
dist

nwb.config.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,38 @@
1+
var HtmlWebpackPlugin = require('html-webpack-plugin')
2+
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
3+
14
module.exports = {
25
type: 'react-app',
36
babel: {
4-
loose: 'all'
7+
loose: true,
8+
stage: false,
9+
presets: ['es2015', 'stage-0', 'react']
510
},
611
webpack: {
12+
loaders: {
13+
babel: {
14+
babelrc: true,
15+
cacheDirectory: true
16+
}
17+
},
718
plugins: {
819
define: {
920
__VERSION__: JSON.stringify(require('./package.json').version)
1021
}
11-
}
22+
},
23+
extra: {
24+
plugins: [
25+
new CommonsChunkPlugin({
26+
names: ['core'],
27+
filename: '[name].js',
28+
minChunks: Infinity
29+
}),
30+
new HtmlWebpackPlugin({
31+
filename: 'views/index.ejs',
32+
template: 'src/views/index.ejs',
33+
markup: '<div id="app"><%- markup %></div>'
34+
})
35+
]
36+
}
1237
}
13-
}
38+
}

package.json

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,49 @@
99
"url": "http://github.com/insin/react-hn.git"
1010
},
1111
"scripts": {
12-
"build": "npm run lint && cp node_modules/sw-toolbox/sw-toolbox.js public/sw-toolbox.js && ./node_modules/.bin/nwb build && npm run precache",
12+
"build": "npm run lint && cp node_modules/sw-toolbox/sw-toolbox.js dist/sw-toolbox.js && ./node_modules/.bin/nwb build && npm run copy-manifest && npm run precache",
1313
"deploy": "gcloud preview app deploy",
1414
"lint": "./node_modules/eslint-config-jonnybuchanan/bin/lint.js src",
1515
"lint:fix": "./node_modules/eslint-config-jonnybuchanan/bin/lint.js --fix .",
1616
"start": "node server.js",
1717
"postinstall": "npm run build",
1818
"serve": "./node_modules/.bin/nwb serve",
19-
"precache": "./node_modules/sw-precache/cli.js --root=public --config=sw-precache-config.json"
19+
"copy-manifest": "cp public/manifest.json dist/manifest.json",
20+
"clean": "rm -rf *.json.gzip dist/index.html",
21+
"precache": "./node_modules/sw-precache/cli.js --root=public --config=sw-precache-config.json && npm run clean"
2022
},
2123
"engines": {
2224
"node": "6.1.0"
2325
},
2426
"main": "server.js",
2527
"dependencies": {
28+
"babel-preset-es2015": "^6.16.0",
29+
"babel-preset-react": "^6.16.0",
30+
"babel-preset-stage-0": "^6.16.0",
31+
"babel-register": "^6.16.0",
2632
"ejs": "^2.4.1",
27-
"eslint-config-jonnybuchanan": "2.0.3",
28-
"events": "1.1.0",
33+
"eslint-config-jonnybuchanan": "4.6.0",
34+
"events": "1.1.1",
2935
"express": "^4.13.4",
30-
"firebase": "2.4.2",
31-
"history": "2.1.1",
36+
"firebase": "3.4.1",
37+
"history": "^2.1.2",
3238
"isomorphic-fetch": "^2.2.1",
33-
"nwb": "0.8.1",
39+
"nwb": "0.12.2",
3440
"object-assign": "^4.1.0",
35-
"react": "15.0.2",
36-
"react-dom": "15.0.2",
37-
"react-router": "2.4.0",
38-
"react-timeago": "3.0.0",
39-
"reactfire": "0.7.0",
40-
"scroll-behavior": "0.5.0",
41-
"setimmediate": "1.0.4",
42-
"sw-precache": "^3.1.1",
41+
"react": "15.3.2",
42+
"react-dom": "15.3.2",
43+
"react-router": "2.8.1",
44+
"react-router-scroll": "^0.3.2",
45+
"react-timeago": "3.1.3",
46+
"reactfire": "1.0.0",
47+
"scroll-behavior": "0.8.1",
48+
"setimmediate": "1.0.5",
49+
"sw-precache": "^4.1.0",
4350
"sw-toolbox": "^3.1.1",
4451
"url-parse": "^1.1.1"
52+
},
53+
"devDependencies": {
54+
"html-webpack-plugin": "^2.22.0",
55+
"webpack": "^1.13.2"
4556
}
4657
}

public/index-static.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
</head>
3535
<body>
3636
<div id="app"></div>
37-
<script src="build/vendor.js"></script>
38-
<script src="build/app.js"></script>
3937
<script>
4038
if ('serviceWorker' in navigator) {
4139
navigator.serviceWorker.register('./service-worker.js', {

server.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ var ReactRouter = require('react-router')
55
var objectAssign = require('object-assign')
66
var HNServerFetch = require('./hn-server-fetch')
77

8-
require('babel/register')
8+
require('babel-register')
99
var routes = require('./src/routes')
1010

1111
var app = express()
1212
app.set('view engine', 'ejs')
13-
app.set('views', process.cwd() + '/src/views')
13+
app.set('views', process.cwd() + '/dist/views')
1414
app.set('port', (process.env.PORT || 5000))
15-
app.use(express.static('public'))
15+
app.use(express.static('dist'))
1616

1717

1818
app.get(['/', '/news'], function(req, res) {

src/App.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,26 @@ var App = React.createClass({
5151
render() {
5252
return <div className="App" onClick={this.state.showSettings && this.toggleSettings}>
5353
<div className="App__wrap">
54-
<div className="App__header">
55-
<Link to="/news" className="App__homelinkicon"><img src="img/logo.png" width="16" height="16" alt="" /></Link>{' '}
56-
<Link to="/news" activeClassName="active" className="App__homelink">React HN</Link>{' '}
57-
<Link to="/newest" activeClassName="active">new</Link>{' | '}
58-
<Link to="/newcomments" activeClassName="active">comments</Link> {' | '}
59-
<Link to="/show" activeClassName="active">show</Link>{' | '}
60-
<Link to="/ask" activeClassName="active">ask</Link>{' | '}
61-
<Link to="/jobs" activeClassName="active">jobs</Link>
62-
<a className="App__settings" tabIndex="0" onClick={this.toggleSettings} onKeyPress={this.toggleSettings}>
63-
{this.state.showSettings ? 'hide settings' : 'settings'}
64-
</a>
65-
{this.state.showSettings && <Settings key="settings"/>}
66-
</div>
67-
<div className="App__content">
68-
<div dangerouslySetInnerHTML={{ __html: this.state.prebootHTML }}/>
69-
{this.state.showChildren ? this.props.children : ''}
70-
</div>
71-
<div className="App__footer">
72-
<a href="https://github.com/insin/react-hn">insin/react-hn</a>
73-
</div>
54+
<div className="App__header">
55+
<Link to="/news" className="App__homelinkicon"><img src="img/logo.png" width="16" height="16" alt="" /></Link>{' '}
56+
<Link to="/news" activeClassName="active" className="App__homelink">React HN</Link>{' '}
57+
<Link to="/newest" activeClassName="active">new</Link>{' | '}
58+
<Link to="/newcomments" activeClassName="active">comments</Link> {' | '}
59+
<Link to="/show" activeClassName="active">show</Link>{' | '}
60+
<Link to="/ask" activeClassName="active">ask</Link>{' | '}
61+
<Link to="/jobs" activeClassName="active">jobs</Link>
62+
<a className="App__settings" tabIndex="0" onClick={this.toggleSettings} onKeyPress={this.toggleSettings}>
63+
{this.state.showSettings ? 'hide settings' : 'settings'}
64+
</a>
65+
{this.state.showSettings && <Settings key="settings"/>}
66+
</div>
67+
<div className="App__content">
68+
<div dangerouslySetInnerHTML={{ __html: this.state.prebootHTML }}/>
69+
{this.state.showChildren ? this.props.children : ''}
70+
</div>
71+
<div className="App__footer">
72+
<a href="https://github.com/insin/react-hn">insin/react-hn</a>
73+
</div>
7474
</div>
7575
</div>
7676
}

src/index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
require('setimmediate')
22

3-
var createHashHistory = require('history/lib/createHashHistory')
43
var React = require('react')
54
var {render} = require('react-dom')
65
var Router = require('react-router/lib/Router')
7-
var useRouterHistory = require('react-router/lib/useRouterHistory')
8-
var withScroll = require('scroll-behavior/lib/withStandardScroll')
6+
var createHashHistory = require('history/lib/createHashHistory')
7+
var useScroll = require('react-router-scroll/lib/useScroll')
8+
var applyRouterMiddleware = require('react-router/lib/applyRouterMiddleware')
9+
var history = createHashHistory()
910

1011
var routes = require('./routes')
1112

12-
var history = withScroll(useRouterHistory(createHashHistory)())
13-
14-
render(<Router history={history} routes={routes}/>, document.getElementById('app'))
13+
render(<Router history={history} render={applyRouterMiddleware(useScroll())} routes={routes}/>, document.getElementById('app'))

src/mixins/CommentMixin.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ var CommentMixin = {
8686
{options.collapsible && ' '}
8787
[dead]
8888
{options.childCounts && ' | (' + options.childCounts.children + ' child' + pluralise(options.childCounts.children, ',ren')}
89-
{options.childCounts && options.childCounts.newComments > 0 && ', '}
90-
{options.childCounts && options.childCounts.newComments > 0 && <em>{options.childCounts.newComments} new</em>}
89+
{options.childCounts && options.childCounts.newComments > 0 && ', '}
90+
{options.childCounts && options.childCounts.newComments > 0 && <em>{options.childCounts.newComments} new</em>}
9191
{options.childCounts && ')'}
9292
</div>
9393
}
@@ -105,8 +105,8 @@ var CommentMixin = {
105105
{options.op && <Link to={`/${this.state.op.type}/${this.state.op.id}`}>{this.state.op.title}</Link>}
106106
{comment.dead && ' | [dead]'}
107107
{options.childCounts && ' | (' + options.childCounts.children + ' child' + pluralise(options.childCounts.children, ',ren')}
108-
{options.childCounts && options.childCounts.newComments > 0 && ', '}
109-
{options.childCounts && options.childCounts.newComments > 0 && <em>{options.childCounts.newComments} new</em>}
108+
{options.childCounts && options.childCounts.newComments > 0 && ', '}
109+
{options.childCounts && options.childCounts.newComments > 0 && <em>{options.childCounts.newComments} new</em>}
110110
{options.childCounts && ')'}
111111
</div>
112112
},

src/routes.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
var IndexRoute = require('react-router/lib/IndexRoute')
22
var React = require('react')
33
var Route = require('react-router/lib/Route')
4+
var Item = require('./Item')
5+
// Polyfill require.ensure
6+
if (typeof require.ensure !== 'function') require.ensure = function(d, c) { c(require) }
47

58
var App = require('./App')
6-
var Item = require('./Item')
7-
var NotFound = require('./NotFound')
8-
var PermalinkedComment = require('./PermalinkedComment')
99
var Stories = require('./Stories')
1010
var Updates = require('./Updates')
11-
var UserProfile = require('./UserProfile')
1211

1312
function stories(route, type, limit, title) {
1413
return React.createClass({
@@ -44,8 +43,29 @@ module.exports = <Route path="/" component={App}>
4443
<Route path="job/:id" component={Item}/>
4544
<Route path="poll/:id" component={Item}/>
4645
<Route path="story/:id" component={Item}/>
47-
<Route path="comment/:id" component={PermalinkedComment}/>
46+
<Route
47+
path="comment/:id"
48+
getComponent={(location, callback) => {
49+
require.ensure([], require => {
50+
callback(null, require('./PermalinkedComment'))
51+
}, 'PermalinkedComment')
52+
}}
53+
/>
4854
<Route path="newcomments" component={Comments}/>
49-
<Route path="user/:id" component={UserProfile}/>
50-
<Route path="*" component={NotFound}/>
55+
<Route
56+
path="user/:id"
57+
getComponent={(location, callback) => {
58+
require.ensure([], require => {
59+
callback(null, require('./UserProfile'))
60+
}, 'UserProfile')
61+
}}
62+
/>
63+
<Route
64+
path="*"
65+
getComponent={(location, callback) => {
66+
require.ensure([], require => {
67+
callback(null, require('./NotFound'))
68+
}, 'NotFound')
69+
}}
70+
/>
5171
</Route>

0 commit comments

Comments
 (0)