prerender-spa-plugin icon indicating copy to clipboard operation
prerender-spa-plugin copied to clipboard

Unable to prerender all routes!

Open JaceHensley opened this issue 7 years ago • 19 comments

I'm getting this error randomly during my deploy build, I'm not sure why it's doing this and can't reproduce locally. And if I rebuild it works.

The main problem is that this is not stopping the build, it seems to exit with 0 and lets the build continue.

[prerender-spa-plugin] Unable to prerender all routes!
(node:2685) UnhandledPromiseRejectionWarning: Error: Navigation Timeout Exceeded: 30000ms exceeded
    at Promise.then (/tmp/build_ec0aa5ea47759615bf77e08801798d3c/node_modules/puppeteer/lib/NavigatorWatcher.js:73:21)
    at <anonymous>
(node:2685) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:2685) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

JaceHensley avatar Jul 23 '18 01:07 JaceHensley

@JaceHensley How many routes are you rendering at once? Have you tried limiting maxConcurrentRoutes?

JoshTheDerf avatar Jul 23 '18 01:07 JoshTheDerf

I'd say a little over a dozen. I'll check that flag out thanks!

JaceHensley avatar Jul 23 '18 01:07 JaceHensley

I am also facing the same issue. My stack is build with VueJs and is up in AWS. I have a CICD system in place which does the build and its currently throwing this error -

I have tried several combination of configurations and none of them have worked so far.

new PrerenderSPAPlugin({
      staticDir: config.build.assetsRoot,
      routes: config.build.prerenderRoutes,
      renderer: new PrerenderSPAPlugin.PuppeteerRenderer({
        timeout: 60000,
        renderAfterTime: 10000,
        maxConcurrentRoutes: 1
      })
    }),
(node:137) UnhandledPromiseRejectionWarning: Error: Navigation Timeout Exceeded: 30000ms exceeded
    at Promise.then (/codebuild/output/src455438129/src/node_modules/puppeteer/lib/NavigatorWatcher.js:73:21)
    at <anonymous>
(node:137) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:137) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@Tribex any idea how we can mitigate this issue?

Strangely enough the error still says Exceeded: 30000ms although I have used timeout: 60000

sohailalam2 avatar Jul 31 '18 14:07 sohailalam2

Now that is odd. Have you tried with headless: false to see what's going on when the page actually loads?

JoshTheDerf avatar Aug 02 '18 00:08 JoshTheDerf

+1 - I'm also experiencing the same issue. Seemingly more frequent when you're on a lower latency network like a CI environment the connections / resource can be slower than your local machine.

In the event there is enough pages for the total timeout to be hit puppeteer will throw a timeout assuming the network has timed out.

Looking into this a bit further. Puppeteer released an update a few days ago that to my naked eye looks like it will cause timeout to always default to 30000.

https://github.com/GoogleChrome/puppeteer/blame/25632133e2683c613c97d9088968c48e3c07a086/lib/Launcher.js#L153

Palgie avatar Aug 03 '18 14:08 Palgie

The preprender dependency of this package has an issue identified by one of our team, they'll submit a PR to patch.

Palgie avatar Aug 03 '18 15:08 Palgie

@Palgie I'll be happy to take a look once you have the details. Thanks for looking into it!

JoshTheDerf avatar Aug 03 '18 18:08 JoshTheDerf

Well, @Tribex this is solved for me... apparently one of the pages had an infinite loop which was causing the rendering to fail. Now its resolved. Thanks

sohailalam2 avatar Aug 05 '18 09:08 sohailalam2

I am having this same issue.... it does seem to matter the number of routes because I have commented out different routes to see and individually they all successfully pre-render... even in groups of 6 they all pre-render. However once I try to pre-render all 30 routes I get the same error above.

cbravo avatar Aug 08 '18 21:08 cbravo

@cbravo Try setting maxConcurrentRoutes to 6 and see if that helps.

JoshTheDerf avatar Aug 08 '18 23:08 JoshTheDerf

even at maxConcurrentRoutes 1 it still failed once or twice..... this makes it unreliable? Is this just caused by the bug in puppeteer where the default 30000ms time out cannot be changed?

cbravo avatar Aug 09 '18 17:08 cbravo

@cbravo Odd. Honestly have no idea what your issue is. My guess is that it's either something going wrong on your page, or puppeteer being buggy.

JoshTheDerf avatar Aug 09 '18 21:08 JoshTheDerf

@Tribex side question... is the unhandled promise rejection an issue with puppeteer? It should be failing and exiting the node process correct? or is this something that could be fixed within this plugin? This is an issue for me because I am trying to integrate this prerender plugin and the build is continuing as if nothing went wrong even if the plugin is unable to prerender all routes as shown in the image below

image

cbravo avatar Aug 10 '18 21:08 cbravo

@cbravo Quite possibly.

JoshTheDerf avatar Aug 11 '18 00:08 JoshTheDerf

@tribex @Palgie @sohailalam2 I have been digging into the timeout issue some more and I have found that the reason why we get this timeout error of 30000ms even though we are setting a timeout is that the timeout param we are using is for launching of puppeteer and the timeout we are experiencing is on navigation. it would be helpful for us to have the ability to not only pass launch parameters to puppeteer but also to pass the navigation timeout param (and other params too i suppose) to this line of code in your puppeteer renderer code (link):

await page.goto(`${baseURL}${route}`, { waituntil: 'networkidle0' })

Would you accept a PR if i were to create one? Perhaps the parameters inside of webpack could be shaped like this:

renderer: new Renderer({
  timeout: 0,
  maxConcurrentRoutes: 6
  navigationParams: {
    timeout: 0
  }
})

and then the page.goto call would change to do an object assign to merge those params in. Thoughts?

As for why my page occasionally does not navigate within the default 30000ms is a different issue entirely which I am still digging into. Any tips on how to debug that would be greatly appreciated!

cbravo avatar Aug 13 '18 16:08 cbravo

Sure, I'd love a PR!

On Mon, Aug 13, 2018, 12:03 PM Camilo Bravo [email protected] wrote:

@Tribex https://github.com/Tribex I have been digging into the timeout issue some more and I have found that it would be helpful for us to have the ability to not only pass launch parameters to puppeteer but also to pass the navigation timeout param (and other params too i suppose) to this line of code https://github.com/Tribex/prerenderer/blob/master/renderers/renderer-puppeteer/es6/renderer.js#L112 in your puppeteer renderer code. Would you accept a PR if i were to create one? Perhaps the parameters inside of webpack could be shaped like this:

renderer: new Renderer({ launch: { timeout: 0, maxConcurrentRoutes: 6 }, navigation: { timeout: 0 } })

As for why my page occasionally does not navigate within the default 30000ms is a different issue entirely which I am still digging into

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/chrisvfritz/prerender-spa-plugin/issues/222#issuecomment-412570679, or mute the thread https://github.com/notifications/unsubscribe-auth/AFlv-9Eab74y6PNDMZHKtWHuow2jBZ6uks5uQaNOgaJpZM4VaPCO .

-- Web Developer & IT Professional *Creation Ministries International *(US) https://creation.com/ Phone: (770) 630-6154

JoshTheDerf avatar Aug 13 '18 19:08 JoshTheDerf

here you go @Tribex! let me know any changes that are needed https://github.com/Tribex/prerenderer/pull/16

cbravo avatar Aug 14 '18 00:08 cbravo

Firstly I use "prerender-spa-plugin": "^3.4.0", to solve this issue(Unable to prerender all routes), set 'headless' true or delete it.

configureWebpack: {
    plugins: [
      new PrerenderSPAPlugin({
        // The path to generate the file can also be consistent with the webpakc package.
        // This directory can only have one level, if the directory level is higher than one level, there will be no error prompt when it is generated, and it will only stick when it is pre-rendered.
        staticDir: path.join(__dirname,'dist'),
        // If you have parameters for your own routing file, such as about, you need to write / about/param1.
        routes: ['/a','/b'],
        // You have to configure or you won't precompile
        renderer: new Renderer({
            // ignoreJSErrors: true,
            // headless: false,
            // In main.js, document.dispatchEvent(new Event('render-event')) should correspond to the event name of both.
            renderAfterDocumentEvent: 'render-event',
            renderAfterTime: 5000
        })
      })
    ],

npm run build succeeds locally, but fails when deployed to the server. It is most likely related to the puppeteer used in prerender-spa-plugin 3.x. (Reference: https://qiita.com/pokotyan/items/11806b8b77f4a3527951) Because the configuration on the CI was not authorized to change, I discarded version 3. Later I used v2.1.0 which based on the PhantomJS and deployed successfully on the server.

vue-cli3 & "prerender-spa-plugin": "^2.1.0" vue.config.js

configureWebpack: {
    plugins: [
      new PrerenderSpaPlugin(
        // Absolute path to compiled SPA
        path.resolve(__dirname, './dist'),
        // List of routes to prerender
        ['/a', '/b', '/c', '/d', '/e'],
        {
          // options
          ignoreJSErrors: true,
        }
      )
    ],
}

SageSanyue avatar Mar 30 '21 10:03 SageSanyue

I am using a React App with the puppeteer renderer

Got the same Issue. [prerender-spa-plugin] Unable to prerender all routes!

Then I looked up where the issue is thrown:

  .catch(err => {
        PrerendererInstance.destroy()
        const msg = '[prerender-spa-plugin] Unable to prerender all routes!'
        console.error(msg)
        compilation.errors.push(new Error(msg))
        done()
      })

In the debugger, I caught the Error.

error:

name:'TimeoutError'
message:'Navigation Timeout Exceeded: 30000ms exceeded'

stack:

TimeoutError: Navigation Timeout Exceeded: 30000ms exceeded
    at C:\Users\ruper\Documents\Code\TypeScript\ru4ert\functions\app\node_modules\puppeteer\lib\LifecycleWatcher.js:142:21
  -- ASYNC --
    at Frame.<anonymous> (C:\Users\ruper\Documents\Code\TypeScript\ru4ert\functions\app\node_modules\puppeteer\lib\helper.js:111:15)
    at Page.goto (C:\Users\ruper\Documents\Code\TypeScript\ru4ert\functions\app\node_modules\puppeteer\lib\Page.js:674:49)
    at Page.<anonymous> (C:\Users\ruper\Documents\Code\TypeScript\ru4ert\functions\app\node_modules\puppeteer\lib\helper.js:112:23)
    at C:\Users\ruper\Documents\Code\TypeScript\ru4ert\functions\app\node_modules\@prerenderer\renderer-puppeteer\es6\renderer.js:113:24
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Promise.all (index 0)

Then I dissabeld the headless mode:

  const renderer = new Renderer({   
        headless: false,
      })

headless: false means that a browser window get's opend.

It turns out, that I changed the PUBLIC_URL property of react. So locally a server is hosted on 127.0.0.1 but tries to fetch from the public domain.

ru4ert avatar Jan 04 '22 05:01 ru4ert