vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.95k stars 33.68k forks source link

Vue should not cause execution of content within <noscript> tags #9669

Open OwenMelbz opened 5 years ago

OwenMelbz commented 5 years ago

Version

2.6.8

Reproduction link

https://jsfiddle.net/ncwuvekm/1/

Steps to reproduce

Check the "network" tab.

You can see that Vue causes a request to the content within the <noscript>

What is expected?

Vue should not cause execution of <noscript>content

What is actually happening?

Vue causes requests to elements within <noscript>


It's typical when websites are using Vue to supplement UI and a common pattern is to wrap the site with an id="app"

However, this introduces a problem when people are using <noscript> in various areas of the site that are not within Vue components as Vue will execute it regardless.

A use case example would be using a lazy loading library with a <noscript> fallback.

<img src="thumbnail.jpg" data-src="hi-resolution.jpg" />
<noscript><img src="hi-resolution.jpg" /></noscript>

Vue will cause the hi-resolution.jpg image to download even though it's within the <noscript>

For anybody experiencing this issue, a hack is to add v-if="false" to your <noscript> to prevent the element from rendering e.g.<noscript v-if="false">

posva commented 5 years ago

It's not that Vue processes the content, the browser seems to fire the requests with noscript tags added dynamically (which I wonder if should even be allowed)

const noscript = document.createElement('noscript')
const img = document.createElement('img')
img.setAttribute('src', "https://images.unsplash.com/photo-1552084007-76f5feb8d22a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60")

noscript.appendChild(img)

window.app.appendChild(noscript)

I think we could avoid rendering noscript elements in general, using a v-if="false" is a valid workaround, you can combine it with v-pre too so Vue skips rendering any of their children and probably boosting the performance a bit too

OwenMelbz commented 5 years ago

Sorry processing was probably the wrong word :) I could just see Vue was causing them to run.

I’ll try out the v-pre you’ve mentioned as well to see what that affects, thanks for the tip :)

I’m a little confused with your code snippet, what is that trying to demonstrate? - the noscript itself is just in a PHP template for something else, however because the page wrapper is what the “new Vue ( el = #app )” Vue starts to work it’s magic which causes this side effect

posva commented 5 years ago

The code is showing the problem without Vue

OwenMelbz commented 5 years ago

Ah okay - do you think this is something Vue could handle? As if it works with v-if and v-pre then would suggest it can handle it without side effects?

tony19 commented 5 years ago

It seems anti-intuitive (or an invalid use case) for <noscript> to be added through scripting -- the very thing that <noscript> indicates is disabled. 😜

OwenMelbz commented 5 years ago

@tony19 - that’s “sort” of my point. The noscript itself isn’t added through JS it just happens to be in the server side page source

posva commented 5 years ago

What he's saying is that you are adding it through Vue by feeding it to Vue, which adds dynamically content. I get the usecase though, it's added in case there is no JS (Vue doesn't run) but if Vue runs you want it to be ignored the same way it is ignored upon first rendering

lanaambre commented 5 years ago

Just add the inline-template attribute to your <noscript> tag

<noscript inline-template>
 <img src="//something.jpg">
</noscript>
OwenMelbz commented 5 years ago

@Antoine-Demailly We've already established that there's several "hacks" to work around this issue, but that's not the point.

The solution should either be


@posva - The v-pre trick did not work, I was hoping it would as it seems better than v-if or inline-template as it's more descriptive. You can see the example https://jsfiddle.net/nvfuyj8k/ - it still requests the content within the noscript

posva commented 5 years ago

yeah, i said combine it to v-if to prevent vue from running inside, it's a performance improvement. Rendering wasn't the right word, interpreting maybe? Anyway, you can check it out in vue docs