chrisvfritz / prerender-spa-plugin

Prerenders static HTML in a single-page application.
MIT License
7.32k stars 633 forks source link

Uncaught ReferenceError: webpackJsonp is not defined #198

Open sohailalam2 opened 6 years ago

sohailalam2 commented 6 years ago

Duplicate of https://github.com/chrisvfritz/prerender-spa-plugin/issues/172

Reopening this as none of the solutions worked for me.

I get Uncaught ReferenceError: webpackJsonp is not defined when I put PrerenderSPAPlugin in the build pipeline. Without PrerenderSPAPlugin, the build works as expected without any issues.

I even tried the suggestion as mentioned in https://github.com/chrisvfritz/prerender-spa-plugin/tree/v2#code-splitting.

After implementing the above suggestion, everything stopped working. I got a blank page, without any errors in console. However, network tab shows that all assets get downloaded but the Vue app does not bootstrap for some unknown reason.

I also tried using https://github.com/chrisvfritz/prerender-spa-plugin/tree/v2#code-splitting without any success.

At this point, I dont know how to proceed with this. @kongjiea any idea how to debug or fix it?

FYI, I am using the Vue PWA template - https://github.com/vuejs-templates/pwa

MinjunYu commented 6 years ago

There is a work-around for this:

  1. Build the project for production
  2. open pre-rendered index.html
  3. find two js files in <head> tag and remove them. They look something like this:
    <script type="text/javascript" charset="utf-8" async="" src="/static/js/0.15dbd6cf48922b1acf35.js"></script>
    <script type="text/javascript" charset="utf-8" async="" src="/static/js/6.3cea7a56da899768d137.js"></script>
qiulang commented 6 years ago

I can't set inject: 'head' otherwise even without using prerender-spa-plugin I got a blank page.

My app needs users to login first so I change PrerenderSPAPlugin's router setting from

routes: ['/'] to routes: ['/','/login','index'], webpackJsonp error disapperaed but I got a blank page, same as @sohailalam2 mentioned.

network tab shows that all assets get downloaded but the Vue app does not bootstrap for some unknown reason

Then I replaced the generated index.html with /login/index.html and my app shows! But I had Uncaught ReferenceError: webpackJsonp is not defined error again, strangely this time that error seems not to affect the app at all, all the functions work fine. I then deleted 2 js tags from index.html as @MinjunYu said to remove the error.

Those 2 js files in my case is 0.xxx.js for vendor-async and the js for the login page. Even after I deleted them from login/index.html Chrome will still download them.

The problem I have now is the page after login didn't use the prerender page, the browser did not request for it, it still uses vue codes to render that page. But I guess if I further modify my vue-router codes I probably can make it work. I am still working on this.

BTW, I further changed routes: ['/','/login','index'], to just routes: ['/login','index'],, replaced the generated index.html with /login/index.html and got the same result.

@sohailalam2 @Tribex not sure if my situation can give you guys some hints about how to fix this problem.

JoshTheDerf commented 6 years ago

@qiulang Thanks for all the details! I'm a bit low on time at the moment, but I'll try to look into it at some point.

zhouweiming commented 6 years ago

I have the same problem.

  1. when use { inject: 'head' }, get blank page, no other errors, but prerender-spa-plugin is not in work ;
  2. when not use { inject: 'head' }, can show pages, but has two js files in head and get Uncaught ReferenceError: webpackJsonp is not defined

thanks for @MinjunYu suggestion, i fix it with postProcess option finally.

Here is my codes:

    new PrerenderSPAPlugin({
      // Required - The path to the webpack-outputted app to prerender.
      staticDir: path.join(__dirname, '../dist'),
      // Required - Routes to render.
      routes: [ '/', '/products', '/products/truck', '/profile', '/docs/api/detail' ],
      postProcess (renderedRoute) {
        renderedRoute.html = renderedRoute.html.replace(/(\<head\>.*?)(\<script.*?\<\/script\>){1,}(.*\<\/head\>)/g, '$1$3');
        return renderedRoute
      }
    })
484sha commented 6 years ago

@zhouweiming hello, I want to delete script with async not all script, how to do?

zhouweiming commented 6 years ago

@484sha

renderedRoute.html has all html , you can do it with postProcess

23hp commented 5 years ago

Same problem I meet while using react-boilerplate

rubenkuipers commented 5 years ago

@zhouweiming your regex does not seem to work, have you tested it?

zhouweiming commented 5 years ago

@kuiperr005

There is no problem with the regex, but you must change it to your project.

This is my final codes:

postProcess (renderedRoute) {
        if (renderedRoute.route.endsWith('.html')) {
          renderedRoute.outputPath = path.join(__dirname, '../dist', renderedRoute.route)
        }
        renderedRoute.html = renderedRoute.html.replace(/(\<head\>.*?)(\<script.*?\<\/script\>){1,}(.*\<\/head\>)/g, '$1$3');
        if (staticRoutes.indexOf(renderedRoute.route) === -1) {
          renderedRoute.html = renderedRoute.html.replace(/(\<section.*\<\/section\>)(.*)/gsi, '<div id=app></div>$2');
        } else {
          renderedRoute.html = renderedRoute.html.replace(/(\<section)(.*)/g, '$1 style="display:none !important" $2');
          renderedRoute.html = renderedRoute.html.replace(/(\<section.*\<\/section\>)(.*)/gsi, '<div id=app>$1</div>$2');
        }
        return renderedRoute
      },
Runtu4378 commented 5 years ago

@zhouweiming bro ,something miss in your code

const staticRoutes = ['/']

postProcess (renderedRoute) {
  if (renderedRoute.route.endsWith('.html')) {
    renderedRoute.outputPath = path.join(__dirname, '../dist', renderedRoute.route)
  }
  renderedRoute.html = renderedRoute.html.replace(/(\<head\>.*?)(\<script.*?\<\/script\>){1,}(.*\<\/head\>)/g, '$1$3');
  if (staticRoutes.indexOf(renderedRoute.route) === -1) {
    renderedRoute.html = renderedRoute.html.replace(/(\<section.*\<\/section\>)(.*)/gi, '<div id=app></div>$2');
  } else {
    renderedRoute.html = renderedRoute.html.replace(/(\<section)(.*)/g, '$1 style="display:none !important" $2');
    renderedRoute.html = renderedRoute.html.replace(/(\<section.*\<\/section\>)(.*)/gi, '<div id=app>$1</div>$2');
  }
  return renderedRoute
},

and your regex expression have an error flag s

lianwf commented 5 years ago

@zhouweiming How do you get what is inside renderedRoute.html ? I don't know how to use postProcess