chore(ts): fix types in renderer (#16)

This commit is contained in:
Xin Du (Clark) 2020-08-12 11:00:47 +01:00 committed by GitHub
parent d6ae2c73d9
commit b82d75d883
9 changed files with 44 additions and 14 deletions

View File

@ -5,7 +5,7 @@ type Plugin = string | { mode?: 'all' | 'client' | 'server', src: string, ssr?:
interface AppOptions { interface AppOptions {
css: string[] css: string[]
head: MetaInfo head: MetaInfo | (() => MetaInfo)
ErrorPage: null | string ErrorPage: null | string
extendPlugins: null | ((plugins: Plugin[]) => Plugin[]) extendPlugins: null | ((plugins: Plugin[]) => Plugin[])
features: { features: {

View File

@ -108,7 +108,7 @@ interface CommonConfiguration {
ignore: Array<string | IgnoreInstance> ignore: Array<string | IgnoreInstance>
// TODO: remove in Nuxt 3 // TODO: remove in Nuxt 3
mode: Mode mode: Mode
modern?: boolean modern?: boolean | 'client' | 'server'
modules: NuxtModule[] modules: NuxtModule[]
privateRuntimeConfig: Record<string, any> | ((env: NodeJS.ProcessEnv) => Record<string, any>) privateRuntimeConfig: Record<string, any> | ((env: NodeJS.ProcessEnv) => Record<string, any>)
publicRuntimeConfig: Record<string, any> | ((env: NodeJS.ProcessEnv) => Record<string, any>) publicRuntimeConfig: Record<string, any> | ((env: NodeJS.ProcessEnv) => Record<string, any>)

View File

@ -27,7 +27,7 @@ type CspPolicyName = 'child-src' | 'connect-src' | 'default-src' | 'font-src' |
interface RenderOptions { interface RenderOptions {
bundleRenderer: { bundleRenderer: {
shouldPrefetch: () => boolean shouldPrefetch: (fileWithoutQuery: string, asType: string) => boolean
shouldPreload: (fileWithoutQuery: string, asType: string) => boolean shouldPreload: (fileWithoutQuery: string, asType: string) => boolean
runInNewContext?: boolean runInNewContext?: boolean
} }
@ -63,6 +63,7 @@ interface RenderOptions {
preloadFiles: PreloadFile[] preloadFiles: PreloadFile[]
) => string[]) ) => string[])
} }
injectScripts?: boolean
resourceHints: boolean resourceHints: boolean
ssr?: boolean ssr?: boolean
ssrLog?: boolean | 'collapsed' ssrLog?: boolean | 'collapsed'

View File

@ -21,6 +21,8 @@ import createTimingMiddleware from './middleware/timing'
interface Manifest { interface Manifest {
assetsMapping: Record<string, string[]> assetsMapping: Record<string, string[]>
publicPath: string publicPath: string
initial: Array<string>
async: Array<string>
} }
export default class Server { export default class Server {
@ -37,6 +39,7 @@ export default class Server {
renderer: VueRenderer renderer: VueRenderer
resources: { resources: {
clientManifest?: Manifest clientManifest?: Manifest
loadingHTML?: string
modernManifest?: Manifest modernManifest?: Manifest
serverManifest?: Manifest serverManifest?: Manifest
ssrTemplate?: TemplateExecutor ssrTemplate?: TemplateExecutor

View File

@ -65,7 +65,7 @@ export const isModernBrowser = (ua: string) => {
) )
} }
export const isModernRequest = (req: NuxtRequest, modernMode = false) => { export const isModernRequest = (req: NuxtRequest, modernMode: boolean | string = false) => {
if (modernMode === false) { if (modernMode === false) {
return false return false
} }

View File

@ -2,19 +2,37 @@ import path from 'path'
import fs from 'fs-extra' import fs from 'fs-extra'
import consola from 'consola' import consola from 'consola'
import template from 'lodash/template' import template from 'lodash/template'
import { TARGETS, isModernRequest, waitFor } from 'src/utils' import { Target, TARGETS, isModernRequest, waitFor } from 'src/utils'
import ServerContext from 'src/server/context' import ServerContext from 'src/server/context'
import SPARenderer from './renderers/spa' import SPARenderer from './renderers/spa'
import SSRRenderer from './renderers/ssr' import SSRRenderer from './renderers/ssr'
import ModernRenderer from './renderers/modern' import ModernRenderer from './renderers/modern'
declare module 'fs-extra' {
export function exists(path: string): Promise<boolean>;
}
export interface RenderContext {
target?: Target
spa?: boolean
modern?: boolean
req?: any
res?: any
runtimeConfig?: {
private: ServerContext['options']['privateRuntimeConfig'],
public: ServerContext['options']['publicRuntimeConfig']
}
url?: string
}
export default class VueRenderer { export default class VueRenderer {
__closed?: boolean __closed?: boolean
_state?: 'created' | 'loading' | 'ready' | 'error' _state?: 'created' | 'loading' | 'ready' | 'error'
_error?: null _error?: null
_readyPromise?: Promise<any> _readyPromise?: Promise<any>
distPath: string distPath: string
options: ServerContext['options']
serverContext: ServerContext serverContext: ServerContext
renderer: { renderer: {
ssr: any ssr: any
@ -252,7 +270,7 @@ export default class VueRenderer {
return renderer.render(renderContext) return renderer.render(renderContext)
} }
async renderRoute (url, renderContext = {}, _retried = 0) { async renderRoute (url, renderContext : RenderContext = {}, _retried = 0) {
/* istanbul ignore if */ /* istanbul ignore if */
if (!this.isReady) { if (!this.isReady) {
// Fall-back to loading-screen if enabled // Fall-back to loading-screen if enabled

View File

@ -1,4 +1,5 @@
import ServerContext from 'nuxt/server/context' import ServerContext from 'src/server/context'
import { RenderContext } from '../renderer'
export default class BaseRenderer { export default class BaseRenderer {
serverContext: ServerContext serverContext: ServerContext
@ -18,7 +19,7 @@ export default class BaseRenderer {
return templateFn(opts) return templateFn(opts)
} }
render (renderContext) { render (_renderContext: RenderContext) {
throw new Error('`render()` needs to be implemented') throw new Error('`render()` needs to be implemented')
} }
} }

View File

@ -37,7 +37,7 @@ export default class SPARenderer extends BaseRenderer {
const modernMode = this.options.modern const modernMode = this.options.modern
const modern = (modernMode && this.options.target === TARGETS.static) || isModernRequest(req, modernMode) const modern = (modernMode && this.options.target === TARGETS.static) || isModernRequest(req, modernMode)
const cacheKey = `${modern ? 'modern:' : 'legacy:'}${url}` const cacheKey = `${modern ? 'modern:' : 'legacy:'}${url}`
let meta = this.cache.get(cacheKey) let meta : Record<string, any> = this.cache.get(cacheKey)
if (meta) { if (meta) {
// Return a copy of the content, so that future // Return a copy of the content, so that future
@ -127,7 +127,7 @@ export default class SPARenderer extends BaseRenderer {
.map(file => ({ ...file, modern })) .map(file => ({ ...file, modern }))
meta.resourceHints += meta.preloadFiles meta.resourceHints += meta.preloadFiles
.map(({ file, extension, fileWithoutQuery, asType, modern }) => { .map(({ file, extension, asType, modern }) => {
let extra = '' let extra = ''
if (asType === 'font') { if (asType === 'font') {
extra = ` type="font/${extension}"${cors ? '' : ' crossorigin'}` extra = ` type="font/${extension}"${cors ? '' : ' crossorigin'}`

View File

@ -11,6 +11,8 @@ import ServerContext from 'src/server/context'
import BaseRenderer from './base' import BaseRenderer from './base'
export default class SSRRenderer extends BaseRenderer { export default class SSRRenderer extends BaseRenderer {
vueRenderer: typeof import('@vue/server-renderer')
constructor (serverContext: ServerContext) { constructor (serverContext: ServerContext) {
super(serverContext) super(serverContext)
this.createRenderer() this.createRenderer()
@ -170,9 +172,14 @@ export default class SSRRenderer extends BaseRenderer {
} }
const { csp } = this.options.render const { csp } = this.options.render
// Only add the hash if 'unsafe-inline' rule isn't present to avoid conflicts (#5387) let shouldHashCspScriptSrc = false
const containsUnsafeInlineScriptSrc = csp.policies && csp.policies['script-src'] && csp.policies['script-src'].includes('\'unsafe-inline\'') if (typeof csp === 'object') {
const shouldHashCspScriptSrc = csp && (csp.unsafeInlineCompatibility || !containsUnsafeInlineScriptSrc) const { policies, unsafeInlineCompatibility } = csp
shouldHashCspScriptSrc = unsafeInlineCompatibility ||
// Only add the hash if 'unsafe-inline' rule isn't present to avoid conflicts (#5387)
!(policies && policies['script-src'] && policies['script-src'].includes('\'unsafe-inline\''))
}
const inlineScripts = [] const inlineScripts = []
if (renderContext.staticAssetsBase) { if (renderContext.staticAssetsBase) {
@ -228,7 +235,7 @@ export default class SSRRenderer extends BaseRenderer {
// Calculate CSP hashes // Calculate CSP hashes
const cspScriptSrcHashes = [] const cspScriptSrcHashes = []
if (csp) { if (typeof csp === 'object') {
if (shouldHashCspScriptSrc) { if (shouldHashCspScriptSrc) {
for (const script of inlineScripts) { for (const script of inlineScripts) {
const hash = crypto.createHash(csp.hashAlgorithm) const hash = crypto.createHash(csp.hashAlgorithm)