Skip to content

Commit c3a6de3

Browse files
committed
separate server/client api creation and add sw-precache plugin
1 parent 06f72f5 commit c3a6de3

File tree

8 files changed

+349
-93
lines changed

8 files changed

+349
-93
lines changed

build/webpack.client.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ const base = require('./webpack.base.config')
33
const vueConfig = require('./vue-loader.config')
44

55
const config = Object.assign({}, base, {
6+
resolve: {
7+
alias: {
8+
'create-api': './create-api-client.js'
9+
}
10+
},
611
plugins: (base.plugins || []).concat([
712
// strip comments in Vue code
813
new webpack.DefinePlugin({
@@ -15,6 +20,7 @@ if (process.env.NODE_ENV === 'production') {
1520
// Use ExtractTextPlugin to extract CSS into a single file
1621
// so it's applied on initial render
1722
const ExtractTextPlugin = require('extract-text-webpack-plugin')
23+
const SWPrecachePlugin = require('sw-precache-webpack-plugin')
1824

1925
// vueConfig is already included in the config via LoaderOptionsPlugin
2026
// here we overwrite the loader config for <style lang="stylus">
@@ -37,6 +43,10 @@ if (process.env.NODE_ENV === 'production') {
3743
compress: {
3844
warnings: false
3945
}
46+
}),
47+
new SWPrecachePlugin({
48+
cacheId: 'vue-hn',
49+
filename: 'service-worker.js'
4050
})
4151
)
4252
}

build/webpack.server.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ module.exports = Object.assign({}, base, {
99
filename: 'server-bundle.js',
1010
libraryTarget: 'commonjs2'
1111
}),
12+
resolve: {
13+
alias: {
14+
'create-api': './create-api-server.js'
15+
}
16+
},
1217
externals: Object.keys(require('../package.json').dependencies),
1318
plugins: [
1419
new webpack.DefinePlugin({

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"lru-cache": "^4.0.1",
2323
"serialize-javascript": "^1.3.0",
2424
"serve-favicon": "^2.3.0",
25+
"sw-precache-webpack-plugin": "^0.5.1",
2526
"vue": "^2.0.0",
2627
"vue-router": "^2.0.0",
2728
"vue-server-renderer": "^2.0.0",

src/client-entry.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ store.replaceState(window.__INITIAL_STATE__)
77

88
// actually mount to DOM
99
app.$mount('#app')
10+
11+
// service worker
12+
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
13+
navigator.serviceWorker.register('/dist/service-worker.js')
14+
}

src/store/api.js

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,18 @@
1-
import Firebase from 'firebase'
2-
import LRU from 'lru-cache'
1+
// this is aliased in webpack config based on server/client build
2+
import api from 'create-api'
33

4-
const inBrowser = typeof window !== 'undefined'
5-
6-
// When using bundleRenderer, the server-side application code runs in a new
7-
// context for each request. To allow caching across multiple requests, we need
8-
// to attach the cache to the process which is shared across all requests.
9-
const cache = inBrowser
10-
? null
11-
: (process.__API_CACHE__ || (process.__API_CACHE__ = createCache()))
12-
13-
function createCache () {
14-
return LRU({
15-
max: 1000,
16-
maxAge: 1000 * 60 * 15 // 15 min cache
17-
})
18-
}
19-
20-
// create a single api instance for all server-side requests
21-
const api = inBrowser
22-
? new Firebase('https://hacker-news.firebaseio.com/v0')
23-
: (process.__API__ || (process.__API__ = createServerSideAPI()))
24-
25-
function createServerSideAPI () {
26-
const api = new Firebase('https://hacker-news.firebaseio.com/v0')
27-
28-
// cache the latest story ids
29-
api.__ids__ = {}
30-
;['top', 'new', 'show', 'ask', 'job'].forEach(type => {
31-
api.child(`${type}stories`).on('value', snapshot => {
32-
api.__ids__[type] = snapshot.val()
33-
})
34-
})
35-
36-
// warm the front page cache every 15 min
4+
// warm the front page cache every 15 min
5+
if (api.cachedIds) {
376
warmCache()
38-
function warmCache () {
39-
fetchItems((api.__ids__.top || []).slice(0, 30))
40-
setTimeout(warmCache, 1000 * 60 * 15)
41-
}
7+
}
428

43-
return api
9+
function warmCache () {
10+
fetchItems((api.cachedIds.top || []).slice(0, 30))
11+
setTimeout(warmCache, 1000 * 60 * 15)
4412
}
4513

4614
function fetch (child) {
15+
const cache = api.cachedItems
4716
if (cache && cache.has(child)) {
4817
return Promise.resolve(cache.get(child))
4918
} else {
@@ -60,8 +29,8 @@ function fetch (child) {
6029
}
6130

6231
export function fetchIdsByType (type) {
63-
return api.__ids__ && api.__ids__[type]
64-
? Promise.resolve(api.__ids__[type])
32+
return api.cachedIds && api.cachedIds[type]
33+
? Promise.resolve(api.cachedIds[type])
6534
: fetch(`${type}stories`)
6635
}
6736

src/store/create-api-client.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Firebase from 'firebase'
2+
3+
export default new Firebase('https://hacker-news.firebaseio.com/v0')

src/store/create-api-server.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Firebase from 'firebase'
2+
import LRU from 'lru-cache'
3+
4+
let api
5+
6+
if (process.__API__) {
7+
api = process.__API__
8+
} else {
9+
api = process.__API__ = new Firebase('https://hacker-news.firebaseio.com/v0')
10+
11+
// fetched item cache
12+
api.cachedItems = LRU({
13+
max: 1000,
14+
maxAge: 1000 * 60 * 15 // 15 min cache
15+
})
16+
17+
// cache the latest story ids
18+
api.cachedIds = {}
19+
;['top', 'new', 'show', 'ask', 'job'].forEach(type => {
20+
api.child(`${type}stories`).on('value', snapshot => {
21+
api.cachedIds[type] = snapshot.val()
22+
})
23+
})
24+
}
25+
26+
export default api

0 commit comments

Comments
 (0)