Commit 392bc154 authored by Evan You's avatar Evan You

set maxAge and warm cache periodically

parent daae797e
......@@ -4,7 +4,7 @@ module.exports = {
devtool: '#source-map',
entry: {
app: './src/client-entry.js',
vendor: ['vue', 'vue-router', 'vuex', 'firebase', 'lru-cache']
vendor: ['vue', 'vue-router', 'vuex', 'firebase', 'lru-cache', 'es6-promise']
},
output: {
path: path.resolve(__dirname, '../dist'),
......
const base = require('./webpack.base.config')
const webpack = require('webpack')
const isProd = process.env.NODE_ENV === 'production'
const config = Object.assign({}, base, {
plugins: [
// strip comments in Vue code
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
// extract vendor chunks for better caching
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'client-vendor-bundle.js'
......@@ -14,7 +15,8 @@ const config = Object.assign({}, base, {
]
})
if (isProd) {
if (process.env.NODE_ENV === 'production') {
// extract CSS into a single file so it's applied on initial render
const ExtractTextPlugin = require('extract-text-webpack-plugin')
config.vue = {
......@@ -28,10 +30,11 @@ if (isProd) {
config.plugins.push(
new ExtractTextPlugin('styles.css'),
// this is needed in webpack 2 for minifying CSS
new webpack.LoaderOptionsPlugin({
minimize: true
}),
// minify
// minify JS
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
......
......@@ -10,9 +10,7 @@ const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
let renderer
function createRenderer (fs) {
const bundlePath = path.resolve(__dirname, 'dist/server-bundle.js')
return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'), {
cache: require('lru-cache')({ max: 1000 })
})
return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'))
}
const app = express()
......
......@@ -5,7 +5,6 @@
<script>
export default {
name: 'NewsItem',
props: ['item'],
serverCacheKey: ({ item }) => `${item.id}:${item.score}:${item.descendents}`
props: ['item']
}
</script>
......@@ -7,20 +7,36 @@ const inBrowser = typeof window !== 'undefined'
// context for each request. To allow caching across multiple requests, we need
// to attach the cache to the process which is shared across all requests.
const cache = inBrowser
? null
: (process.__API_CACHE__ || (process.__API_CACHE__ = LRU({ max: 1000 })))
? createCache()
: (process.__API_CACHE__ || (process.__API_CACHE__ = createCache()))
function createCache () {
return LRU({
max: 1000,
maxAge: 1000 * 60 * 15 // 15 min cache
})
}
// create a single api instance for all server-side requests
// and cache the latest top Ids on it.
const api = inBrowser
? new Firebase('https://hacker-news.firebaseio.com/v0')
: (process.__API__ || (process.__API__ = createServerSideAPI()))
function createServerSideAPI () {
const api = new Firebase('https://hacker-news.firebaseio.com/v0')
// cache the latest top stories' ids
api.child(`topstories`).on('value', snapshot => {
api.__topIds__ = snapshot.val()
})
// warm the cache every 15 min, since the front page changes quite often
warmCache()
function warmCache () {
fetchItems((api.__topIds__ || []).slice(0, 30))
setTimeout(warmCache, 1000 * 60 * 15)
}
return api
}
......@@ -47,11 +63,11 @@ export function watchTopIds (cb) {
}
export function fetchItem (id, forceRefresh) {
if (!forceRefresh && cache && cache.has(id)) {
if (!forceRefresh && cache.has(id)) {
return Promise.resolve(cache.get(id))
} else {
return fetch(`item/${id}`).then(item => {
cache && cache.set(id, item)
cache.set(id, item)
return item
})
}
......
......@@ -23,7 +23,7 @@ const store = new Vuex.Store({
})
},
FETCH_NEWS: ({ commit, state }) => {
const ids = getDisplayedIds(state).filter(id => !state.items[id])
const ids = getDisplayedIds(state)
return fetchItems(ids).then(items => {
commit('RECEIVE_ITEMS', { items })
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment