zoukankan      html  css  js  c++  java
  • vue预渲染实践总结

    # 预渲染

    ## 预渲染简介

    SEO和首屏加载速度慢的问题,社区讨论最多的解决方案是同构 SSR,即首屏使用服务端渲染,之后的交互逻辑交给客户端处理,解决了单页应用带来的两个问题,但是也带来了服务器压力增大,学习成本高,对老项目入侵性过强等问题。

    ## 版本信息

    vue: 2.5.2

    webpack: 3.6.0

    vue-router: 3.0.1

    prerender-spa-plugin: 3.4.0


    ## 使用

    这里我们按照官方 github 的例子敲一下

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

    module.exports = {
    plugins: [
    ...
    new PrerenderSPAPlugin({
    // 这里选择文件生成目录.
    staticDir: path.join(__dirname, 'dist'),
    // 这里选择你要预加载的 router 路径,要与在 router 文件里面定义保持一致
    routes: [ '/login' ],
    })
    ]
    }


    还有一些注意事项,假设你的 vue 工程是 vue-cli 2-x 版本的

    在 `config/index.js` 里面 `build/assetsPublicPath` 的值为 '/', 这里不能使用相对路径了


    const path = require("path")
    
    module.exports = {
      build: {
        index: path.resolve(__dirname, "../base/index.html"),
        assetsRoot: path.resolve(__dirname, "../dist"),
        assetsSubDirectory: "static",
        assetsPublicPath: "/",
      }
    }

    还有个配置要注意下在`build/utils.js` 中的 `ExtractTextPlugin.extract` 的 `publicPath` ,否则一些vue中引用的资源会找不到

    ExtractTextPlugin.extract({
      use: loaders,
      fallback: 'vue-style-loader',
      // publicPath: '../../'
    })
    


    然后在 `router/index.js` 的配置,预渲染要求是 history 模式,如果不声明,则生成的页面都是同一个 html,

    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [...]
    })

    这个时候可以执行 `npm run build` 打包我们的项目了,一切正常的话,dist目录应该是这个样子的

    ├── index.html
    ├── login
    │   └── index.html
    └── static
    ├── css
    ├── fonts
    ├── images
    ├── img
    └── js

    看到 login 文件夹里面有 index.html,就代表你成功了,


    ## nginx 配置

    这里不需要对这个插件做特殊处理,但是需要对 history 路由做处理,这里贴一下我的ngnix.config配置

    server{
        listen          8000;
        server_name     localhost;
        root            /dist;
        error_page 500 502 503 504 /50x.html;
    
        location ~^/declaring/ {
            try_files $uri $uri/ /index.html;
        }
        location = /50x.html {
            root    /dist;
        }
    }
    

      

    到这里,重启 nginx, 应该就可以看到效果了

    ## 遇到的问题:

    **生成的 html 里面不是我们想要的页面 html,或者里面的css,js引用失效。**

    检查 `config/index` 里面的 `build/assetsPublicPath` 是不是根目录,

    检查 路由是否是 history 模式

    检查 `build/utils.js` 中的 `ExtractTextPlugin.extract` 的 `publicPath` 字段是否为空,


    **加载页面会有闪屏的效果**

    因为预加载是把当前页面,提到构建的时候加载,请求的时候,就会先加载html,然后加载 vue 实例,当 vue 加载好了,vue 会 render 并 push 到 #app 的 DOM 节点上,效果就是闪屏,而且如果页面是动态的,千人千面的,那么用户第一次看到的页面将会是你 build 时获取的数据,然后闪一下,vue 接管页面后正常渲染,

    这个问题,RRS也是遇到,vue 也提供了相应的解决方案,我们移植过来就可以解决了,想了解更详细的,请参考[客户端激活(client-side hydration)](https://ssr.vuejs.org/zh/guide/hydration.html)

    postProcess(context) {
       context.html = context.html.replace('id="app"', 'id="app" data-server-rendered="true"');
       return context;
     },
    

      


    下面是全部更改:
    // build/webpack.prod.conf.js
    ...
    const PrerenderSpaPlugin = require('prerender-spa-plugin')
    
    const Renderer = PrerenderSpaPlugin.PuppeteerRenderer
    ...
    plugins: [
    new PrerenderSpaPlugin({
      //   编译后html需要存放的路径
      staticDir: config.build.assetsRoot,
      outputDir: config.build.assetsRoot,
      indexPath: config.build.index,
      // 列出需要预渲染的路由
      routes: ['/', '/login'],
      postProcess(context) {
        context.html = context.html.replace('id="app"', 'id="app" data-server-rendered="true"');
        return context;
      },
      renderer: new Renderer({
        headless: false,
        renderAfterTime: 5000,
        // renderAfterDocumentEvent: 'render-event' // document.dispatchEvent(new Event('render-event'))
      })
    })
    ]
    
    
    // build/utils
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader',
        // publicPath: '../../'
      })
    }
    
    
    // router/indes.js
    let router = new Router({
        mode: 'history',
        routes: [...]
    })
    
    
    // config/index.js
    build: {
    ...
    assetsPublicPath: '/'
    }
    
    
    // nginx.conf
    
    server{
        listen          8000;
            server_name     localhost;
            root            /dist;
            error_page 500 502 503 504 /50x.html;
    
       location /api/ {
                #rewrite  ^/api/(.*)$ /$1 break;
                proxy_pass xxx.xxx.xxx;
            }
    
            location ~^/declaring/ {
                try_files $uri $uri/ /index.html;
            }
            location = /50x.html {
                root    /dist;
            }
    }


  • 相关阅读:
    SAP应用界面开发:1)SELECTOPTIONS对象
    ABAP工作区,内表,标题行的定义和区别
    Open SQL:6)Open SQL 增刪查改(CRUD)
    SAP应用界面开发:2)PARAMETERS对象
    Open SQL:5)Open SQL获取数据行数限制
    Open SQL:3)多个表数据连接查询
    Open SQL:4)参照内表条件进行查询
    Open SQL:7)动态WHERE条件内表
    SAP应用界面开发:3)SELECTIONSCREEN 对象(1)
    SAP应用界面开发:3)Text Elements(文本元素)对象
  • 原文地址:https://www.cnblogs.com/zifayin/p/9928906.html
Copyright © 2011-2022 走看看