Vue.js 3 Global API Tutorial

In this Vue tutorial we learn how to add standalone components to an existing website with the Global API.

We cover how to add Vue to an existing project, how to create and mount the instance to the DOM, the config object and how to create a component with the Global API.

Finally, we cover which Global API build file to choose.

Lesson Project

If you want to follow along with the examples, you will need a folder with the following two files.

  • index.html
  • app.js

The project should look similar to the following.

Example: project
project-name/
├── index.html
└── app.js

The index.html file will have the following basic HTML.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue Global API</title>
</head>
<body>

</body>
</html>

The app.js file can be empty for now but there’s one last thing we have to set up, if it’s not already setup on your system.

What is the Global API?

As we mentioned in the Vue API lesson, the Global API is used to add standalone components to an existing website.

We don’t use the Vue CLI to scaffold a project with the Global API. Instead, we use a file with the core Vue library that we either host ourselves or add a link to a CDN.

How to add Vue to an existing project

Vue has different versions of the its core library depending on what we want to do, but for testing and learning purposes we can just use the latest package.

Example:
<script src="https://unpkg.com/vue@next"></script>

We can replace next with a specific version.

Example:
<script src="https://unpkg.com/vue@3.2.22"></script>

For our example, we’ll copy the script tag with the latest version into the head of our index.html file, right above the app.js import.

note Script loading strategies are outside of the scope of this course, we won’t cover them in this lesson.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- import Vue -->
  <script src="https://unpkg.com/vue@next" defer></script>
  <!-- import app instance -->
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <h1>Hello, World!</h1>

</body>
</html>

That’s all we need to do to add Vue to an existing project. However, we still need to create the Vue application instance.

How to create the Vue Application Instance

When we use the Application API and generate a new Vue project, it creates the application instance for us. When we use the Global API, we need to create the application instance ourselves and link it an element on the page.

We use the same createApp method as we do with the Application API, but this time we use it on a Vue object that the Global API gives us access to.

Syntax: createApp
Vue.createApp()

For our example, we’ll create the application instance in the app.js file.

Example: app.js
// create app instance
Vue.createApp()

Mounting the Vue Application Instance in the DOM

The next step is to tell Vue which part of the page we want it to control and like the Application API, we specify the element in the mount method.

Syntax: mount
mount('element')

For our example, we’ll use an element with id="app" .

Example: app.js
Vue.createApp().mount('#app')

Of course, for this to work we need an element in our HTML with an id="app" .

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/vue@next" defer></script>
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <!-- mount Vue app instance -->
  <div id="app">
    <h1>Hello, World!</h1>
    <p>
      Everything in this div will be controlled by Vue
      because it's linked with the <code>mount</code> method
    </p>
  </div>

  <hr>
  <p>Everything else outside the div works as it normally would</p>

</body>
</html>

Once we link the element, everything inside it becomes the Template. Vue can control the Template from inside the app.js file and output dynamic data or react to events.

Creating the configuration object

Typically, we would import the root App component as the main configuration for the createApp method. With the Global API, we’ll need to create one ourselves.

Example: app.js
// config object
const App = {

}

// create App with config above
// and mount to element with id="app"
Vue.createApp(App).mount('#app')

Within the config object, we can use any of the properties and methods from the Options API.

To demonstrate, let’s create a data property in the config object.

Example: app.js
const App = {
  data() {
    return { name: 'John' }
  }
}

Vue.createApp(App).mount('#app')

Then use string interpolation to show it in the linked div in the index.html file.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/vue@next" defer></script>
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <div id="app">
    <h1>Hello, {{ name }}!</h1>
  </div>
</body>
</html>

When we run the example in the browser, the name renders on the page like we expect.

So, we use the linked div just like we would the template block in the Application API. We can use data binding, directives etc. without any issues.

To demonstrate, let’s change our example to an array of people.

Example: app.js
const App = {
  data() {
    return {
      people: [
        { id: 1, name: 'John' },
        { id: 2, name: 'Jane' },
        { id: 3, name: 'Jack' },
        { id: 4, name: 'Jill' }
      ]
    }
  }
}

