import { jsx, jsxs, Fragment } from 'solid-jsx/jsx-runtime';

/*@jsxRuntime automatic @jsxImportSource solid-jsx*/
const toc = [{
  "depth": 1,
  "value": "SSR",
  "children": [{
    "depth": 2,
    "value": "注水脚本",
    "children": []
  }, {
    "depth": 2,
    "value": "异步和流式 SSR",
    "children": []
  }, {
    "depth": 2,
    "value": "SSR 注意事项",
    "children": []
  }, {
    "depth": 2,
    "value": "SSR 入门",
    "children": []
  }, {
    "depth": 2,
    "value": "静态站点生成入门",
    "children": []
  }]
}];
function _createMdxContent(props) {
  const _components = Object.assign({
    h1: "h1",
    a: "a",
    p: "p",
    code: "code",
    pre: "pre",
    span: "span",
    em: "em",
    h2: "h2",
    ul: "ul",
    li: "li"
  }, props.components);
  return jsxs(Fragment, {
    children: [jsxs(_components.h1, {
      id: "ssr",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#ssr",
        children: "#"
      }), "SSR"]
    }), "\n", jsxs(_components.p, {
      children: ["Solid 通过将 JSX 模板编译为无比高效的字符串附加代码来处理服务器渲染。这可以通过传入 ", jsx(_components.code, {
        children: "generate: \"ssr\""
      }), " 到 babel 插件或者预设来实现。对于客户端和服务端而言，你都需要传入 ", jsx(_components.code, {
        children: "hydratable: true"
      }), " 来生成注水兼容代码。"]
    }), "\n", jsxs(_components.p, {
      children: ["在 node 环境中运行时，", jsx(_components.code, {
        children: "solid-js"
      }), " 和 ", jsx(_components.code, {
        children: "solid-js/web"
      }), " 运行时被置换为非响应式的对应。对于其他环境，你需要将导出条件设置为 ", jsx(_components.code, {
        children: "node"
      }), " 来打包服务端代码。大多数构建工具都有办法做到这一点。一般来说，我们还是建议使用 ", jsx(_components.code, {
        children: "solid"
      }), " 的导出条件，并建议库在", jsx(_components.code, {
        children: "solid"
      }), " 的导出条件下输出源代码。"]
    }), "\n", jsxs(_components.p, {
      children: ["构建 SSR 肯定需要更多配置，因为我们需要生成 2 个单独的包。客户端入口应该使用 ", jsx(_components.code, {
        children: "hydrate"
      }), "："]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { hydrate } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "hydrate"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ", ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ");\n"]
      })
    }), "\n", jsx(_components.p, {
      children: jsx(_components.em, {
        children: "注意：可以从文档根节点进行渲染和注水。这允许我们在 JSX 中描述完整的视图。"
      })
    }), "\n", jsx(_components.p, {
      children: "服务器入口可以使用 Solid 提供的四个渲染函数之一。每个都会输出对应产物或者是一个要插入到文档头部的脚本标签。"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " {\n  renderToString,\n  renderToStringAsync,\n  renderToStream\n} ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-comment",
          children: "// 同步渲染字符串"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " html = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "renderToString"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ");\n\n", jsx(_components.span, {
          className: "hljs-comment",
          children: "// 异步渲染字符串"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " html = ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "await"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "renderToStringAsync"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ");\n\n", jsx(_components.span, {
          className: "hljs-comment",
          children: "// 渲染到 Stream"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " stream = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "renderToStream"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ");\n\n", jsx(_components.span, {
          className: "hljs-comment",
          children: "// Node"
        }), "\nstream.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "pipe"
        }), "(res);\n\n", jsx(_components.span, {
          className: "hljs-comment",
          children: "// Web streams (for like Cloudflare Workers)"
        }), "\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " { readable, writable } = ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "TransformStream"
        }), "();\nstream.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "pipeTo"
        }), "(writable);\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["为方便起见，", jsx(_components.code, {
        children: "solid-js/web"
      }), " 导出了一个十分有用的 ", jsx(_components.code, {
        children: "isServer"
      }), " 标志。这样大多数打包工具将能够在此标志下对任意代码进行的 treeshake 操作，或者仅在此标志下使用浏览器端之外的代码。"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { isServer } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "if"
        }), " (isServer) {\n  ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// 仅在服务端执行此操作"
        }), "\n} ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "else"
        }), " {\n  ", jsx(_components.span, {
          className: "hljs-comment",
          children: "// 仅在浏览器上执行此操作"
        }), "\n}\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "注水脚本",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#注水脚本",
        children: "#"
      }), "注水脚本"]
    }), "\n", jsxs(_components.p, {
      children: ["甚至为了在 Solid 运行时加载之前渐进式注水，需要在页面上插入一个特殊的脚本。这个脚本可以通过 ", jsx(_components.code, {
        children: "generateHydrationScript"
      }), " 生成和插入，也可以使用 ", jsx(_components.code, {
        children: "<HydrationScript />"
      }), " JSX 标签。"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { generateHydrationScript } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " app = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "renderToString"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ");\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " html = ", jsxs(_components.span, {
          className: "hljs-string",
          children: ["`\n  <html lang=\"en\">\n    <head>\n      <title>🔥 Solid SSR 🔥</title>\n      <meta charset=\"UTF-8\" />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n      <link rel=\"stylesheet\" href=\"/styles.css\" />\n      ", jsx(_components.span, {
            className: "hljs-subst",
            children: "${generateHydrationScript()}"
          }), "\n    </head>\n    <body>", jsx(_components.span, {
            className: "hljs-subst",
            children: "${app}"
          }), "</body>\n  </html>\n`"]
        }), ";\n"]
      })
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "HydrationScript"
        }), " } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "App"
        }), " = (", jsx(_components.span, {
          className: "hljs-params"
        }), ") => {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " (\n    ", jsxs(_components.span, {
          className: "xml",
          children: [jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "html"
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "lang"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"en\""
            }), ">"]
          }), "\n      ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "head"
            }), ">"]
          }), "\n        ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "title"
            }), ">"]
          }), "🔥 Solid SSR 🔥", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "title"
            }), ">"]
          }), "\n        ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "meta"
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "charset"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"UTF-8\""
            }), " />"]
          }), "\n        ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "meta"
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "name"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"viewport\""
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "content"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"width=device-width, initial-scale=1.0\""
            }), " />"]
          }), "\n        ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "link"
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "rel"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"stylesheet\""
            }), " ", jsx(_components.span, {
              className: "hljs-attr",
              children: "href"
            }), "=", jsx(_components.span, {
              className: "hljs-string",
              children: "\"/styles.css\""
            }), " />"]
          }), "\n        ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "HydrationScript"
            }), " />"]
          }), "\n      ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "head"
            }), ">"]
          }), "\n      ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "body"
            }), ">"]
          }), "{/*... App 其他部分*/}", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "body"
            }), ">"]
          }), "\n    ", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "html"
            }), ">"]
          })]
        }), "\n  );\n};\n"]
      })
    }), "\n", jsxs(_components.p, {
      children: ["当从文档中补水时，插入在客户端运行中不可用的资源也可能会在不在 ", jsx(_components.code, {
        children: "<head>"
      }), " 标签下时搞砸。Solid 提供了一个 ", jsx(_components.code, {
        children: "<NoHydration>"
      }), " 组件，其子组件将在服务器上正常工作，但不能在浏览器中进行水合。"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: ["<", jsx(_components.span, {
          className: "hljs-title class_",
          children: "NoHydration"
        }), ">\n  ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "ImNotHydrated"
            }), " />"]
          })
        }), "\n</", jsx(_components.span, {
          className: "hljs-title class_",
          children: "NoHydration"
        }), ">\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "异步和流式-ssr",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#异步和流式-ssr",
        children: "#"
      }), "异步和流式 SSR"]
    }), "\n", jsx(_components.p, {
      children: "异步和流式服务端渲染机制建立在 Solid 对应用如何工作的了解之上。它通过在服务器上使用 Suspense 和 Resource API 来实现，而不是提前获取然后渲染。Solid 获取资源数据在服务器上行为，就像在客户端上一样。代码的编写方式和执行模式完全相同。"
    }), "\n", jsx(_components.p, {
      children: "异步渲染会等到所有 Suspense 边界解析后发送结果（或在静态站点生成的情况下将它们写入文件）。"
    }), "\n", jsx(_components.p, {
      children: "一旦服务器将流同步地将内容刷新到浏览器，那么浏览器会即时展示你的 Suspense 回退。然后当异步数据在服务器上完成时，它通过相同的流将数据发送到客户端以完成 Suspense，浏览器完成工作并用真实内容替换回退。"
    }), "\n", jsx(_components.p, {
      children: "这种方法的优点："
    }), "\n", jsxs(_components.ul, {
      children: ["\n", jsx(_components.li, {
        children: "服务器不必等待异步数据响应。资源可以更快地开始在浏览器中加载，并且用户能够更快地看到内容。"
      }), "\n", jsx(_components.li, {
        children: "与 JAMStack 之类的客户端获取方案相比，这种方案的数据加载在服务器上即时开始，无需等待客户端 JavaScript 进行加载。"
      }), "\n", jsx(_components.li, {
        children: "所有数据都被序列化并自动从服务器传输到客户端。"
      }), "\n"]
    }), "\n", jsxs(_components.h2, {
      id: "ssr-注意事项",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#ssr-注意事项",
        children: "#"
      }), "SSR 注意事项"]
    }), "\n", jsx(_components.p, {
      children: "Solid 的 SSR 同构解决方案非常强大，因为你可以将代码编写一份代码就差不多可以在在两种环境中运行。然而，有人期望这会增加注水功能。大多数情况下，客户端中渲染的视图与服务器上渲染的视图大体相同。精确到文本可能不同，但在结构上标记应该是相同的。"
    }), "\n", jsx(_components.p, {
      children: "我们使用在服务端中渲染的标记来匹配客户端的元素和资源位置。为此，客户端和服务器应该具有相同的组件。鉴于 Solid 在客户端和服务器上以相同的方式渲染，这根本不是问题。但是目前没有办法在服务器上渲染不会在客户端注水的东西。也没有办法对整个页面进行部分注水，也无法为其生成注水标记。要么全有要么全无。部分注水是我们未来想要探索的东西。"
    }), "\n", jsxs(_components.p, {
      children: ["最后，所有资源都需要在 ", jsx(_components.code, {
        children: "render"
      }), " 树下定义。它们会自动序列化并在浏览器中提取，这样起作用是因为 ", jsx(_components.code, {
        children: "render"
      }), " 或 ", jsx(_components.code, {
        children: "pipeTo"
      }), " 方法会跟踪渲染的进度。如果它们是在独立的上下文中创建的，我们就无法做到跟踪。同理可得，服务器上没有响应性，因此不要在初始渲染时更新 signal，并期望它们传递到树的上层。虽然我们有 Suspense 边界，但 Solid 的 SSR 基本是自上而下的。"]
    }), "\n", jsxs(_components.h2, {
      id: "ssr-入门",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#ssr-入门",
        children: "#"
      }), "SSR 入门"]
    }), "\n", jsxs(_components.p, {
      children: ["SSR 配置很棘手。我们准备了几个示例包 ", jsx(_components.a, {
        href: "https://github.com/solidjs/solid/blob/main/packages/solid-ssr",
        children: "solid-ssr"
      }), " 。与此同时，一个新的脚手架工具正在开发中 ", jsx(_components.a, {
        href: "https://github.com/solidjs/solid-start",
        children: "SolidStart"
      }), " 旨在使开发更加流畅。"]
    }), "\n", jsxs(_components.h2, {
      id: "静态站点生成入门",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#静态站点生成入门",
        children: "#"
      }), "静态站点生成入门"]
    }), "\n", jsxs(_components.p, {
      children: [jsx(_components.a, {
        href: "https://github.com/solidjs/solid/blob/main/packages/solid-ssr",
        children: "solid-ssr"
      }), " 还附带一个用于生成静态或预渲染站点实用工具。阅读 README 文件了解更多信息。"]
    })]
  });
}
function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? jsx(MDXLayout, Object.assign({}, props, {
    children: jsx(_createMdxContent, props)
  })) : _createMdxContent(props);
}

export { MDXContent as default, toc };
//# sourceMappingURL=server-f3dbdf31.js.map
