Skip to content

Instantly share code, notes, and snippets.

@prasanthmj
Last active August 12, 2019 11:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prasanthmj/7b2e27a2e9236b161726af3c367255a6 to your computer and use it in GitHub Desktop.
Save prasanthmj/7b2e27a2e9236b161726af3c367255a6 to your computer and use it in GitHub Desktop.
Simple Vue SSR without Vuex and Router.
import Vue from 'vue';
import { createApp } from './main.js';
const app = createApp();
app.$mount('#app');
import {createApp } from './main.js';
const isDev = process.env.NODE_ENV !== 'production'
// This exported function will be called by `bundleRenderer`.
// This is where we perform data-prefetching to determine the
// state of our application before actually rendering it.
// Since data fetching is async, this function is expected to
// return a Promise that resolves to the app instance.
export default (context) =>
{
return new Promise((resolve, reject) =>
{
const app = createApp();
// After all preFetch hooks are resolved, our store is now
// filled with the state needed to render the app.
// Expose the state on the render context, and let the request handler
// inline the state in the HTML response. This allows the client-side
// store to pick-up the server-side state without having to duplicate
// the initial data fetching on the client.
context.state = {}; //store.state
resolve(app);
});
}
import Vue from 'vue';
import App from './App.vue';
//Create the vue instance
export function createApp ()
{
const app = new Vue({
render: h => h(App)
});
return app;
}
{
"name": "simple_vue_templ",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"build": "yarn build:client && yarn build:server",
"build:client": "cross-env NODE_ENV=production node_modules/.bin/webpack --config ./build/webpack.client.config.js --progress --hide-modules",
"build:server": "cross-env NODE_ENV=production node_modules/.bin/webpack --config ./build/webpack.server.config.js --progress --hide-modules"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"cross-env": "^5.2.0",
"debug": "~2.6.9",
"dotenv": "^8.0.0",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"morgan": "~1.9.1",
"pg": "^7.12.0",
"pg-hstore": "^2.3.3",
"sequelize": "^5.13.0",
"sequelize-cli": "^5.5.0",
"vue": "^2.6.10",
"vue-server-renderer": "^2.6.10"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
"babel-preset-env": "^1.7.0",
"css-loader": "^3.2.0",
"node-sass": "^4.12.0",
"vue-loader": "^15.7.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.39.1",
"webpack-cli": "^3.3.6",
"webpack-merge": "^4.2.1",
"webpack-node-externals": "^1.7.2"
}
}
const Vue = require('vue');
var express = require('express');
const fs = require('fs');
const path = require('path');
const resolve = file => path.resolve(__dirname, file)
var router = express.Router();
const { createBundleRenderer } = require('vue-server-renderer');
function createRenderer (bundle, options)
{
const template = fs.readFileSync(resolve('../src/index.template.html'), 'utf-8')
// https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
return createBundleRenderer(bundle, Object.assign(options, {
template,
// this is only needed when vue-server-renderer is npm-linked
basedir: resolve('../dist')
}))
}
router.get('/app', function(req, res, next)
{
const bundle = require('../dist/vue-ssr-server-bundle.json');
const clientManifest = require('../dist/vue-ssr-client-manifest.json');
let renderer = createRenderer(bundle, { clientManifest});
const context = {
url: req.url
};
renderer.renderToString(context, (err, html) =>
{
if (err)
{
console.log("Error!", err);
res.status(500).end('500 | Internal Server Error');
}
res.end(html);
});
});
module.exports = router;
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const isProd = process.env.NODE_ENV === 'production';
module.exports = {
mode: 'production',
output:
{
path: path.resolve(__dirname, '../dist'),
publicPath: '/dist/',
filename: '[name].[chunkhash].js'
},
resolve:
{
extensions: ['.js', '.vue', '.json']
},
module:
{
rules:
[
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
},
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader']
}
]
},
plugins: [
// make sure to include the plugin!
new VueLoaderPlugin()
]
}
const merge = require('webpack-merge');
const base = require('./webpack.base.config');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
const config = merge(base,
{
entry:
{
app: './src/entry-client.js'
},
plugins:
[
new VueSSRClientPlugin()
]
});
module.exports = config;
const merge = require('webpack-merge');
const base = require('./webpack.base.config');
const nodeExternals = require('webpack-node-externals');
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
module.exports = merge(base, {
target: 'node',
devtool: '#source-map',
entry: './src/entry-server.js',
output: {
filename: 'server-bundle.js',
libraryTarget: 'commonjs2'
},
// https://webpack.js.org/configuration/externals/#externals
// https://github.com/liady/webpack-node-externals
externals: nodeExternals({
// do not externalize CSS files in case we need to import it from a dep
whitelist: /\.css$/
}),
plugins: [
new VueSSRServerPlugin()
]
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment