Skip to content

Refactor vue-ssr, switch to maintained fast-render #407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions packages/vue-router2/plugin/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ class VueRouterCompiler extends CachingCompiler {
let map = ''

let babelOptions = Babel.getDefaultOptions()
babelOptions.sourceMap = true
babelOptions.filename = babelOptions.sourceFileName = sourcePath
babelOptions.sourceMapTarget = babelOptions.filename + '.map'

// Babel compilation
let output = Babel.compile(code, babelOptions)
Expand Down
2 changes: 1 addition & 1 deletion packages/vue-ssr/.versions
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ routepolicy@1.0.12
server-render@0.3.0
service-configuration@1.0.11
socket-stream-client@0.1.0
staringatlights:fast-render@2.16.5
cloudspider:fast-render@3.2.1
staringatlights:inject-data@2.0.5
tracker@1.1.3
underscore@1.0.10
Expand Down
4 changes: 2 additions & 2 deletions packages/vue-ssr/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Package.onUse(function (api) {
'routepolicy',
'url',
'akryum:npm-check@0.1.1',
'staringatlights:fast-render@3.2.0',
'cloudspider:fast-render@3.2.1',
'ejson',
'server-render',
])
Expand All @@ -28,6 +28,6 @@ Package.onUse(function (api) {
})

Npm.depends({
'vue-server-renderer': '2.6.10',
'vue-server-renderer': '2.6.11',
'cookie-parser': '1.4.4',
})
2 changes: 1 addition & 1 deletion packages/vue-ssr/server/context.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// server/ssr_context.js
// stolen from https://github.com/kadirahq/flow-router/blob/ssr/server/ssr_context.js

import { FastRender } from 'meteor/staringatlights:fast-render'
import { FastRender } from 'meteor/cloudspider:fast-render'

