Skip to content

Commit 0a11483

Browse files
committed
prefetching state for ssr
1 parent 57493f4 commit 0a11483

File tree

12 files changed

+166
-48
lines changed

12 files changed

+166
-48
lines changed

package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"axios": "0.21.1",
1919
"bulma": "0.9.1",
2020
"express": "4.17.1",
21+
"serialize-javascript": "5.0.1",
2122
"vue": "2.6.12",
2223
"vue-router": "3.4.9",
2324
"vue-server-renderer": "2.6.12",

server.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const express = require('express');
22
const path = require('path');
33
const fs = require('fs');
4+
const serialize = require('serialize-javascript');
45

56
const { createBundleRenderer } = require('vue-server-renderer');
67

@@ -30,13 +31,24 @@ if (process.env.NODE_ENV === 'development') {
3031
app.get('/*', (req, res) => {
3132
const renderer = createBundleRenderer(appBundle);
3233

33-
renderer.renderToString({ url: req.url }, (err, html) => {
34+
const context = { url: req.url };
35+
36+
renderer.renderToString(context, (err, html) => {
3437
if (err) {
3538
console.log(err);
3639
return res.status(500).send('server error');
3740
}
3841

39-
const ssrIndexHTML = indexHTML.replace('{{APP}}', html);
42+
let ssrIndexHTML = indexHTML.replace('{{APP}}', html);
43+
ssrIndexHTML = ssrIndexHTML.replace(
44+
'{{STATE}}',
45+
`<script type="text/javascript">window.__INITIAL_STATE__=${serialize(
46+
context.state,
47+
{
48+
isJSON: true
49+
}
50+
)}</script>`
51+
);
4052

4153
res.write(ssrIndexHTML);
4254
res.end();

src/app.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,47 @@
11
import Vue from 'vue';
22
import AppLayout from './theme/AppLayout.vue';
3-
import router from './router';
4-
import store from './vuex-state';
3+
// import router from './router';
4+
import { createRouter } from './router';
5+
// import store from './vuex-state';
6+
import { createStore } from './vuex-state';
57
import './styles/index.scss';
68

79
// Vue.config.productionTip = false;
810

9-
Vue.config.devtools = true;
11+
if (typeof window !== 'undefined') {
12+
Vue.config.devtools = true;
13+
}
1014

11-
const app = new Vue({
12-
store,
13-
router,
14-
// render: (h) => h(AppLayout),
15-
...AppLayout
16-
});
15+
// const app = new Vue({
16+
// store,
17+
// router,
18+
// // render: (h) => h(AppLayout),
19+
// ...AppLayout
20+
// });
1721

18-
export { app, router, store };
22+
// export { app, router, store };
23+
24+
const createApp = () => {
25+
const router = createRouter();
26+
27+
const store = createStore();
28+
29+
const app = new Vue({
30+
store,
31+
router,
32+
// render: (h) => h(AppLayout),
33+
...AppLayout
34+
});
35+
return { app, router, store };
36+
};
37+
38+
// export function createApp() {
39+
// const app = new Vue({
40+
// store,
41+
// router,
42+
// // render: (h) => h(AppLayout),
43+
// ...AppLayout
44+
// });
45+
// return { app, router, store };
46+
// }
47+
export { createApp };

src/client-entry.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
import { app, router } from './app';
1+
// import { app, router, store } from './app';
2+
import { createApp } from './app';
3+
4+
const { app, router, store } = createApp();
5+
6+
if (window.__INITIAL_STATE__) {
7+
// We initialize the store state with the data injected from the server
8+
// console.log(store);
9+
// store.replaceState(window.__INITIAL_STATE__);
10+
store.replaceState(window.__INITIAL_STATE__);
11+
12+
delete window.__INITIAL_STATE__;
13+
14+
console.log(store);
15+
}
216

317
router.onReady(() => {
4-
app.$mount('#app');
18+
app.$mount('#app', true);
519
});

src/network/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const getPosts = async categoryId => {
2323
return [
2424
{
2525
id: 0,
26-
title: { rendered: 'Opps, too busy rigth now' },
26+
title: { rendered: 'Opps, too busy rigth now from getPosts' },
2727
content: { rendered: 'Please try leater' },
2828
rest_api_enabler: { Link: '/#' }
2929
}

src/router/index.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,25 @@ const routes = [
4444
}
4545
];
4646

47-
const router = new VueRouter({
48-
mode: 'history',
49-
// linkExactActiveClass: 'is-active',
50-
linkActiveClass: 'is-active',
51-
scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
52-
// base: process.env.BASE_URL,
53-
routes
54-
});
55-
56-
export default router;
47+
// const router = new VueRouter({
48+
// mode: 'history',
49+
// // linkExactActiveClass: 'is-active',
50+
// linkActiveClass: 'is-active',
51+
// scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
52+
// // base: process.env.BASE_URL,
53+
// routes
54+
// });
55+
56+
// export default router;
57+
58+
const createRouter = () =>
59+
new VueRouter({
60+
mode: 'history',
61+
// linkExactActiveClass: 'is-active',
62+
linkActiveClass: 'is-active',
63+
scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
64+
// base: process.env.BASE_URL,
65+
routes
66+
});
67+
68+
export { createRouter };

src/server-entry.js

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,52 @@
1-
import { app, router, store } from './app';
1+
// import { app, router, store } from './app';
2+
3+
// export default context => {
4+
// console.log(context);
5+
// router.push(context.url);
6+
// return new Promise((resolve, reject) => {
7+
// // set server-side router's location
8+
9+
// // wait until router has resolved possible async components and hooks
10+
// router.onReady(() => {
11+
// const matchedComponents = router.getMatchedComponents();
12+
// // console.log(matchedComponents);
13+
// // no matched routes, reject with 404
14+
// if (!matchedComponents.length) {
15+
// return reject({ code: 404 });
16+
// }
17+
18+
// matchedComponents.map(component => {
19+
// if (component.asyncData) {
20+
// return component.asyncData(store, router.currentRoute).then(() => {
21+
// context.initialState = store.state;
22+
// console.log(context.initialState.postsModule.posts);
23+
// resolve(app);
24+
// });
25+
// }
26+
// resolve(app);
27+
// });
28+
29+
// // the Promise should resolve to the app instance so it can be rendered
30+
// }, reject);
31+
// });
32+
// // return app;
33+
// };
34+
35+
import { createApp } from './app';
236

337
export default context => {
4-
router.push(context.url);
38+
const { app, router, store } = createApp();
39+
// console.log(context);
540
return new Promise((resolve, reject) => {
6-
// set server-side router's location
41+
router.push(context.url);
742

8-
// wait until router has resolved possible async components and hooks
943
router.onReady(() => {
10-
const matchedComponents = router.getMatchedComponents();
11-
// no matched routes, reject with 404
12-
if (!matchedComponents.length) {
13-
return reject({ code: 404 });
14-
}
44+
context.rendered = () => {
45+
context.state = store.state;
46+
console.log(context.state);
47+
};
1548

16-
// the Promise should resolve to the app instance so it can be rendered
1749
resolve(app);
1850
}, reject);
1951
});
20-
// return app;
2152
};

src/theme/PostList.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ import { mapGetters, mapActions } from 'vuex';
3636
3737
export default {
3838
name: 'PostList',
39+
// async asyncData(store, route) {
40+
// // console.log(route.params.id);
41+
// return await store.dispatch('postsModule/fetchPosts', route.params.id);
42+
// },
43+
async serverPrefetch() {
44+
await this.fetchPosts(this.id);
45+
},
3946
components: {
4047
'post-card': PostCard
4148
},
@@ -53,6 +60,7 @@ export default {
5360
},
5461
5562
async created() {
63+
// console.log('from postList created');
5664
await this.fetchPosts(this.id);
5765
// console.log(this.profile);
5866
},

src/vuex-state/index.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,33 @@ import postsModule from './modules/posts';
88

99
Vue.use(Vuex);
1010

11-
const state = {
11+
const state = () => ({
1212
isAuthenticated: false,
1313
profile: {}
14-
};
14+
});
1515

1616
const getters = {
1717
isAuthenticated: state => state.isAuthenticated,
1818
profile: state => state.profile
1919
};
2020

21-
export default new Vuex.Store({
22-
strict: process.env.NODE_ENV !== 'production',
23-
modules: { postsModule },
24-
state,
25-
mutations,
26-
actions,
27-
getters
28-
});
21+
// export default new Vuex.Store({
22+
// strict: process.env.NODE_ENV !== 'production',
23+
// modules: { postsModule },
24+
// state,
25+
// mutations,
26+
// actions,
27+
// getters
28+
// });
29+
30+
const createStore = () =>
31+
new Vuex.Store({
32+
strict: process.env.NODE_ENV !== 'production',
33+
modules: { postsModule },
34+
state,
35+
mutations,
36+
actions,
37+
getters
38+
});
39+
40+
export { createStore };

src/vuex-state/modules/posts/actions.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const actions = {
2222
break;
2323
default:
2424
postsUpdate = errorPost;
25-
return;
2625
}
2726
commit(types.GET_POSTS, postsUpdate);
2827
}

template/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<title>Document</title>
8+
{{STATE}}
89
</head>
910

1011
<body>

0 commit comments

Comments
 (0)