Setting up a Vue CLI project for building Custom HTML Elements
Tags: vue, javascript, customelements, webdev
Published: 2019-07-08 20:40:38

---
title: Setting up a Vue CLI project for building Custom HTML Elements
published: true
tags: vue, javascript, customelements, webdev
canonical_url: https://jerickson.net/setting-vue-cli-project-custom-html-elements/
cover_image: https://images.unsplash.com/photo-1504292004442-f285299403fa?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1053&q=80
series: Vue Custom Elements
---

I talked about [what custom HTML elements were](nttps://jerickson.net/what-are-custom-HTML-elements) in my last post. Today, I'm going to walk through the process of getting a new Vue CLI project off the ground so that you can build your own. I'll be using the `<my-blink>` tag example again, but will be focusing on the step by step[^1] instructions for creating the environment in which to build and deploy the tags you will be creating.

[^1]: Oooooooh, Baby!

## Getting the Vue CLI[^2]

[^2]: I'm going to assume here that you have [Node and NPM](https://nodejs.org/en/) installed already. If you don't, do that first.

The first thing you'll want to set up is the [Vue CLI](https://cli.vuejs.org/). This is an amazing tool that will install and configure nearly everything you need to Vue development, and will help you build our components as custom HTML elements.

You're going to do quite a bit in our command line, so open up your favorite command line and type in the following on Windows:

```bash
npm install -g @vue/cli
```

Or this on Mac or Linux:

```bash
sudo npm install -g @vue/cli
```

This will install a new program on your computer called, funnily enough, `vue`. This `vue` application is a great starting point for any new Vue project, whether that's a SPA[^3], a mobile application, or custom HTML elements.

[^3]: Single Page Application

## Using Vue CLI to create a new project

To create a new Vue project, you can use the new Vue CLI. If you run the following command, it will create and download a whole new Vue project into a folder called `my-custom-elements`:

``` bash
vue create --bare --default my-custom-elements
```

Using `--bare` will prevent the CLI from creating a needless `HelloWorld` component and `--default` will tell the CLI to set up a simple project. There are a lot of extras that you can add to the project using the CLI, but you don't need any of that at the moment.

Once this is done, change into the new directory and open it in your favorite editor.[^4]

[^4]: Might I suggest [Visual Studio Code](https://code.visualstudio.com/)?

## The Vue project structure

Looking at the project structure, there's a lot that was created for us here! There are a number of Node.js files here that set up some tools for our project and all the libraries we will need to build and compile our tags. You can read up about what [`package.json` is here](https://nodesource.com/blog/the-basics-of-package-json-in-node-js-and-npm/) and get a bit of knowledge about [`node_modules` here](https://stackoverflow.com/questions/34526844/what-is-node-modules-directory-in-angularjs).

You should see two other folders in there are well, `src` and `public`. I'll leave an explanation of `public` for another time, but what you want to focus on is the `src` folder.

The `src` folder is where all of your component code will go for the project. This is the location of your source code in the project structure.

In fact, you're going to create a new folder here. Just right click on the `src` folder, select New Folder and call the folder `components`. This is where you will create your components that will become custom elements.

## Creating the custom element

Now that you have your project set up, we're going to create a new component. Right click on the new `components` folder and select New File. Name this file `Blink.vue` and set its content to the following:

```html
<template>
<span ref="blinkyText"><slot></slot></span>
</template>

<script>
export default {
  name: "blink",
  mounted() {
    setInterval(() => {
      this.$refs.blinkyText.classList.toggle("onoff");
    }, 500);
  }
};
</script>

<style>
.onoff {
  visibility: hidden;
}
</style>
```

This creates a [Single File Component](https://vuejs.org/v2/guide/single-file-components.html) in Vue for us, which makes creating custom elements very simple and with an existing web developer syntax. This component should be pretty easy to read as is. `<slot></slot>` will be replaced with whatever is inside our custom tag, so the view is just wrapping a `span` around that. The CSS, at the bottom, creates a new style class that will hide an element (setting its visibility to `hidden`). The JavaScript logic will then, when the component is "mounted" or loaded onto the page, take that span that you created and toggle (or add/remove) the class from the span, thereby showing and hiding the content from the `slot`.

Now you can create this as a custom HTML element.

## Building the component into a custom element

By default, this project is not set up to actually create custom elements. It has all the tools needed to do so, but we need to set up a new script to get it to happen.

Open the `package.json` file. There is a lot already set up in this file, but you want to go to the section that is labeled `"scripts"` and add a new one. Currently, it will look like this:

``` json
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
```

You're going to change the `build` script to something new. Change it to look line this:

```json
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --target wc --name my-blink 'src/components/Blink.vue'",
    "lint": "vue-cli-service lint"
  },

```

That build script is now changed to create Web Components (`--target wc`), give the custom element a name (`--name my-blink`)[^5], and just build the one component (`'src/components/Blink.vue'`).

[^5]: By the standard, all custom elements built by a developer must contain a `-`. I'll get into good naming conventions in another post.

Once you add that to `package.json` and save the file, you can now run the build process to create your custom element. Run the following command on the command line in your project folder:

```bash
npm run build
```

This will build your custom element and put a JavaScript file in the `dist` folder of your project (which should have just been created). It will also create a `demo.html` file for you. From that file, you'll see this:

``` html
<meta charset="utf-8">
<title>my-blink demo</title>
<script src="https://unpkg.com/vue"></script>
<script src="./my-blink.js"></script>


<my-blink></my-blink>
```

This isn't a full HTML file, so isn't too useful, but you can see what you will need to do to use this custom element. First, you'll need to include the Vue framework on the page:

``` html
<script src="https://unpkg.com/vue"></script>
```

Then include your custom element JavaScript file that got built into the `dist` folder:

```html
<script src="./my-blink.js"></script>
```

And then use your new tag!

``` html
<my-blink></my-blink>
```

Or, more accurately if you were using this in real life:

```html
<my-blink><h1>Look!!! Blinking text!!!</h1></my-blink>
```

That's all there is to it. There are a lot of steps here and we haven't even talked about multiple custom elements or getting them to communicate together (which I plan on getting to), but you can see how a simple Vue component can be created into a custom element.