export default class SsrContext {
constructor () {
Expand Down
160 changes: 42 additions & 118 deletions packages/vue-ssr/server/index.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,30 @@
import Vue from 'vue'
import { createRenderer } from 'vue-server-renderer'
import { WebApp } from 'meteor/webapp'
import cookieParser from 'cookie-parser'
import { onPageLoad } from 'meteor/server-render'
import { FastRender } from 'meteor/staringatlights:fast-render'
import { FastRender } from 'meteor/cloudspider:fast-render'

import defaultAppTemplate from './lib/defaultAppTemplate'
import createDefaultApp from './lib/createDefaultApp'

import SsrContext from './context'
import patchSubscribeData from './data'

function IsAppUrl (req) {
var url = req.url
if (url === '/favicon.ico' || url === '/robots.txt') {
return false
}

if (url === '/app.manifest') {
return false
}

// Avoid serving app HTML for declared routes such as /sockjs/.
if (RoutePolicy.classify(url)) {
return false
}
return true
}
export { default as IsAppUrl } from './lib/isAppUrl'

VueSSR = {}
const VueSSR = {}

VueSSR.outlet = process.env.VUE_OUTLET || 'app'

VueSSR.defaultAppTemplate = `
<div id="not-the-app" style="font-family: sans-serif;">
<h1>This is not what you expected</h1>
<p>
You need to tell <code>vue-ssr</code> how to create your app by setting the <code>VueSSR.createApp</code> function. It should return a new Vue instance.
</p>
<p>
Here is an example of server-side code:
</p>
<pre style="background: #ddd; padding: 12px; border-radius: 3px; font-family: monospace;">import Vue from 'vue'
import { VueSSR } from 'meteor/akryum:vue-ssr'

function createApp () {
return new Vue({
render: h => h('div', 'Hello world'),
})
}

VueSSR.createApp = createApp</pre>
</div>
`

VueSSR.createApp = function () {
return new Vue({
template: VueSSR.defaultAppTemplate,
})
}

VueSSR.defaultAppTemplate = defaultAppTemplate
VueSSR.createApp = createDefaultApp()
VueSSR.ssrContext = new Meteor.EnvironmentVariable()
VueSSR.inSubscription = new Meteor.EnvironmentVariable() // <-- needed in data.js

patchSubscribeData(VueSSR)

const renderer = createRenderer()

function writeServerError (sink) {
function writeServerError(sink) {
sink.appendToBody('Server Error')
}

Expand All @@ -83,63 +43,42 @@ onPageLoad(sink => new Promise((resolve, reject) => {
// https://github.com/kadirahq/flow-router/blob/ssr/server/route.js#L61
const ssrContext = new SsrContext()

VueSSR.ssrContext.withValue(ssrContext, () => {
VueSSR.ssrContext.withValue(ssrContext, async () => {
try {
// const frData = InjectData.getData(res, 'fast-render-data')
// if (frData) {
// ssrContext.addData(frData.collectionData)
// }

// Vue
const context = { url: req.url }
let asyncResult

const result = VueSSR.createApp(context)
if (result && typeof result.then === 'function') {
asyncResult = result
} else {
asyncResult = Promise.resolve(result)
}

asyncResult.then(app => {
renderer.renderToString(
app,
context,
(error, html) => {
if (error) {
console.error(error)
writeServerError(sink)
return
}

// const frContext = FastRender.frContext.get()
// const data = frContext.getData()
// // InjectData.pushData(res, 'fast-render-data', data)
// const injectData = EJSON.stringify({
// 'fast-render-data': data,
// })
// // sink.appendToHead(`<script type="text/inject-data">${encodeURIComponent(injectData)}</script>`)

let appendHtml
if (typeof context.appendHtml === 'function') appendHtml = context.appendHtml()

const head = ((appendHtml && appendHtml.head) || context.head) || ''
const body = ((appendHtml && appendHtml.body) || context.body) || ''
const js = ((appendHtml && appendHtml.js) || context.js) || ''

const script = js && `<script type="text/javascript">${js}</script>`

sink.renderIntoElementById(VueSSR.outlet, html)
sink.appendToHead(head)
sink.appendToBody([body, script])

resolve()
},
)
}).catch(e => {
console.error(e)
writeServerError(sink)
resolve()
})

const asyncResult = typeof result.then === 'function' ? result : Promise.resolve(result)

const app = await asyncResult

renderer.renderToString(
app,
context,
(error, html) => {
if (error) {
console.error(error)
writeServerError(sink)
return
}

const appendHtml = typeof context.appendHtml === 'function' && context.appendHtml()

const head = ((appendHtml && appendHtml.head) || context.head) || ''
const body = ((appendHtml && appendHtml.body) || context.body) || ''
const js = ((appendHtml && appendHtml.js) || context.js) || ''

const script = js && `<script type="text/javascript">${js}</script>`

sink.renderIntoElementById(VueSSR.outlet, html)
sink.appendToHead(head)
sink.appendToBody([body, script])

resolve()
}
)
} catch (error) {
console.error(error)
writeServerError(sink)
Expand All @@ -149,19 +88,4 @@ onPageLoad(sink => new Promise((resolve, reject) => {
})
}))

return

/* eslint-disable */

Meteor.bindEnvironment(function () {
WebApp.rawConnectHandlers.use(cookieParser())

WebApp.connectHandlers.use((req, res, next) => {
if (!IsAppUrl(req)) {
next()
return
}


})
})()
export { VueSSR }
9 changes: 9 additions & 0 deletions packages/vue-ssr/server/lib/createDefaultApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Vue from 'vue'

import defaultAppTemplate from './defaultAppTemplate'

export default () => {
return new Vue({
template: defaultAppTemplate
})
}
21 changes: 21 additions & 0 deletions packages/vue-ssr/server/lib/defaultAppTemplate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export default `
<div id="not-the-app" style="font-family: sans-serif;">
<h1>This is not what you expected</h1>
<p>
You need to tell <code>vue-ssr</code> how to create your app by setting the <code>VueSSR.createApp</code> function. It should return a new Vue instance.
</p>
<p>
Here is an example of server-side code:
</p>
<pre style="background: #ddd; padding: 12px; border-radius: 3px; font-family: monospace;">import Vue from 'vue'
import { VueSSR } from 'meteor/akryum:vue-ssr'

function createApp () {
return new Vue({
render: h => h('div', 'Hello world'),
})
}

VueSSR.createApp = createApp</pre>
</div>
`
14 changes: 14 additions & 0 deletions packages/vue-ssr/server/lib/isAppUrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { RoutePolicy } from 'meteor/routepolicy'

const nonAppUrls = ['/favicon.ico', '/robots.txt', '/app.manifest']

export default (req) => {
const url = req.url

if (nonAppUrls.includes(url)) {
return false
}

// Avoid serving app HTML for declared routes such as /sockjs/.
return !RoutePolicy.classify(url)
}