Evan You 9 лет назад
Родитель
Сommit
ac219b34c3

+ 4 - 3
src/server/bundle-renderer/create-bundle-renderer.js

@@ -30,10 +30,11 @@ type RenderBundle = {
 export function createBundleRendererCreator (createRenderer: () => Renderer) {
   return function createBundleRenderer (
     bundle: string | RenderBundle,
-    rendererOptions?: RenderOptions
+    rendererOptions?: RenderOptions = {}
   ) {
     let files, entry, maps, moduleMappings
-    let basedir = rendererOptions && rendererOptions.basedir
+    let basedir = rendererOptions.basedir
+    const direct = rendererOptions.directMode
 
     // load bundle if given filepath
     if (
@@ -83,7 +84,7 @@ export function createBundleRendererCreator (createRenderer: () => Renderer) {
     }
     const renderer = createRenderer(rendererOptions)
 
-    const run = createBundleRunner(entry, files, basedir)
+    const run = createBundleRunner(entry, files, basedir, direct)
 
     return {
       renderToString: (context?: Object, cb: (err: ?Error, res: ?string) => void) => {

+ 26 - 7
src/server/bundle-renderer/create-bundle-runner.js

@@ -70,12 +70,31 @@ function compileModule (files, basedir) {
   return evaluateModule
 }
 
-export function createBundleRunner (entry, files, basedir) {
+export function createBundleRunner (entry, files, basedir, direct) {
   const evaluate = compileModule(files, basedir)
-  return (_context = {}) => new Promise((resolve, reject) => {
-    const context = createContext(_context)
-    const evaluatedFiles = _context._evaluatedFiles = {}
-    const res = evaluate(entry, context, evaluatedFiles)
-    resolve(typeof res === 'function' ? res(_context) : res)
-  })
+  if (!direct) {
+    // default mode: creates a fresh context and re-evaluate the bundle
+    // on each render. Ensures entire application state is fresh for each
+    // render, but incurs extra evaluation cost.
+    return (_context = {}) => new Promise((resolve, reject) => {
+      const context = createContext(_context)
+      const evaluatedFiles = _context._evaluatedFiles = {}
+      const res = evaluate(entry, context, evaluatedFiles)
+      resolve(typeof res === 'function' ? res(_context) : res)
+    })
+  } else {
+    // direct mode: instead of re-evaluating the whole bundle on
+    // each render, it simply calls the exported function. This avoids the
+    // module evaluation costs but requires the source code to be structured
+    // slightly differently.
+    const context = createContext()
+    const runner = evaluate(entry, context, {})
+    if (typeof runner !== 'function') {
+      throw new Error('direct mode expects bundle export to be a function.')
+    }
+    return (_context = {}) => {
+      context.__VUE_SSR_CONTEXT__ = _context
+      return runner(_context)
+    }
+  }
 }

+ 1 - 0
src/server/create-renderer.js

@@ -24,6 +24,7 @@ export type RenderOptions = {
   cache?: RenderCache;
   template?: string;
   basedir?: string;
+  directMode?: boolean;
   shouldPreload?: Function;
   serverManifest?: ServerManifest;
   clientManifest?: ClientManifest;