30

I'm new on VueJS ans Webpack. I've created a project with VueJS CLI and trying to work with it. I need to insert an CDN to my code.

When working with standard HTML, CSS & JS solutions, I'd include CDNs like this:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>False Merge</title>

    <!-- CDN -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.16/sl-1.2.5/datatables.min.css"/>

    <!-- StyleSheets -->
    <link rel="stylesheet" href="public/stylesheets/index.css" />
</head>

<body>


    <script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
    <script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.16/sl-1.2.5/datatables.min.js"></script>

    <script src="public/javascripts/index.js"></script>

</body>

</html>

As you can see, you can add a CDN script with the HTML script tag, and start using it in the JS.

I'm trying to do the same with VueJS in a component. I've got the template and style sections ready.

Unfortunately, I don't know how to add in a simple way a CDN to use inmediately in the script tag within the Vue component. I tried to do this but it is not working.

<template>
  <div class="index">
    <div class="container">
      <table id="table_dataset" class="display">
      </table>
    </div>
  </div>
  
</template>

<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.16/sl-1.2.5/datatables.min.js"></script>
<script>
  export default {
    name: 'Index',
    data() {
      return { 
      }
    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

Is there a way to add a CDN (without Webpack or NPM) to a VueJS component?

Fabricio Chacon
  • 313
  • 1
  • 3
  • 4
  • Vue single file components are not the right place for this because they are compiled into regular javascript, and has a number of limitations, such as: only one script tag in a component. – Ruslan Mar 16 '18 at 23:30
  • You can add cdn styles/scripts directly to the `./index.html` or `./public/index.html` in vue-cli@3.0. – Ruslan Mar 16 '18 at 23:30

3 Answers3

50

Unfortunately, no, you can't add a <script> tag to a specific component via template.

In your case you have some options:

1: Use NPM

Propertly install the dependency using npm

  • Pros: proper usage of NPM and Webpack; scoped definition;
  • Cons: the script must be available as a NPM package.
  • Note: when available this is the recommended approach.
  • Steps:


2: Add <script> tag to index.html

Locate and a dd the <script> tag to your index.html

  • Pros: the <script> tag is clearly (and declaratively) added to the HTML source. The script will only be loaded once.
  • Cons: the script will be globally loaded.
  • Steps:
    • Just add the <script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.16/sl-1.2.5/datatables.min.js"></script> to the end of the index.html file, preferably right before </body>.

3: Create the <script> tag programatically

The other alternative is to create the script tag programatically at the component, when the component is lodaded.

  • Pros: the code stays in the component only. Your external script will be loaded only when the component is loaded.
  • Cons: the script still will be globally available once it is loaded.
  • Steps/Code:

    <script>
      export default {
        name: 'Index',
        data() {
          return { 
          }
        },
        mounted() {
          if (document.getElementById('my-datatable')) return; // was already loaded
          var scriptTag = document.createElement("script");
          scriptTag.src = "https://cdn.datatables.net/v/dt/dt-1.10.16/sl-1.2.5/datatables.min.js";
          scriptTag.id = "my-datatable";
          document.getElementsByTagName('head')[0].appendChild(scriptTag);
        }
      }
    </script>
    
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • When using NPM where is the library module saved? Is it included in app.js? If so, it is same as other option right? – Yosua Lijanto Binar Jul 26 '18 at 04:58
  • Trying this with e.g. `npm install emailjs` and then `require('emailjs/email')();`, I get an error: `Uncaught TypeError: __webpack_require__(...) is not a function` – sunwarr10r Apr 11 '19 at 14:44
  • #3 has been the best option for me, especially when loading large libraries – Master of Ducks Jul 10 '19 at 13:11
  • With option #2 or #3, is it possible to refer to types and functions within the script inside your component's Javascript? I've asked a question about this, if you know the answer: https://stackoverflow.com/questions/57840349/how-to-use-external-javascript-objects-in-vue-js-methods – Duncan Jones Sep 08 '19 at 08:45
4

I don't know if this is still a concern, but you could also give vue-meta a look. I'm using it to create a better SEO implementation, but with it, you can include CSS, and/or JS files for specific components. You can even set the individual files to preload if you wanted. Here's a pretty good write-up. https://alligator.io/vuejs/vue-seo-tips/

In there it says that vue-meta isn't stable, but the article was written in February of 2018, and the version as of today, is 2.2.1.

  1. add this line to your package.json file within the dependencies object: "vue-meta": "^2.2.1",

note - omit the trailing comma if it's to be the last line of the dependencies object

  1. open a terminal and cd to the dir which contains above mentioned package.json file. (BTW, this is all super easy if you use the vue ui).
  2. in the terminal run: npm install

Then add the following to your main.js file.

import Meta from "vue-meta";
Vue.use(Meta);

Now you can freely load static CSS/JS assets. This works for local, or from cdn. Below is my example. Disregard my imports, components and methods... they aren't related to vue-meta and may differ from yours. I just wanted to show you a working version.

<script>
import { page } from "vue-analytics";
import Header from "@/components/Header.vue";
import Footer from "@/components/Footer.vue";
export default {
  components: {
    Header,
    Footer
  },
  data: function() {
    return {};
  },
  methods: {
    track() {
      page("/");
    }
  },
  metaInfo: {
    link: [
      {
        rel: "preload",
        as: "style",
        href: "https://cdn.jsdelivr.net/npm/bootstrap-vue@2.0.0-rc.28/dist/bootstrap-vue.min.css"
      },
      {
        rel: "preload",
        as: "style",
        href: "https://fonts.googleapis.com/css?family=Cinzel|Great+Vibes|Montserra"
      },
      {
        rel: "preload",
        as: "style",
        href: "/content/css/site.css"
      },
      {
        rel: "stylesheet",
        href:
          "https://fonts.googleapis.com/css?family=Cinzel|Great+Vibes|Montserra"
      },
      {
        rel: "stylesheet",
        href: "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css",
        integrity:
          "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T",
        crossorigin: 'anonymous"'
      },
      {
        rel: "stylesheet",
        href: "https://cdn.jsdelivr.net/npm/bootstrap-vue@2.0.0-rc.28/dist/bootstrap-vue.min.css",
        async: true,
        defer: true
      },
      {
        rel: "stylesheet",
        href: "https://use.fontawesome.com/releases/v5.8.1/css/all.css",
        integrity:
          "sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf",
        crossorigin: 'anonymous"',
        async: true,
        defer: true
      },
      {
        rel: "stylesheet",
        href: "/content/css/site.css",
        async: true,`enter code here`
        defer: true
      },
      { rel: 'favicon', href: 'favicon.ico' }
    ],
    script: [{ src: "https://unpkg.com/axios/dist/axios.min.js", async: true, defer: true }],
  }
};
</script>
N8_
  • 41
  • 1
0

https://renatello.com/vue-js-external-css

  1. Include CSS file in one component
  2. Include globally
  3. Include in index.html
Rich
  • 705
  • 9
  • 16