nuxt / vue-meta

Manage HTML metadata in Vue.js components with SSR support
https://vue-meta.nuxtjs.org
Other
4.08k stars 247 forks source link

Head scripts are reappended and reexecuted on navigation #381

Closed guanzo closed 5 years ago

guanzo commented 5 years ago

Version

2.7.1

Reproduction link

https://github.com/guanzo/codesandbox-nuxt

Steps to reproduce

$ git clone https://github.com/guanzo/codesandbox-nuxt nuxtbug
$ cd nuxtbug
$ npm i
$ npm run generate
$ npx http-server dist

Open the webpage and dev tools, go to the Elements tab, expand the <head> node

Note the position of the element

<script data-n-head="true" src="https://arc.io/widget.js?MURGrEjPmB6gVvzyvpbDut" async=""></script>

Note the element <div id="arc-widget"></div> at the bottom of <body>. This element is created when the arc.io/widget.js script is loaded.

Click the "test" link

The <head> is updated and the script has been appended to the bottom of <head>, causing it to execute again, and now there are 2 #arc-widget elements.

What is expected ?

A script is loaded once across all navigations.

What is actually happening?

A script is loaded twice across all navigations.

Additional comments?

Related to https://github.com/nuxt/nuxt.js/issues/3396.

This only occurs when each nuxt page has its own title. When nuxt updates the page title on navigation, the script is reappended. The hid attribute on the script tag doesn't fix it.

This bug report is available on Nuxt community (#c9269)
rchl commented 5 years ago

@pimlie

Script in generated page has this outerHTML:

<script data-n-head="true" src="..." async></script>

while dynamically created script has this:

<script data-n-head="true" src="..." async="true"></script>

so then those fail isEqualNode check in here: https://github.com/nuxt/vue-meta/blob/2775c2dfd9b5a0752a71df780f5f3fc97942ffb8/src/client/updaters/tag.js#L63 because async attribute value is different.

SSR page when using npm run dev works fine (has async="true" in source).

pimlie commented 5 years ago

@guanzo I am afraid I cant reproduce this on csb. As in the widget.js script doesnt move to the end of head, for me it stays at the same position as after the page has loaded and the div is only listed once.

@rchl Please try the rc for vue-meta v2 as that should be fixed in v2

rchl commented 5 years ago

@pimlie But I don't think you can reproduce that on CSB as this bug only reproduces with nuxt generate. I've created maybe more clear version of original repro at https://github.com/rchl/nuxt-generate-meta-bug . You could give it a try maybe? Need to follow instructions in the readme.

And sorry but I haven't tested v2 rc as I have troubles figuring out how to plug in that version into existing dependencies. Tried linking vue-app and vue-renderer from my local nuxt checkout but got Unexpected token export errors.

pimlie commented 5 years ago

You can install v2rc by running yarn add vue-meta@next (npm lists all available tags for a package you can use on the XX Versions tab here: https://www.npmjs.com/package/vue-meta)

I actually did run the generate on csb. I couldnt add extra yarn scripts it seems so I first ran yarn generate, then I changed the generate script in package.json to be the npx command (and added -p 3000) then deliberately added an error to nuxt.config so nuxt dev would fail to run (and port 3000 was available), clicked on yarn generate which now started the http-server et voila :)

rchl commented 5 years ago

@pimlie but yarn add vue-meta@next doesn't override vue-meta sub-dependencies of vue-app and vue-renderer as far as I can see. It will just install hoisted version but nothing will use it.

Or am I wrong? I can still see references to vue-meta v1.6.0 in generated files at least.

pimlie commented 5 years ago

The quickest way to check if you are running v2 is load your Nuxt app in the browser and check window.$nuxt._vueMeta. If that exists (and is an object) then you are using v2.

rchl commented 5 years ago

window.$nuxt._vueMeta exists and is an object but bug still reproduces.

rchl commented 5 years ago

And actually with v2 it reproduces both when using yarn generate and yarn dev while with v1 it only reproduces with yarn generate.

pimlie commented 5 years ago

Transferred this to vue-meta repo as it appears to be a vue-meta bug indeed.

More strangely, apparantly I even deliberately 'fixed' the tests to include this difference: https://github.com/nuxt/vue-meta/blob/master/test/utils/meta-info-data.js#L127

Will have a look tomorrow whether that was just a brain fart or that there was more to it.

pimlie commented 5 years ago

This should be fixed now. Seemed to just have been an oversight, not a brain fart as so much ;)

(fix will be released this weekend)

snapwich commented 5 years ago

Hi @pimlie,

After much struggle I've decided with about 99% certainty that this bug is what is causing this other bug: https://github.com/nuxt-community/google-adsense-module/issues/16

The google adsense code placed in the head is ran once in dev mode but with nuxt generate code it runs once on load and once when navigating to another page but then no more after that. Running twice in those situations breaks the adsense module for pages rendered from nuxt generate

I used yarn to resolve vue-meta to 2.0.3 (latest) and confirmed that window.$nuxt._vueMeta exists and is an object but the problem still exists. If this is the same bug (which I think it is) then I don't think it has been fixed.

amritk commented 5 years ago

Hmm I think I'm running into this issue right now with nuxt build --spa. Was the fix released?

Edit: I will create a new issue

bengineer19 commented 4 years ago

@snapwich I agree.

I initially had the issue with npm run dev but after updating nuxt, everything now works fine in dev mode (and also npm run build && npm run start). However when statically generating using npm run generate, the problem still occurs.

I think this should be re-opened?