• prerender-spa-plugin报错处理,prerender-spa-plugin-next长江后浪


    前言

    由于业务需求需要用到预渲染,vite+vue3没有找到好的库。

    考虑使用prerender-spa-plugin这个插件满足需求。

    以下是我的配置信息。

    const PrerenderSpaPlugin = require("prerender-spa-plugin");
    const Renderer = PrerenderSpaPlugin.PuppeteerRenderer
    const path = require("path");
    
    module.exports = {
    configureWebpack: config => {
    if (process.env.NODE_ENV !== "production") return;
        return {
            plugins: [
                new PrerenderSpaPlugin({
                    staticDir: path.join(__dirname, 'dist'),
                    routes: ['/', '/home', '/test', '/about'],
                    renderer: new Renderer({
                        timeout: 0,
                        maxConcurrentRoutes: 1,
                        renderAfterTime: 5000,
                        headless: false
                    })
    
                }),
            ]
        };
    }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    使用过程中诸多报错,但后续都以解决。

    最终卡在这个条报错信息上。

    Unable to prerender all routes!

    在这里插入图片描述

    查阅国内外论坛,查找到了了诸多解决方案。

    方案一:修改源码

    // node_modules/@prerenderer/renderer-puppeteer/es6/renderer.js
    const navigationOptions = (options.navigationOptions) ? { waituntil: 'networkidle0', ...options.navigationOptions } : { waituntil: 'networkidle0' };
    
    await page.goto(`${baseURL}${route}`, navigationOptions); // navigationOptions -> { waituntil: 'networkidle0'}
    
    • 1
    • 2
    • 3
    • 4

    在\node_modules@prerenderer\renderer-puppeteer\es6\renderer.js中第113行

    await page.goto(`${baseURL}${route}`, navigationOptions);
    
    • 1

    改为:

     await page.goto(`${baseURL}${route}`, {...navigationOptions, timeout:0} );
    //或者 await page.goto(`${baseURL}${route}`, { waitUntil: 'domcontentloaded' });
    
    • 1
    • 2

    方案二:prerender-spa-plugin-next

    在找到prerender-spa-plugin-next之前,我一直在处理相同的错误输出。然后我注意到最新版本的prerender-spa-plugin是 4 年前发布的,并且 prerender-spa-plugin-next 正在不断更新。看起来 prerender-spa-plugin-nextprerender-spa-plugin 的新版本,具有相同的功能。所以我使用 prerender-spa-plugin-next 而不是 prerender-spa-plugin 然后一切正常!

    vue.config.js

    这里附上配置信息

    // 预渲染插件
    const PrerenderSPAPlugin = require("prerender-spa-plugin-next");
    // 可选
    const renderer = require("@prerenderer/renderer-puppeteer");  
    
    //configureWebpack
    configureWebpack: (config) => {
        if (process.env.NODE_ENV === "production") {
          // 为生产环境修改配置...
          config.mode = "production";
          config.performance = {
            //打包文件大小配置
            maxEntrypointSize: 10000000,
            maxAssetSize: 30000000,
          };
          // 移除console及注释
          config.plugins.push(
            new UglifyJsPlugin({
              uglifyOptions: {
                output: {
                  comments: false, // 去掉注释
                },
                warnings: false,
                compress: {
                  drop_console: true,
                  drop_debugger: false,
                  pure_funcs: ["console.log"], //移除console
                },
              },
              sourceMap: false,
              parallel: true,
            }),
            // new CompressionPlugin({
            //   test: /\.(js|css|html)?$/i, // 压缩文件格式
            //   //   filename: "[path].gz[query]",
            //   filename: "[path][base].gz", // 设置成这样就行了// 压缩后的文件名
            //   algorithm: "gzip", // 使用gzip压缩
            //   // 只有大小大于该值的资源会被处理。单位是 bytes。默认值是 0。
            //   // threshold: 10240,
            //   minRatio: 0.8, // 压缩率小于1才会压缩
            //   deleteOriginalAssets: true, // 是否删除原资源
            // }),
            new PrerenderSPAPlugin({
              routes: ["/", "/about"],
              rendererOptions: {
                // headless: false,
                renderAfterDocumentEvent: "render-event",
                inject: {},
                timeout: 10000,
              },
              // 可选
              renderer,
              //   postProcess(context) {
              //     context.outputPath = path.join(
              //       // 不要拼__dirname,最终会转成绝对路径,拼了反而出错。
              //       // PS: 为什么要加一层文件夹? 因为默认写入首页叫index.html, 不加会导致写入冲突 ——_——#
              //       "rerender",
              //       (context.route.replace("/", "") || "index") + ".html"
              //     );
              //     return context;
              //   },
              postProcess: function (context) {
                var titles = {
                  "/": "Home",
                  "/about": "Our Story",
                  "/contact": "Contact Us",
                };
                context.html = context.html.replace(
                  /[^<]*<\/title></span><span class="token regex-delimiter">/</span><span class="token regex-flags">i</span></span><span class="token punctuation">,</span>
                  <span class="token string">"<title>"</span> <span class="token operator">+</span> titles<span class="token punctuation">[</span>context<span class="token punctuation">.</span>route<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">""
                );
              },
              renderOptions: {
                renderAfterDocumentEvent: "prerender",
              },
            })
          );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    打包后的效果图

    在这里插入图片描述

    方案三:vite+**vitesse**使用SSR渲染完成SEO

    考虑稳定性,以及已经踩过坑的的游戏玩家数,最终采用了第二方案解决的项目中的痛点。

  • 相关阅读:
    JavaWeb_第6章_Filter&Listener&Ajax
    【线程中断】什么是中断、interrupt、isInterrupted、interrupted⽅法源码解析、如何使⽤中断标识停⽌线程_JUC18
    【我的渲染技术进阶之旅】让我们一起来了解一下什么是glTF?为什么glTF是3D世界的JPEG?
    谐云课堂 | 一文详解分布式改造理论与实战
    cs与msf联动
    设计模式——组合模式(Composite Pattern)+ Spring相关源码
    TS+Hooks二次封装antd Modal,实现可拖拽
    Java文件为什么可以跨平台执行
    lambda 自定义收集器
    Transformer
  • 原文地址:https://blog.csdn.net/RequesToGod/article/details/126268457