prerenderer: renderAfterDocumentEvent does not get capture the event early enough

I currently have a vue / typescript project set up where I want to prerender two different routes:

// webpack.prod.conf.js

new PrerenderSpaPlugin({
        // Absolute path to compiled SPA
        staticDir: config.build.assetsRoot,
        // List of routes to prerender
        routes: [ '/', '/contact' ],

        renderer:  new PrerenderSpaPlugin.PuppeteerRenderer({
          renderAfterDocumentEvent: 'prerender-page-ready',
          injectProperty: '__PRERENDER_INJECTED',
          inject: {
            // Update src/window-shim.d.ts if you change this
            USER_ID: process.argv[2] || 'test-id',
            PRERENDER_PAGE_EVENT: 'prerender-page-ready'
          }
        })
      })

The app starts into the main App.vue component, which

  • loads data from an API asynchronously,
  • shows (with a v-if) the router-view when the call finishes,
  • and emits the event with name __PRERENDER_INJECTED.PRERENDER_PAGE_EVENT on document in the mounted hook of the components loaded by the router.

I have setup an eventlistener in the mounted hook of the App.vue, which works and logs the event when it comes in:

// App.vue

mounted() {
    console.log(PRERENDER_PAGE_EVENT);
    document.addEventListener(PRERENDER_PAGE_EVENT, (ev) => {console.log(ev)});
    axios.get(`${API_URL}/api/${ID}`)
      .then((res) => {
        this.title = res.data.title;
      })
      .catch(() => {
        this.title = 'An error occurred';
      });
  }

prerender-console

However, the prerenderer does not seem to take notice and the build hangs indefinitely. When I emit the event by hand from the devtools console, the respective tab closes and the correctly rendered version of the html is saved.

In the routed page components, changing the following:

  // Contact.vue

  mounted() {
    this.$nextTick(() => {
      document.dispatchEvent(new Event(PRERENDER_PAGE_EVENT));
    });
  }

To this:

  // Contact.vue

  mounted() {
    this.$nextTick(() => {
      setTimeout(() => {
        document.dispatchEvent(new Event(PRERENDER_PAGE_EVENT));
      }, 500);
    });
  }

Makes the build succeed, but feels very hacky.

Tested on Debian.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

@Tribex I copy pasted the code into prerenderer-puppeteer/es6 and it seems to work. Going to try with the npm version now. Don’t worry btw, your response has been great!