Skip to content

00预渲染

Prerender SPA Plugin

预渲染技术 https://github.com/chrisvfritz/prerender-spa-plugin

一个灵活的静态网站构建框架,让你更好地使用webpack为SPA应用打包

什么是预渲染??

服务端渲染在前端界变得越来越主流。在将网页或应用程序发送给客户之前,在服务器就先呈现了我们想展示的内容。这是一个革命性的想法。

然而,对于PHP、ASP、JSP(以及这样的)站点来说,同样的批评对于今天的服务器端呈现是有效的。它很慢,很容易被打破,并且很难正确地实现。问题是,尽管每个人可能会告诉你,你可能不需要SSR。您可以通过使用预先设定来获得几乎所有的优点(没有缺点)。

预渲染的原理是启动一个无头浏览器(如puperteer),加载应用程序的路由,并将结果保存到静态HTML文件中。然后,可使用以前使用的静态文件-文件服务解决方案来服务它。它只适用于HTML5导航和类似的东西。不需要更改代码或添加服务器端渲染工作区。


使用场景 改善少数营销页面,广告页等的SEO,预渲染就能起到很好的效果.

当然,我们也要承认,在某些场景下,预渲染并不是特别适合:

  • 大量的网页和跳转 使用预渲染会很慢,虽然这种场景并没那么多,但不代表不会出现
  • 动态内容 如果网页中有大量的动态内容,Ajax这类,应确保有占位符组件,直到动态内容加载完后才显示出来,否则页面闪动和重绘的开销会得不偿失

关于 About prerender-spa-plugin

3.x 版本是基于puppeteer的稳定版本。

该插件的目标是提供一个简单、可扩展的预渲染解决方案,可以用于任何网站或用webpack构建的单页面应用。

当然,前提是其他任务是已构建好并可运行的

Examples 示例

特定框架例子 可以在源码中找到

Basic Usage

基础用法 webpack.config.js

js
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')

module.exports = {
  plugins: [
    // 省略其他配置
    new PrerenderSPAPlugin({
      // 必填,填写output打包出来的路径
      staticDir: path.join(__dirname, 'dist'),
      // 必填,需要预渲染的路由
      routes: ['/', '/about', '/some/deep/nested/route']
    })
  ]
}

Advanced Usage

高级用法 webpack.config.js

js
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

module.exports = {
  plugins: [
    new PrerenderSPAPlugin({
      staticDir: path.join(__dirname, 'dist'),
      // 可选, 预渲染应该输出到的路径
      outputDir: path.join(__dirname, 'prerendered'),
      // 可选,根文档的路径
      indexPath: path.join(__dirname, 'dist', 'index.html'),
      routes: ['/', '/about', '/some/deep/nested/route'],

      // 可选 在写入渲染内容到文件之前 允许配置 html和输出路径
      // 可以修改渲染, 也可等待返回。 以下是renderedRoute 的格式:
      // {
      //   route: String, // 输出文件将在何处结束(相对于outputDir)
      //   originalRoute: String, // 在重定向之前,传递给渲染器的路由。.
      //   html: String // 该路由渲染的html
      // }
      postProcess(renderedRoute) {
        // 忽略任何重定向
        renderedRoute.path = renderedRoute.originalPath
        // 删除空格. (建议别在生产环境中用)
        renderedRoute.html = renderedRoute.html.split(/>[\s]+</gmi).join('><')
        // 返回renderedRoute, 其实就是对 传入的 对象进行了一次处理,返回的还是该对象
        return renderedRoute
      },

      // 可选,使用 html-minifier  它会压缩html, 更多参考官方
      minify: {
        collapseBooleanAttributes: true,
        collapseWhitespace: true,
        decodeEntities: true,
        keepClosingSlash: true,
        sortAttributes: true
      },

      // 服务端配置选项
      server: {
        // 端口是自动检测的
        port: 8001
      },

      // 渲染器 Renderer的实例,可自行编写
      renderer: new Renderer({
        // 注入到window对象 kv对   window.__PRERENDER_INJECTED 就可以访问到了
        injectProperty: '__PRERENDER_INJECTED',
        // 可选,可配置想通过 window 对象注入的可访问值
        inject: {
          foo: 'bar'
        },
        // 默认为 0 没有限制 
        // 由于路由是异步加载的,用该属性限制路由的数量
        maxConcurrentRoutes: 4,

        // ... 更多的看文档吧
      })
    })
  ]
}

可用的渲染器

  • @prerenderer/renderer-puppeteer 已经预先准备好了几百页,并希望得到准确的结果 那就是用它吧
  • @prerenderer/renderer-jsdom 你需要提前阅读成千上万页的内容,但是质量并不是那么重要,你愿意为更高级的案例解决问题

其他

  • JS 在 prerender前不运行

如果您的代码依赖于“body”的存在,那么只需在domcontent重载事件的回调中运行它:(否则会发现在JS运行之前,预编译-spa-plugin将输出页面的内容)

document.addEventListener('DOMContentLoaded', function() {})

如果使用 Vue,将 <div id="root"> mounting 到 body标签上:

js
const app = new Vue({ /**/ })

document.addEventListener('DOMContentLoaded', function() {
  app.$mount('#root')
})

Inline styles 内联样式

如果您依赖于内联CSS,也就是说,您不会从捆绑包中提取CSS,因此,体验重复的CSS样式标签,可以考虑使用 extract-text-webpack-plugin 将CSS提取到单独的文件中。然后将CSS注入到模板中。使用 html-webpack-plugin 的html文件,或者将其称为外部CSS文件。

无论哪种方式,JS中都不会有任何不必要的样式。

警告

  • 出于显而易见的原因,预安装-spa-插件只适用于使用HTML5历史API的spa。索引。不幸的是,html/hash/路由url将无法工作

  • vue2+ 确保你的根组件与它所替换的预先设计的元素具有相同的id。否则,您将得到重复的内容

共 20 个模块,1301 篇 Markdown 文档。