Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Head script is added multiple times on navigation #498

Closed
simonbrent opened this issue Dec 5, 2019 · 22 comments
Closed

Head script is added multiple times on navigation #498

simonbrent opened this issue Dec 5, 2019 · 22 comments

Comments

@simonbrent
Copy link

I am opening a new issue, since #381 is closed, but I am still finding that there is a problem.

Nuxt version

2.10.2

Vue-meta version

2.3.1

Reproduction link

https://github.com/simonbrent/nuxt-vue-meta-bug

Steps to reproduce

$ git@github.com:simonbrent/nuxt-vue-meta-bug.git
$ cd nuxt-vue-meta-bug
$ npm install
$ npx nuxt
  • Open the site in Chrome, with dev tools open to the navigation tab
  • Click on the link to "foo" - see that "head-script.js" is downloaded
  • Click on the link to "index"
  • Click on the link to "foo" - see that "head-script.js" is downloaded again

What is expected?

"head-script.js" is downloaded once, the first time you navigate to /foo

What is actually happening?

"head-script.js" is downloaded every time you navigate to /foo

@pimlie
Copy link
Collaborator

pimlie commented Dec 7, 2019

The behaviour you are describing is expected, page specific meta info is completely removed when you move away from that page. If its really downloaded again by your browser, you should make sure that head-script.js is cachable and/or maybe explicitly add a link prefetch for that file.

Please check the docs for once for a workaround

@pimlie pimlie added the question label Dec 7, 2019
@pimlie
Copy link
Collaborator

pimlie commented Dec 8, 2019

Wait, I only noticed now you are using vmid in your project as identifier. But as you are using Nuxt you should be using hid

@simonbrent
Copy link
Author

@pimlie I have updated the repo to use hid and once, so that the code is now:

    head: () => ({
      script: [{
        hid  : 'head-script',
        src  : '/head-script.js',
        once : true,
      }],
    }),

Neither change made any difference to the behaviour.
I have also tried using once with a stylesheet, as shown in the docs you linked to:

    head: () => ({
      script: [{
        hid  : 'head-script',
        src  : '/head-script.js',
        once : true,
      }],
      link: [{
        hid  : 'head-style',
        rel  : 'stylesheet',
        href : '/head-style.css',
        once : true,
      }],
    }),

This also did not have the effect that I expected. head-style.css sets the body background to red. Given the docs, I expected that the first time I navigated to /foo, the body background would change to red, and stay that way on all subsequent navigations. This does not happen - going to / after /foo turns the background white again, going back to /foo downloads the css file again and turns the background red.

You can see this behaviour in the latest commit to the repo.

@stale
Copy link

stale bot commented Dec 31, 2019

Thanks for your contribution to vue-meta! This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of vue-meta
  2. Comment the steps to reproduce it
    Issues that are labeled as pending will not be automatically marked as stale.

@stale stale bot added the stale label Dec 31, 2019
@simonbrent
Copy link
Author

There have been no new releases since I reported this issue so it is not fixed and not stale

@stale stale bot removed the stale label Jan 2, 2020
@pimlie
Copy link
Collaborator

pimlie commented Jan 2, 2020

Could you create a working repro on codesandbox please?

@simonbrent
Copy link
Author

https://codesandbox.io/s/github/simonbrent/nuxt-vue-meta-bug

@pimlie
Copy link
Collaborator

pimlie commented Jan 2, 2020

Thanks, seems like once isnt working as it should indeed.

Not ideal, but this could maybe be a workaround for now? So just make sure to return the script once by using a custom var. For the css you could maybe try to remove the hid prop, it could be that the existence of a hid has the tag removed

let headJsAdded = false
...
export default {
...
    head () {
      const meta = {
        script: headJsAdded ? [] : [{
          hid  : 'head-script',
          src  : '/head-script.js',
          once : true,
        }],
        link: [{
          hid  : 'head-style',
          rel  : 'stylesheet',
          href : '/head-style.css',
          once : true,
        }]
      }
      headJsAdded = true
      return meta
    }),

@simonbrent
Copy link
Author

I have a workaround already - my use case is only javascript, and the scripts I'm importing all add a value to window, so i'm doing:

head: function () {
  return (
    global.foo
      ? {}
      : {
        script: [{
          vmid: 'foo',
          src: '/foo.js',
        }],
      }
  );
},

@stale
Copy link

stale bot commented Jan 24, 2020

Thanks for your contribution to vue-meta! This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of vue-meta
  2. Comment the steps to reproduce it
    Issues that are labeled as pending will not be automatically marked as stale.

@stale stale bot added the stale label Jan 24, 2020
@simonbrent
Copy link
Author

This is still reproducible with nuxt 2.11.0 and vue-meta 2.3.2 - see https://codesandbox.io/s/github/simonbrent/nuxt-vue-meta-bug

@stale stale bot removed the stale label Jan 24, 2020
@pimlie pimlie added the pending label Jan 24, 2020
@pimlie
Copy link
Collaborator

pimlie commented Jan 24, 2020

Thanks, have added the pending label so stale bot doesnt close it as I wont expect to have time to fix this soon

@pimlie pimlie closed this as completed in c74c645 Feb 26, 2020
@pimlie
Copy link
Collaborator

pimlie commented Feb 26, 2020

This should be possble in the upcoming release by combining once & skip. (Just once wont work.)

let haveAddedTheJs = false // <-- outside the component scope

export default {
  ...
  head() {
    const skip = haveAddedTheJs
    haveAddedTheJs = true

    return {
      script: [
        { once: true, skip, src: '/file.js' }
      ]
    }
  }
}

@simonbrent
Copy link
Author

Is that going to be the permanent solution then? It still seems pretty hacky.

@pimlie
Copy link
Collaborator

pimlie commented Feb 27, 2020

Trying to fix this in vue-meta is even more hackier. With once we need to track the state whether the tag has been added or not. If you use head as a function then it returns a new object on every meta update, so we cant use the object itself.

This means if we want to support this in vue-meta itself then we need keep track of all head elements that have been added with once, and then on every metadata update render all elements with once again but only add them if we dont track them yet.

I feel keeping this tracking state (if a once: true tag has already been added or not) in userland as above is a nicer/cleaner solution. But if a lot of people think we should do this in vue-meta anyway then im happy to do so

@simonbrent
Copy link
Author

Fair enough

@gabrielsze
Copy link

Hi there, I'm encountering almost exactly same issue but with Google Maps API. Happens with navigating across pages as well. Tried the above fix with once and skip but doesn't work for my case.

You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.

@thomas4Bitcraft
Copy link

Same here with the Google Adsense Script

@JSAustin
Copy link

Hello, we have similar behavior with other Ad scripts. It works well if we put in nuxt.config.js, but if we want to only add to some pages, it seems to rerun the script on navigation, which it shouldn't. It's creating new, duplicatate Ad Managers each route change and getting silly. Is there a way to get the desired behavior without loading globally?

@amjmhs
Copy link

amjmhs commented Feb 8, 2021

@JSAustin take a look at the workaround above.

@kevhof
Copy link

kevhof commented Nov 3, 2021

@pimlie sorry for bothering you but can you explain why it's not possible to only use skip without once ? What is once used for ?

@arsengoian
Copy link

For anyone facing this in nuxt at the moment, a good workaround is to check using process.client whether page is rendered on the client and if it is, don't insert the script. That will work if you only need the script to work on initial page load and not on soft navigation for example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants