Skip to content
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

refactor(vue-renderer): split renderer into ssr, spa and modern #5559

Merged
merged 10 commits into from
Apr 20, 2019
29 changes: 3 additions & 26 deletions packages/server/src/middleware/modern.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import chalk from 'chalk'
import consola from 'consola'
import UAParser from 'ua-parser-js'
import semver from 'semver'

Expand All @@ -23,22 +21,6 @@ const isModernBrowser = (ua) => {
return Boolean(modernBrowsers[browser.name] && semver.gte(browserVersion, modernBrowsers[browser.name]))
}

const distinctModernModeOptions = [false, 'client', 'server']

const detectModernBuild = ({ options, resources }) => {
if (distinctModernModeOptions.includes(options.modern)) {
return
}

if (!resources.modernManifest) {
options.modern = false
return
}

options.modern = options.render.ssr ? 'server' : 'client'
consola.info(`Modern bundles are detected. Modern mode (${chalk.green.bold(options.modern)}) is enabled now.`)
}

const detectModernBrowser = ({ socket = {}, headers }) => {
if (socket.isModernBrowser === undefined) {
const ua = headers && headers['user-agent']
Expand All @@ -48,15 +30,10 @@ const detectModernBrowser = ({ socket = {}, headers }) => {
return socket.isModernBrowser
}

export default ({ context }) => {
let detected = false
export default ({ serverContext }) => {
return (req, res, next) => {
if (!detected) {
detectModernBuild(context)
detected = true
}
if (context.options.modern !== false) {
req.modernMode = detectModernBrowser(req)
if (serverContext.options.modern !== false) {
req._modern = detectModernBrowser(req)
}
next()
}
Expand Down
4 changes: 1 addition & 3 deletions packages/server/src/middleware/nuxt.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default ({ options, nuxt, renderRoute, resources }) => async function nux
cspScriptSrcHashes,
error,
redirected,
getPreloadFiles
preloadFiles
} = result

if (redirected) {
Expand All @@ -52,8 +52,6 @@ export default ({ options, nuxt, renderRoute, resources }) => async function nux
if (!error && options.render.http2.push) {
// Parse resourceHints to extract HTTP.2 prefetch/push headers
// https://w3c.github.io/preload/#server-push-http-2
const preloadFiles = getPreloadFiles()

const { shouldPush, pushAssets } = options.render.http2
const { publicPath } = resources.clientManifest

Expand Down
6 changes: 3 additions & 3 deletions packages/server/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export default class Server {
// Initialize vue-renderer
const { VueRenderer } = await import('@nuxt/vue-renderer')

const context = new ServerContext(this)
this.renderer = new VueRenderer(context)
this.serverContext = new ServerContext(this)
this.renderer = new VueRenderer(this.serverContext)
await this.renderer.ready()

// Setup nuxt middleware
Expand Down Expand Up @@ -112,7 +112,7 @@ export default class Server {
}

this.useMiddleware(createModernMiddleware({
context: this.renderer.context
serverContext: this.serverContext
}))

// Dev middleware
Expand Down
97 changes: 31 additions & 66 deletions packages/server/test/middleware/modern.test.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import consola from 'consola'

jest.mock('chalk', () => ({
green: {
bold: modern => `greenBold(${modern})`
}
}))

const createContext = () => ({
const createServerContext = () => ({
resources: {},
options: {
render: {}
}
})

const createServerContext = () => ({
const createRenderContext = () => ({
req: { headers: {} },
next: jest.fn()
})
Expand All @@ -34,107 +32,74 @@ describe('server: modernMiddleware', () => {
})

test('should not detect modern build if modern mode is specified', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()

context.options.modern = false
modernMiddleware(ctx.req, ctx.res, ctx.next)
context.options.modern = 'client'
modernMiddleware(ctx.req, ctx.res, ctx.next)
context.options.modern = 'server'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.modernMode).toEqual(false)
})

test('should detect client modern build and display message', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()
const serverContext = createServerContext()
const modernMiddleware = createModernMiddleware({ serverContext })
const ctx = createRenderContext()

context.resources.modernManifest = {}
serverContext.options.modern = false
modernMiddleware(ctx.req, ctx.res, ctx.next)
expect(context.options.modern).toEqual('client')
expect(consola.info).toBeCalledWith('Modern bundles are detected. Modern mode (greenBold(client)) is enabled now.')
})

test('should detect server modern build and display message', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()

context.options.render.ssr = true
context.resources.modernManifest = {}
serverContext.options.modern = 'client'
modernMiddleware(ctx.req, ctx.res, ctx.next)
expect(context.options.modern).toEqual('server')
expect(consola.info).toBeCalledWith('Modern bundles are detected. Modern mode (greenBold(server)) is enabled now.')
})

test('should not detect modern browser if modern build is not found', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()

serverContext.options.modern = 'server'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.modernMode).toBeUndefined()
expect(ctx.req._modern).toEqual(false)
})

test('should not detect modern browser if connect has been detected', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()
const serverContext = createServerContext()
const modernMiddleware = createModernMiddleware({ serverContext })
const ctx = createRenderContext()
ctx.req.socket = { isModernBrowser: true }

context.options.dev = true
context.options.modern = 'server'
serverContext.options.dev = true
serverContext.options.modern = 'server'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.modernMode).toEqual(true)
expect(ctx.req._modern).toEqual(true)
})

test('should detect modern browser based on user-agent', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()
const serverContext = createServerContext()
const modernMiddleware = createModernMiddleware({ serverContext })
const ctx = createRenderContext()
const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
ctx.req.headers['user-agent'] = ua
ctx.req.socket = {}

context.options.dev = true
context.options.modern = 'server'
serverContext.options.dev = true
serverContext.options.modern = 'server'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.socket.isModernBrowser).toEqual(true)
expect(ctx.req.modernMode).toEqual(true)
expect(ctx.req._modern).toEqual(true)
})

test('should detect legacy browser based on user-agent', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()
const serverContext = createServerContext()
const modernMiddleware = createModernMiddleware({ serverContext })
const ctx = createRenderContext()
const ua = 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))'
ctx.req.headers['user-agent'] = ua
ctx.req.socket = {}

