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

+ 55 - 0
src/compiler/create-compiler.js

@@ -0,0 +1,55 @@
+/* @flow */
+
+import { extend } from 'shared/util'
+import { detectErrors } from './error-detector'
+import { createCompileToFunctionFn } from './to-function'
+
+export function createCompilerCreator (baseCompile: Function): Function {
+  return function createCompiler (baseOptions: CompilerOptions) {
+    function compile (
+      template: string,
+      options?: CompilerOptions
+    ): CompiledResult {
+      const finalOptions = Object.create(baseOptions)
+      const errors = []
+      const tips = []
+      finalOptions.warn = (msg, tip) => {
+        (tip ? tips : errors).push(msg)
+      }
+
+      if (options) {
+        // merge custom modules
+        if (options.modules) {
+          finalOptions.modules =
+            (baseOptions.modules || []).concat(options.modules)
+        }
+        // merge custom directives
+        if (options.directives) {
+          finalOptions.directives = extend(
+            Object.create(baseOptions.directives),
+            options.directives
+          )
+        }
+        // copy other options
+        for (const key in options) {
+          if (key !== 'modules' && key !== 'directives') {
+            finalOptions[key] = options[key]
+          }
+        }
+      }
+
+      const compiled = baseCompile(template, finalOptions)
+      if (process.env.NODE_ENV !== 'production') {
+        errors.push.apply(errors, detectErrors(compiled.ast))
+      }
+      compiled.errors = errors
+      compiled.tips = tips
+      return compiled
+    }
+
+    return {
+      compile,
+      compileToFunctions: createCompileToFunctionFn(compile)
+    }
+  }
+}

+ 6 - 52
src/compiler/index.js

@@ -1,13 +1,14 @@
 /* @flow */
 
-import { extend } from 'shared/util'
 import { parse } from './parser/index'
 import { optimize } from './optimizer'
 import { generate } from './codegen/index'
-import { detectErrors } from './error-detector'
-import { createCompileToFunctionFn } from './to-function'
+import { createCompilerCreator } from './create-compiler'
 
-function baseCompile (
+// `createCompilerCreator` allows creating compilers that use alternative
+// parser/optimizer/codegen, e.g the SSR optimizing compiler.
+// Here we just export a default compiler using the default parts.
+export const createCompiler = createCompilerCreator(function baseCompile (
   template: string,
   options: CompilerOptions
 ): CompiledResult {
@@ -19,51 +20,4 @@ function baseCompile (
     render: code.render,
     staticRenderFns: code.staticRenderFns
   }
-}
-
-export function createCompiler (baseOptions: CompilerOptions) {
-  function compile (
-    template: string,
-    options?: CompilerOptions
-  ): CompiledResult {
-    const finalOptions = Object.create(baseOptions)
-    const errors = []
-    const tips = []
-    finalOptions.warn = (msg, tip) => {
-      (tip ? tips : errors).push(msg)
-    }
-
-    if (options) {
-      // merge custom modules
-      if (options.modules) {
-        finalOptions.modules = (baseOptions.modules || []).concat(options.modules)
-      }
-      // merge custom directives
-      if (options.directives) {
-        finalOptions.directives = extend(
-          Object.create(baseOptions.directives),
-          options.directives
-        )
-      }
-      // copy other options
-      for (const key in options) {
-        if (key !== 'modules' && key !== 'directives') {
-          finalOptions[key] = options[key]
-        }
-      }
-    }
-
-    const compiled = baseCompile(template, finalOptions)
-    if (process.env.NODE_ENV !== 'production') {
-      errors.push.apply(errors, detectErrors(compiled.ast))
-    }
-    compiled.errors = errors
-    compiled.tips = tips
-    return compiled
-  }
-
-  return {
-    compile,
-    compileToFunctions: createCompileToFunctionFn(compile)
-  }
-}
+})

+ 14 - 4
src/compiler/to-function.js

@@ -3,6 +3,12 @@
 import { noop } from 'shared/util'
 import { warn, tip } from 'core/util/debug'
 
