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

how to insert <script> tag before </body>? #2000

Closed
cdoneshot opened this issue Nov 1, 2017 · 26 comments · Fixed by nuxt/vue-meta#154
Closed

how to insert <script> tag before </body>? #2000

cdoneshot opened this issue Nov 1, 2017 · 26 comments · Fixed by nuxt/vue-meta#154

Comments

@cdoneshot
Copy link

cdoneshot commented Nov 1, 2017

i want to insert some <script> tag before the </ body> tag in some pages. if i modify app.html ,all pages will be inserted,or i use head() in these pages,it will be inserted in the head,these are not my wanted

This feature request is available on Nuxt.js community (#c1775)
@mokeio
Copy link

mokeio commented Nov 1, 2017

can edit in the template html

@cdoneshot
Copy link
Author

cdoneshot commented Nov 1, 2017

can edit in the template html

app.html?all pages will be inserted

@clarkdo
Copy link
Member

clarkdo commented Nov 1, 2017

All <script> tags have been inserted before </body>, soure is in renderer.js#L530
image

@cdoneshot
Copy link
Author

@clarkdo

emmm..i want to import 3rd party lib ,use script tag to import instead import .
like this <script src= "//amp.azure.net/libs/amp/latest/azuremediaplayer.min.js"></script>
it will be used in some pages not all pages ,so i dont want to modify app.html.

@paulgv
Copy link

paulgv commented Nov 1, 2017

I guess you could include those scripts in the pages themselves.

@cdoneshot
Copy link
Author

cdoneshot commented Nov 1, 2017

I guess you could include those scripts in the pages themselves.

i include theses scripts in the < template > now,but i got the missmatch warnning.
image
image

i guess the 3rd party lib will change the dom so i got this warnning and the <script> is not in the place where i want .

Is there any other way?

@clarkdo
Copy link
Member

clarkdo commented Nov 1, 2017

<template>
<div></div>
</template>

<script>
export default {
  created() {
    if (process.browser) {
      let recaptchaScript = document.createElement('script')
      recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
      document.body.appendChild(recaptchaScript)
    }
  }
}
</script>

@cdoneshot
Copy link
Author

@clarkdo I had tried this way ,but there are some reasons cant use this way.
this page be put in a native ios app.ios webview will call some js method on finishedload page,but the js has not be loaded yet.
image

@clarkdo
Copy link
Member

clarkdo commented Nov 1, 2017

How about this ?

<div v-html="scripts"></div>
export default {
  data: () => ({
    scripts: "<script src='https://www.google.com/recaptcha/api.js'><\/script>"
  })
}

image
image

@pimlie
Copy link

pimlie commented Nov 1, 2017

I guess you want to add scripts to the bottom to defer execution because the script is used on the page but not required for viewing the page?

Actually I have asked for the same functionality in #1370, it would be nice it you could do this easily with nuxt. Although you can set the defer tag with vue-meta, which should defer execution, I still also prefer to put them psychically at the bottom of the page.

@cretueusebiu
Copy link

Nuxt will generate a app.template.html file inside .nuxt/views. You can edit it and add your script there.

@clarkdo clarkdo closed this as completed Nov 2, 2017
@cdoneshot
Copy link
Author

<div v-html="scripts"></div>
export default {
  data: () => ({
    scripts: "<script src='https://www.google.com/recaptcha/api.js'><\/script>"
  })
}

works ,same as

  <div>
    <video id="azuremediaplayer" ></video>
    <script src="azure/azuremediaplayer.min.js"></script>
  </div>

not in front of the </ body> tag

@clarkdo clarkdo reopened this Nov 2, 2017
@clarkdo
Copy link
Member

clarkdo commented Nov 2, 2017

works ,same as

There is no Vue warn in v-html way.

not in front of the </ body> tag

It will have the same effect, even same as head with defer. Is there any purpose of </body> thought ?

Even in app.html or vendor way, browser will cache js file at first time, also make no difference to performance.

@pimlie
Copy link

pimlie commented Nov 2, 2017

Putting <scripts> just before </body> is mostly about user experience, specifically to make sure a functioning / visible page is rendered as fast as possible.

This strategy is mostly used for scripts that are not important to the functioning of the page itself, think of analytic scripts, delayed/async image loading and especially 3rd party ads. Although the browser caches the files probably themselves, you often want to make fully sure execution is delayed as you dont want your page to feel sluggish due to a heavy ad. Defer should do this as well, but putting it at the end of the body just physically makes sure it happens like this.

@cdoneshot
Copy link
Author

cdoneshot commented Nov 2, 2017

There is no Vue warn in v-html way.

if the script in static folder,will get an error=>cannot resolve xx.js in 'pages/xxx'

@Atinux
Copy link
Member

Atinux commented Nov 2, 2017

@cdoneshot if it's in static/ folder, make sure to use an absolute path, example: src="/azure/azuremediaplayer.min.js"

@cdoneshot
Copy link
Author

make sure to use an absolute path

I'm sure I'm using an absolute path and these scripts are all in _static _ folder.
image

then i got an error
image

@dotneet
Copy link

dotneet commented Nov 2, 2017

Hi, this is my way.

<template>
<div>
   <a class="twitter-timeline" href="https://twitter.com/nuxt_js">Tweets by nuxt_js</a>
   <span v-if="twitterWidget">
      <script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
    </span>
</div>
</template>
<script>
export default {
    data () {
      return {
        twitterWidget: false,
      }
    },
    async mounted () {
      this.twitterWidget = true
    },
}
</script>

@clarkdo
Copy link
Member

clarkdo commented Nov 2, 2017

@cdoneshot @pimlie
Hi guys, I have discussed with @Atinux, we may try to support this feature in vue-meta and may add configuration like:

{
  metaInfo: {
    bodyScript: [
      { src: 'azure/azuremediaplayer.min.js' }
    ]
  }
}

This feature is planned to 1.0.0 release for now.

@phivk
Copy link

phivk commented Feb 26, 2018

I came across this issue and still had to look for quite a while to find the correct syntax that was released in 1.0.0, so for reference:

<script>
export default {
  head: {
    script: [
      { src: '/head.js' },
      // Supported since 1.0
      { src: '/body.js', body: true },
      { src: '/defer.js', defer: '' }
    ]
  }
}
</script>

src: this example from the 1.0.0 release notes

@ameno-gdrive
Copy link

ameno-gdrive commented Mar 2, 2018

Close, but we're not 100% there yet.

Utilizing the method quoted by @phivk , the script will be put near the end of the < head > tag, not at the end of the < body >. While the defer property will allow parallel script fetch and downloads, the load ordering of js during the parsing phase is still off.

Currently any deferred script will parse and execute before the Vuejs application script. Suppose you have a ton of scripts that can use async property, or scripts that dont need to execute before the application executes.

We're forced to lose a chunk of time waiting.

@qm3ster
Copy link

qm3ster commented Mar 3, 2018

@ameno-gdrive why put scripts in html at all? Can't you just asynchronously import them in your javscript where you need them?

@mesqueeb
Copy link

@qm3ster
For some libraries this is not possible. E.g. the UMD version of Quasar.

@Geowan
Copy link

Geowan commented Jun 1, 2018

Its very easy

Just create a app.html at the root of your project and add

  <html {{ HTML_ATTRS }}>
   <head>
    {{ HEAD }} 
  </head>
 <body {{ BODY_ATTRS }}>
   {{ APP }}

   <!--EXTRA JS FILES-->
   </body>
</html>

THats the default template that nuxtjs uses by default. Ensure that you place this at the root of your project

@weddinghairandmakeupartists

@Geowan That will put the script on every page. @cdoneshot wanted it on specific pages

@lock
Copy link

lock bot commented Nov 19, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 19, 2018
@danielroe danielroe added the 2.x label Jan 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.