context.options.dev = true
context.options.modern = 'client'
serverContext.options.dev = true
serverContext.options.modern = 'client'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.socket.isModernBrowser).toEqual(false)
})

test('should ignore illegal user-agent', () => {
const context = createContext()
const modernMiddleware = createModernMiddleware({ context })
const ctx = createServerContext()
const serverContext = createServerContext()
const modernMiddleware = createModernMiddleware({ serverContext })
const ctx = createRenderContext()
const ua = 'illegal user agent'
ctx.req.headers['user-agent'] = ua
ctx.req.socket = {}

context.options.dev = true
context.options.modern = 'client'
serverContext.options.dev = true
serverContext.options.modern = 'client'
modernMiddleware(ctx.req, ctx.res, ctx.next)

expect(ctx.req.socket.isModernBrowser).toEqual(false)
Expand Down
10 changes: 5 additions & 5 deletions packages/server/test/middleware/nuxt.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe('server: nuxtMiddleware', () => {
const context = createContext()
const result = {
html: 'rendered html',
getPreloadFiles: jest.fn(() => ['/nuxt/preload1.js', '/nuxt/preload2.js'])
preloadFiles: ['/nuxt/preload1.js', '/nuxt/preload2.js']
}
context.renderRoute.mockReturnValue(result)
const pushAssets = jest.fn((req, res, publicPath, preloadFiles) => preloadFiles)
Expand All @@ -158,12 +158,12 @@ describe('server: nuxtMiddleware', () => {
const context = createContext()
const result = {
html: 'rendered html',
getPreloadFiles: jest.fn(() => [
preloadFiles: [
{ file: '/nuxt/preload1.js', asType: 'script' },
{ file: '/nuxt/preload2.js', asType: 'script' },
{ file: '/nuxt/style.css', asType: 'style' },
{ file: '/nuxt/font.woff', asType: 'font' }
])
]
}
context.renderRoute.mockReturnValue(result)
context.options.render.http2 = { push: true }
Expand All @@ -182,12 +182,12 @@ describe('server: nuxtMiddleware', () => {
const context = createContext()
const result = {
html: 'rendered html',
getPreloadFiles: jest.fn(() => [
preloadFiles: [
{ file: '/nuxt/preload1.js', asType: 'script' },
{ file: '/nuxt/preload2.js', asType: 'script', modern: true },
{ file: '/nuxt/style.css', asType: 'style' },
{ file: '/nuxt/font.woff', asType: 'font' }
])
]
}
context.renderRoute.mockReturnValue(result)
context.options.dev = true
Expand Down
7 changes: 3 additions & 4 deletions packages/server/test/server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ describe('server: server', () => {
const nuxt = createNuxt()
const server = new Server(nuxt)
server.useMiddleware = jest.fn()
server.renderer = {
context: { id: 'test-server-context' }
}
server.serverContext = { id: 'test-server-context' }

await server.setupMiddleware()

Expand All @@ -198,8 +196,9 @@ describe('server: server', () => {
})

const modernMiddleware = {
context: server.renderer.context
serverContext: server.serverContext
}

expect(createModernMiddleware).toBeCalledTimes(1)
expect(createModernMiddleware).toBeCalledWith(modernMiddleware)
expect(server.useMiddleware).nthCalledWith(3, {
Expand Down
Loading