+type CompiledFunctionResult = {
+  render: Function;
+  staticRenderFns: Array<Function>;
+  stringRenderFns?: Array<Function>;
+};
+
 function createFunction (code, errors) {
   try {
     return new Function(code)
@@ -71,10 +77,14 @@ export function createCompileToFunctionFn (compile: Function): Function {
     const res = {}
     const fnGenErrors = []
     res.render = createFunction(compiled.render, fnGenErrors)
-    const l = compiled.staticRenderFns.length
-    res.staticRenderFns = new Array(l)
-    for (let i = 0; i < l; i++) {
-      res.staticRenderFns[i] = createFunction(compiled.staticRenderFns[i], fnGenErrors)
+    res.staticRenderFns = compiled.staticRenderFns.map(code => {
+      return createFunction(code, fnGenErrors)
+    })
+    // ssr-specific
+    if (res.stringRenderFns) {
+      res.stringRenderFns = compiled.stringRenderFns.map(code => {
+        return createFunction(code, fnGenErrors)
+      })
     }
 
     // check function generation errors.

+ 1 - 0
src/platforms/web/entry-compiler.js

@@ -2,3 +2,4 @@
 
 export { parseComponent } from 'sfc/parser'
 export { compile, compileToFunctions } from './compiler/index'
+export { ssrCompile, ssrCompileToFunctions } from './server/compiler'

+ 11 - 0
src/platforms/web/server/compiler.js

@@ -0,0 +1,11 @@
+/* @flow */
+
+import { baseOptions } from '../compiler/options'
+import { createCompiler } from 'server/optimizing-compiler/index'
+
+const { compile, compileToFunctions } = createCompiler(baseOptions)
+
+export {
+  compile as ssrCompile,
+  compileToFunctions as ssrCompileToFunctions
+}

+ 19 - 3
src/server/optimizing-compiler/codegen.js

@@ -1,7 +1,11 @@
 /* @flow */
 
+// The SSR codegen is essentially extending the default codegen to handle
+// SSR-optimizable nodes and turn them into string render fns. In cases where
+// a node is not optimizable it simply falls back to the default codegen.
+
 // import * as directives from './directives'
-import { CodegenState } from 'compiler/codegen/index'
+import { CodegenState, genElement } from 'compiler/codegen/index'
 
 type SSRCompileResult = {
   render: string;
@@ -23,7 +27,7 @@ export function generate (
   options: CompilerOptions
 ): SSRCompileResult {
   const state = new SSRCodegenState(options)
-  const code = ast ? genElement(ast, state) : '_c("div")'
+  const code = ast ? genSSRElement(ast, state, true) : '_c("div")'
   return {
     render: `with(this){return ${code}}`,
     staticRenderFns: state.staticRenderFns,
@@ -31,6 +35,18 @@ export function generate (
   }
 }
 
-function genElement (el: ASTElement, state: SSRCodegenState): string {
+function genSSRElement (
+  el: ASTElement,
+  state: SSRCodegenState,
+  isComponentRoot?: boolean
+): string {
+  if (el.ssrOptimizableRoot && !isComponentRoot) {
+    return genStringRenderFn(el, state)
+  } else {
+    return genElement(el, state)
+  }
+}
 
+function genStringRenderFn (el, state) {
+  return ''
 }

+ 5 - 48
src/server/optimizing-compiler/index.js

@@ -1,13 +1,11 @@
 /* @flow */
 
-import { extend } from 'shared/util'
 import { parse } from 'compiler/parser/index'
-import { detectErrors } from 'compiler/error-detector'
-
 import { generate } from './codegen'
 import { optimize } from './optimizer'
+import { createCompilerCreator } from 'compiler/create-compiler'
 
-function baseCompile (
+export const createCompiler = createCompilerCreator(function baseCompile (
   template: string,
   options: CompilerOptions
 ): CompiledResult {
@@ -17,48 +15,7 @@ function baseCompile (
   return {
     ast,
     render: code.render,
-    staticRenderFns: code.staticRenderFns
-  }
-}
-
-export function createCompiler (baseOptions: CompilerOptions) {
-  return function compile (
-    template: string,
-    options?: CompilerOptions
-  ): CompiledResult {
-    const finalOptions = Object.create(baseOptions)
-    const errors = []
-    const tips = []
-    finalOptions.warn = (msg, tip) => {
-      (tip ? tips : errors).push(msg)
-    }
-
-    if (options) {
-      // merge custom modules
-      if (options.modules) {
-        finalOptions.modules = (baseOptions.modules || []).concat(options.modules)
-      }
-      // merge custom directives
-      if (options.directives) {
-        finalOptions.directives = extend(
-          Object.create(baseOptions.directives),
-          options.directives
-        )
-      }
-      // copy other options
-      for (const key in options) {
-        if (key !== 'modules' && key !== 'directives') {
-          finalOptions[key] = options[key]
-        }
-      }
-    }
-
-    const compiled = baseCompile(template, finalOptions)
-    if (process.env.NODE_ENV !== 'production') {
-      errors.push.apply(errors, detectErrors(compiled.ast))
-    }
-    compiled.errors = errors
-    compiled.tips = tips
-    return compiled
+    staticRenderFns: code.staticRenderFns,
+    stringRenderFns: code.stringRenderFns
   }
-}
+})