i see there is an unassigned var webpack.server.js
which is used in vue ssr at this link
ive havent have luck using on it coz even though everything is ok when i run yarn prod and yarn run:server
this gives me error as such
SyntaxError: Unexpected token :
at getCompiledScript (C:\Users\uriah\sites\www\vuetified-ssr\node_modules\vue-server-renderer\build.js:8122:18)
at evaluateModule (C:\Users\uriah\sites\www\vuetified-ssr\node_modules\vue-server-renderer\build.js:8137:18)
at C:\Users\uriah\sites\www\vuetified-ssr\node_modules\vue-server-renderer\build.js:8191:17
at Promise (<anonymous>)
at C:\Users\uriah\sites\www\vuetified-ssr\node_modules\vue-server-renderer\build.js:8189:14
at Object.renderToStream (C:\Users\uriah\sites\www\vuetified-ssr\node_modules\vue-server-renderer\build.js:8397:9)
at VueSSR.RenderToStream (C:\Users\uriah\sites\www\vuetified-ssr\render_server\vue-ssr\renderer.js:115:44)
at VueSSR.render (C:\Users\uriah\sites\www\vuetified-ssr\render_server\vue-ssr\renderer.js:110:14)
at main (C:\Users\uriah\sites\www\vuetified-ssr\render_server\routers\view.js:35:19)
at Layer.handle [as handle_request] (C:\Users\uriah\sites\www\vuetified-ssr\node_modules\express\lib\router\layer.js:95:5)
__vue_ssr_bundle__:2
"entry": "main.build.js",
Anyway have configure the following files
views.js
renderer.js
webpack.server.js
and webpack.mix.js
and for the record im using latest laravel 5.5 vue, vuex , vue router,vue-server-renderer
Here is my Code:
view.js
const path = require('path')
// const VueSSR = require('vue-ssr')
const VueRender = require('../vue-ssr/renderer')
const serverConfig = require('../webpack.server')
const clientManifest = require('../../public/vue-ssr-client-manifest.json')
const indexRenderer = new VueRender({
// This will produce main.build.js
projectName: 'main',
// Cache View
rendererOptions: {
cache: require('lru-cache')({
max: 10240,
maxAge: 1000 * 60 * 15
}),
//! https://ssr.vuejs.org/en/bundle-renderer.html
//! We can add here Options such as
clientManifest
},
// Server Config
webpackServer: serverConfig,
contextHandler: function (req) {
// We Inject here the full url from laravel and data var
let context = { url: req.query.path };
context = Object.assign({}, context, JSON.parse(req.query.renderLaravelData));
return context
}
})
function main (req, res) {
indexRenderer.render(req, res, JSON.parse(req.query.renderLaravelTemplate))
}
module.exports = {
main
}
renderer.js
//! https://ssr.vuejs.org/en/streaming.html
const fs = require('fs')
const path = require('path')
const serialize = require('serialize-javascript')
process.env.VUE_ENV = 'server'
const NODE_ENV = process.env.NODE_ENV || 'production'
const isDev = NODE_ENV === 'development'
const { createBundleRenderer } = require('vue-server-renderer')
//! Can be Override at view.js
const DEFAULT_RENDERER_OPTIONS = {
cache: require('lru-cache')({
max: 1000,
maxAge: 1000 * 60 * 15
})
}
/**This will Yield HTML on resources/assets/views/server/app.blade.php
* This is the following Json Encoded Object we can Pass in Laravel Blade Template
* That will Replace resources/assets/views/app.blade.php
*/
const DEFAULT_APP_HTML = '{{ APP }}'
const DEFAULT_TITLE_HTML = '{{ _VueSSR_Title }}'
const DEFAULT_KEYWORDS_HTML = '{{ _VueSSR_Keywords }}'
const DEFAULT_DESCRIPTION_HTML = '{{ _VueSSR_Description }}'
const DEFAULT_HEAD_DATA = {
baseTitle: 'default title',
baseKeywords: 'keywords',
baseDescription: 'default description',
title: '',
description: '',
keywords: ''
}
function getFileName (webpackServer, projectName) {
return webpackServer.output.filename.replace('[name]', projectName)
}
class VueSSR {
constructor ({ projectName, rendererOptions, webpackServer , AppHtml, contextHandler, defaultHeadData }) {
this.projectName = projectName
this.rendererOptions = Object.assign({}, DEFAULT_RENDERER_OPTIONS, rendererOptions)
this.webpackServerConfig = webpackServer
this.AppHtml = AppHtml || DEFAULT_APP_HTML
this.contextHandler = contextHandler
this.HTML = null
this.template = ''
this.defaultHeadData = defaultHeadData || DEFAULT_HEAD_DATA
this.initRenderer()
}
//! If We Passed An Array, with headData['title','keywords','description'] var it will be replace
headDataInject (context, html) {
if (!context.headData) context.headData = {}
let head
head = html.replace('{{ _VueSSR_Title }}', (context.headData.title || this.defaultHeadData.title) + this.defaultHeadData.baseTitle)
head = head.replace('{{ _VueSSR_Keywords }}', (context.headData.keywords || this.defaultHeadData.keywords) + this.defaultHeadData.baseKeywords)
head = head.replace('{{ _VueSSR_Description }}', (context.headData.description || this.defaultHeadData.description) + this.defaultHeadData.baseDescription)
return head
}
createRenderer (bundle) {
//! Use the Vue SSR Function createBundleRenderer
return createBundleRenderer(bundle, this.rendererOptions)
}
//! Holds BundleRenderer Vue Object
initRenderer () {
//! If We Already Have Bundle Then Return
if (this.renderer) {
return this.renderer
}
//! Check if We are On Production Then We use SSR Bundle renderer
if (!isDev) {
// const bundlePath = path.join(this.webpackServerConfig.output.path, getFileName(this.webpackServerConfig, this.projectName))
//! Using https://ssr.vuejs.org/en/build-config.html
const bundlePath = path.resolve(__dirname, '../vue-ssr-bundle.json')
this.renderer = this.createRenderer(fs.readFileSync(bundlePath, 'utf-8'))
} else {
//! if No Node Server is Running We Use The Default Non SSR Vue Template
require('./bundle-loader')(this.webpackServerConfig, this.projectName, bundle => {
this.renderer = this.createRenderer(bundle)
})
}
}
parseHTML (template) {
const i = template.indexOf(this.AppHtml)
this.HTML = {
head: template.slice(0, i),
tail: template.slice(i + this.AppHtml.length)
}
}
render (req, res, template) {
if (this.template !== template) {
this.parseHTML(template)
}
if (!this.renderer) {
return res.end('waiting for compilation... refresh in a moment.')
}
let context = { url: req.url}
if (this.contextHandler) {
context = this.contextHandler(req)
}
this.RenderToStream(context, res)
}
RenderToStream (context, res) {
//! Use RenderToStream function in Vue SSR
const renderStream = this.renderer.renderToStream(context)
let firstChunk = true
renderStream.on('data', chunk => {
if (firstChunk) {
res.write(this.headDataInject(context, this.HTML.head))
if (context.initialState) {
let contextClean = Object.assign({}, context.initialState);
delete contextClean['_registeredComponents'];
delete contextClean['_styles'];
res.write(
`<script>window.__INITIAL_STATE__=${
serialize(contextClean, { isJSON: true })
}</script>`
)
}
firstChunk = false
}
res.write(chunk)
})
renderStream.on('end', () => {
res.end(this.HTML.tail)
})
//! If there is an Error Redirect to Error Page...
renderStream.on('error', err => {
console.error(err)
res.end('<script>location.href="/"</script>')
})
}
}
module.exports = VueSSR
webpack.server.js
const path = require('path')
const webpack = require('webpack')
const VueSSRServerPlugin = require('vue-ssr-webpack-plugin')
//! https://ssr.vuejs.org/en/build-config.html
module.exports = {
target: 'node',
devtool: 'source-map',
entry: './resources/assets/js/server-entry.js',
output: {
filename: '[name].build.js',
libraryTarget: 'commonjs2',
path: path.resolve(__dirname, '../render_server')
},
context: path.resolve(__dirname, '../'),
resolve: {
extensions: ['.js', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'~': path.resolve(__dirname, '../resources/assets/js'),
Components: path.resolve(__dirname, '../resources/assets/js/components'),
Views: path.resolve(__dirname, '../resources/assets/js/views'),
Routes: path.resolve(__dirname, '../resources/assets/js/routes'),
Helpers: path.resolve(__dirname, '../resources/assets/js/helpers'),
Plugins: path.resolve(__dirname, '../resources/assets/js/plugins'),
Layouts: path.resolve(__dirname, '../resources/assets/js/layouts'),
Partials: path.resolve(__dirname, '../resources/assets/js/partials'),
Mixins: path.resolve(__dirname, '../resources/assets/js/mixins'),
Api: path.resolve(__dirname, '../resources/assets/js/api')
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader'
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg|ttf|woff|eot)$/,
loader: 'file-loader',
query: {
name: 'file/[name].[ext]'
}
},
{
test: /\.styl$/,
loader: ['style-loader', 'css-loader', 'stylus-loader']
}
]
},
externals: Object.keys(require('../package.json').dependencies),
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.VUE_ENV': '"server"',
'process.BROWSER': false
}),
new VueSSRServerPlugin()
]
}
webpack.mix.js
let { mix } = require('laravel-mix');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.webpackConfig({
module: {
rules: [
//! Allow Us To Compile Stylus
{
test: /\.styl$/,
loader: ['style-loader', 'css-loader', 'stylus-loader']
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'~': path.resolve(__dirname, 'resources/assets/js'),
Components: path.resolve(__dirname, 'resources/assets/js/components'),
Views: path.resolve(__dirname, 'resources/assets/js/views'),
Routes: path.resolve(__dirname, 'resources/assets/js/routes'),
Helpers: path.resolve(__dirname, 'resources/assets/js/helpers'),
Plugins: path.resolve(__dirname, 'resources/assets/js/plugins'),
Layouts: path.resolve(__dirname, 'resources/assets/js/layouts'),
Partials: path.resolve(__dirname, 'resources/assets/js/partials'),
Mixins: path.resolve(__dirname, 'resources/assets/js/mixins'),
Api: path.resolve(__dirname, 'resources/assets/js/api')
}
},
plugins: [
// This plugins generates `vue-ssr-client-manifest.json` in the
// output directory.
new VueSSRClientPlugin()
]
});
mix.js('resources/assets/js/client-entry.js', 'public/js/main.js')
it did produce me vue-ssr-bundle.json
main.build.js
and vue-ssr-client.manifest.json
Without node run:server running, if it is not running
i get
If i do run node run:server i get this