Skip to content

Commit

Permalink
prefetching state for ssr
Browse files Browse the repository at this point in the history
  • Loading branch information
carloscorti committed Jan 23, 2021
1 parent 57493f4 commit 0a11483
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 48 deletions.
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -18,6 +18,7 @@
"axios": "0.21.1",
"bulma": "0.9.1",
"express": "4.17.1",
"serialize-javascript": "5.0.1",
"vue": "2.6.12",
"vue-router": "3.4.9",
"vue-server-renderer": "2.6.12",
Expand Down
16 changes: 14 additions & 2 deletions server.js
@@ -1,6 +1,7 @@
const express = require('express');
const path = require('path');
const fs = require('fs');
const serialize = require('serialize-javascript');

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

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

renderer.renderToString({ url: req.url }, (err, html) => {
const context = { url: req.url };

renderer.renderToString(context, (err, html) => {
if (err) {
console.log(err);
return res.status(500).send('server error');
}

const ssrIndexHTML = indexHTML.replace('{{APP}}', html);
let ssrIndexHTML = indexHTML.replace('{{APP}}', html);
ssrIndexHTML = ssrIndexHTML.replace(
'{{STATE}}',
`<script type="text/javascript">window.__INITIAL_STATE__=${serialize(
context.state,
{
isJSON: true
}
)}</script>`
);

res.write(ssrIndexHTML);
res.end();
Expand Down
49 changes: 39 additions & 10 deletions src/app.js
@@ -1,18 +1,47 @@
import Vue from 'vue';
import AppLayout from './theme/AppLayout.vue';
import router from './router';
import store from './vuex-state';
// import router from './router';
import { createRouter } from './router';
// import store from './vuex-state';
import { createStore } from './vuex-state';
import './styles/index.scss';

// Vue.config.productionTip = false;

Vue.config.devtools = true;
if (typeof window !== 'undefined') {
Vue.config.devtools = true;
}

const app = new Vue({
store,
router,
// render: (h) => h(AppLayout),
...AppLayout
});
// const app = new Vue({
// store,
// router,
// // render: (h) => h(AppLayout),
// ...AppLayout
// });

export { app, router, store };
// export { app, router, store };

const createApp = () => {
const router = createRouter();

const store = createStore();

const app = new Vue({
store,
router,
// render: (h) => h(AppLayout),
...AppLayout
});
return { app, router, store };
};

// export function createApp() {
// const app = new Vue({
// store,
// router,
// // render: (h) => h(AppLayout),
// ...AppLayout
// });
// return { app, router, store };
// }
export { createApp };
18 changes: 16 additions & 2 deletions src/client-entry.js
@@ -1,5 +1,19 @@
import { app, router } from './app';
// import { app, router, store } from './app';
import { createApp } from './app';

const { app, router, store } = createApp();

if (window.__INITIAL_STATE__) {
// We initialize the store state with the data injected from the server
// console.log(store);
// store.replaceState(window.__INITIAL_STATE__);
store.replaceState(window.__INITIAL_STATE__);

delete window.__INITIAL_STATE__;

console.log(store);
}

router.onReady(() => {
app.$mount('#app');
app.$mount('#app', true);
});
2 changes: 1 addition & 1 deletion src/network/index.js
Expand Up @@ -23,7 +23,7 @@ const getPosts = async categoryId => {
return [
{
id: 0,
title: { rendered: 'Opps, too busy rigth now' },
title: { rendered: 'Opps, too busy rigth now from getPosts' },
content: { rendered: 'Please try leater' },
rest_api_enabler: { Link: '/#' }
}
Expand Down
32 changes: 22 additions & 10 deletions src/router/index.js
Expand Up @@ -44,13 +44,25 @@ const routes = [
}
];

const router = new VueRouter({
mode: 'history',
// linkExactActiveClass: 'is-active',
linkActiveClass: 'is-active',
scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
// base: process.env.BASE_URL,
routes
});

export default router;
// const router = new VueRouter({
// mode: 'history',
// // linkExactActiveClass: 'is-active',
// linkActiveClass: 'is-active',
// scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
// // base: process.env.BASE_URL,
// routes
// });

// export default router;

const createRouter = () =>
new VueRouter({
mode: 'history',
// linkExactActiveClass: 'is-active',
linkActiveClass: 'is-active',
scrollBehavior: (to, from, savedPosition) => ({ y: 0 }),
// base: process.env.BASE_URL,
routes
});

export { createRouter };
53 changes: 42 additions & 11 deletions src/server-entry.js
@@ -1,21 +1,52 @@
import { app, router, store } from './app';
// import { app, router, store } from './app';

// export default context => {
// console.log(context);
// router.push(context.url);
// return new Promise((resolve, reject) => {
// // set server-side router's location

// // wait until router has resolved possible async components and hooks
// router.onReady(() => {
// const matchedComponents = router.getMatchedComponents();
// // console.log(matchedComponents);
// // no matched routes, reject with 404
// if (!matchedComponents.length) {
// return reject({ code: 404 });
// }

// matchedComponents.map(component => {
// if (component.asyncData) {
// return component.asyncData(store, router.currentRoute).then(() => {
// context.initialState = store.state;
// console.log(context.initialState.postsModule.posts);
// resolve(app);
// });
// }
// resolve(app);
// });

// // the Promise should resolve to the app instance so it can be rendered
// }, reject);
// });
// // return app;
// };

import { createApp } from './app';

export default context => {
router.push(context.url);
const { app, router, store } = createApp();
// console.log(context);
return new Promise((resolve, reject) => {
// set server-side router's location
router.push(context.url);

// wait until router has resolved possible async components and hooks
router.onReady(() => {
const matchedComponents = router.getMatchedComponents();
// no matched routes, reject with 404
if (!matchedComponents.length) {
return reject({ code: 404 });
}
context.rendered = () => {
context.state = store.state;
console.log(context.state);
};

// the Promise should resolve to the app instance so it can be rendered
resolve(app);
}, reject);
});
// return app;
};
8 changes: 8 additions & 0 deletions src/theme/PostList.vue
Expand Up @@ -36,6 +36,13 @@ import { mapGetters, mapActions } from 'vuex';
export default {
name: 'PostList',
// async asyncData(store, route) {
// // console.log(route.params.id);
// return await store.dispatch('postsModule/fetchPosts', route.params.id);
// },
async serverPrefetch() {
await this.fetchPosts(this.id);
},
components: {
'post-card': PostCard
},
Expand All @@ -53,6 +60,7 @@ export default {
},
async created() {
// console.log('from postList created');
await this.fetchPosts(this.id);
// console.log(this.profile);
},
Expand Down
32 changes: 22 additions & 10 deletions src/vuex-state/index.js
Expand Up @@ -8,21 +8,33 @@ import postsModule from './modules/posts';

Vue.use(Vuex);

const state = {
const state = () => ({
isAuthenticated: false,
profile: {}
};
});

const getters = {
isAuthenticated: state => state.isAuthenticated,
profile: state => state.profile
};

export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
modules: { postsModule },
state,
mutations,
actions,
getters
});
// export default new Vuex.Store({
// strict: process.env.NODE_ENV !== 'production',
// modules: { postsModule },
// state,
// mutations,
// actions,
// getters
// });

const createStore = () =>
new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
modules: { postsModule },
state,
mutations,
actions,
getters
});

export { createStore };
1 change: 0 additions & 1 deletion src/vuex-state/modules/posts/actions.js
Expand Up @@ -22,7 +22,6 @@ const actions = {
break;
default:
postsUpdate = errorPost;
return;
}
commit(types.GET_POSTS, postsUpdate);
}
Expand Down
1 change: 1 addition & 0 deletions template/index.html
Expand Up @@ -5,6 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
{{STATE}}
</head>

<body>
Expand Down

0 comments on commit 0a11483

Please sign in to comment.