Vue.createApp(App).mount('#app')

Then loop over them in a paragraph with a v-for loop.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/vue@next" defer></script>
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <div id="app">
    <p v-for="person in people" :key="person.id">{{ person.name }}</p>
  </div>
</body>
</html>

When we run the example in the browser, everything works as expected.

How to create a component with the Global API

To create a component with the Global API, we use the component method on an existing App.

The method takes two arguments.

  1. The component’s name.
  2. The component’s config object.
Syntax: component
// create App instance
const App = Vue.createApp({})

// component with its config object
App.component('component-name', {

})

// mount app & component
App.mount('#app')

As an example, let’s create a component with a greeting message.

Example: app.js
const App = Vue.createApp({})

App.component('greeting-message', {
  data() {
    return { msg: 'Hello, Vue!' }
  }
})

App.mount('#app')

Then create an instance of the component in the app’s div.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/vue@next" defer></script>
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <div id="app">
    <!-- create an instance of the component -->
    <greeting-message />
  </div>
</body>
</html>

But if we run the example in the browser, nothing happens and Vue raises a warning in the console.

Output:
Component is missing template or render function.

Because our component doesn’t have a template block, Vue doesn’t know what to render.

For a component to be able to render anything, it needs to use the template option.

This option’s value is a string with the content we want the component to render, just like in a template block. We can use any valid HTML, data binding, directives etc.

Syntax: template
template: `<element>{{ dataProperty }} etc.</element>`

tip Use backticks to wrap the content instead of single or double quotes. The backtick symbol can be found above the Tab key on a standard US layout keyboard.

To demonstrate, let’s add a template to our example that renders the greeting message in a heading.

Example: app.js
const App = Vue.createApp({})

App.component('greeting-message', {
  data() {
    return { msg: 'Hello, Vue!' }
  },
  template: `<h1>{{ msg }}</h1>`
})

App.mount('#app')

If we run the example in the browser, the message renders as we expect.

Which Global API build file to choose

So far in this lesson, we’ve been using the full Vue library that we included from a CDN.

Example:
<script src="https://unpkg.com/vue@next" defer></script>

But this file is more than 600kB, we don’t really want to use something that big for production. Luckily, Vue provides us with several smaller options.

The files can be downloaded on linked to from one of two CDNs.

The files we use depend on what the application does.

  1. Your app compiles templates on the client with the template option and/or in-DOM HTML (like we’ve been doing throughout this lesson).

    You will need both the runtime and the compiler, so you want to choose the vue.global.prod.js file.

  2. Your app compiles templates during a build step .

    You will need only the runtime, so you want to choose the vue.runtime.global.prod.js file.

  3. Your app compiles templates on the client and uses a bundler like webpack, rollup or parcel.

    You will need both the runtime and the compiler, so you want to choose the vue.esm-bundler.js file.

  4. Your app compiles templates on the client and uses a bundler .

    You will need only the runtime, so you want to choose the vue.runtime.esm-bundler.js file.

  5. Your app uses Node server-side rendering.

    You will need the vue.cjs.prod.js file.

The examples we’ve been using in this lesson compiles templates in the browser on the fly, so we want to use the vue.global.prod.js file.

note JsDelivr exposes the raw file’s url so you can use it directly. But in unpkg you will need to browse the file, then click on View Raw to get the raw file’s url.

Example: index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- raw file import -->
  <script src="https://unpkg.com/vue@3.2.22/dist/vue.global.prod.js" defer></script>
  <script src="app.js" defer></script>

  <title>Vue Global API</title>
</head>
<body>
  <div id="app">
    <greeting-message />
  </div>
</body>
</html>
Example: app.js
const App = Vue.createApp({})

App.component('greeting-message', {
  data() {
    return { msg: 'Hello, Vue!' }
  },
  template: `<h1>{{ msg }}</h1>`
})

App.mount('#app')

If we run the example in the browser, everything still works as expected.

Further Reading

For more information on the topics covered in this lesson, please see the relevant sections below.