chrisvfritz / prerender-spa-plugin

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

Is there any way to support reCaptcha ? #70

Closed desirelabs closed 7 years ago

desirelabs commented 7 years ago

Hi, I'm using google recaptcha on my spa. But the prerender makes it useless and not working at all. I used vue-recaptcha, but the recaptcha returns a 400 error. This is only happening when prerendering pages, not without.

drewlustro commented 7 years ago

The Problem

vue-recaptcha does not work because it relies on immediately executing window.vueRecaptchaApiLoaded upon page load, which is undefined on pages that prerender-spa-plugin generates.


Why

From the vue-recaptcha README, the author instructs you to include the Google ReCaptcha API JS like so between your <head> tags:

<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
</script>

Since this is in your main index.html file, it will be at the head of every file prerendered by this plugin. When prerender-spa-plugin tries to render each page, this script loads, executes quickly and throws an exception because there is no callback defined as window.vueRecaptchaApiLoaded.

Looking at the vue-recaptcha source code, we see the author hard codes this reference:

  window.vueRecaptchaApiLoaded = function () {
    recaptcha.setRecaptcha(window.grecaptcha);
  };

source code

Thus, Google's ReCaptcha API Javasript callback has a dependency on window.vueRecaptchaApiLoaded.


Possible Solution

Try to inject the ReCapcha API Javascript programmatically after Vue.js has completely mounted().

I haven't tested this, but it could look something like this:

<script>
  import backToTop from './components/Backtotop'
  import Heading from './components/Heading'
  import Foot from './components/Foot'
  import Loader from './components/Loader'
  export default {
    name: 'app',
    components: { backToTop, Foot, Loader, Heading },
    data () {
      return {
        loader: true
      }
    },
    mounted () {
      this.loader = false

       /* PROGRAMMATICALLY INJECT JS HERE */
      var recaptchaJs = document.createElement('script');
      recaptchaJs.setAttribute('src','https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit');
      document.head.appendChild(recaptchaJs);

    }
  }
</script>

An exception being thrown can be the source of broken transitions. Thus, your use of ReCaptcha is likely related to #69 .

drewlustro commented 7 years ago

Closing this due to no response by original author. Create another Issue if your problem persists!

;)

mrto1 commented 4 years ago

There is also an issue of prerender-spa-plugin with vue-programmatic-invisible-google-recaptcha: "Error: reCAPTCHA has already been rendered in this element". :( The possible solution above didn't help.