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
                })

            }),
        ]
    };
}
};

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

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

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'}

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

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

改为:

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

方案二: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>[^<]*<\/title>/i,
              "<title>" + titles[context.route] + "</title>"
            );
          },
          renderOptions: {
            renderAfterDocumentEvent: "prerender",
          },
        })
      );
打包后的效果图

在这里插入图片描述

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

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

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
要将Vue项目改为使用prerender-spa-plugin,需要进行以下步骤: 1. 安装prerender-spa-plugin插件: ``` npm install prerender-spa-plugin --save-dev ``` 2. 在webpack配置文件中引入插件: ``` const PrerenderSPAPlugin = require('prerender-spa-plugin'); ``` 3. 在plugins数组中添加插件配置: ``` plugins: [ new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), routes: ['/', '/about', '/contact'], // 可选项,生成的文件存储的路径,默认为 `./prerendered` outputDir: path.join(__dirname, 'prerendered'), // 可选项,生成文件的后缀名,默认为 `.html` postProcess (renderedRoute) { // 对渲染后的路由文件进行额外处理 } }) ] ``` 4. 在`package.json`文件中添加一个脚本: ``` "scripts": { "prerender": "npm run build && node prerender.js" } ``` 5. 创建一个名为`prerender.js`的文件,并添加以下代码: ``` const path = require('path'); const PrerenderSPAPlugin = require('prerender-spa-plugin'); const rendererPath = path.join(__dirname, 'dist', 'server', 'bundle.js'); const renderer = require(rendererPath); const options = { staticDir: path.join(__dirname, 'dist'), routes: ['/'], renderer: new PrerenderSPAPlugin.PuppeteerRenderer({ renderAfterDocumentEvent: 'render-event', headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], }), }; const prerenderer = new PrerenderSPAPlugin(options); prerenderer .initialize() .then(() => { return prerenderer.renderRoutes(['/']); }) .then((renderedRoutes) => { console.log('Prerendering successful!'); console.log(renderedRoutes); }) .catch((error) => { console.error('Prerendering failed:'); console.error(error); }); ``` 6. 运行`npm run prerender`命令,生成预渲染文件。 以上就是将Vue项目改为使用prerender-spa-plugin的步骤。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值