Going from .vue files to vue-cli
Tags: codenewbie, vue, javascript, webpack
Published: 2020-08-22 18:49:28

---
title: Going from .vue files to vue-cli
published: true
description: 
series: Setting up a vue.js build
tags: #codenewbie, #vue, #javascript, #webpack
---

In the [last tutorial](https://dev.to/andyhaskell/setting-up-a-vue-js-build-from-plain-vue-to-vue-files-ih9), we saw how by reorganizing our Vue code and then adding a build process to our app with webpack and `vue-loader`, we can use Vue single-file components to arrange the code in our Vue web apps.

But that's not all a Vue build process can give us. vue-loader gives you a lot of ways you can customize your `.vue` files even further! So let's take a look at some extra .vue configuration we can use, and then take a quick look at one more convenient Vue tool, vue-cli!

Examples from this tutorial can be found on [this GitHub repository](https://github.com/andyhaskell/vue-build-tutorial).

## 🏠 Trick out our .vue files. With webpack, it's your house!

It's cool and all that we have this new `.vue` file format, but what if we wanted to do our own custom syntax in our single-file components, like using TypeScript in our `<script>` tags instead of regular JavaScript, or Pug instead of HTML? Turns out, you can indeed make the sections of your `.vue` files work with other programming languages.

You still need to add on to your webpack build to do that, but to see that in action, let's try having `ColorPicker.vue` use Pug.js instead of plain HTML. If you haven't tried Pug before, it's like HTML, but it has a more condensed syntax without closing tags.

To start, in `ColorPicker.vue`, replace the content of the `<template>` with this:

```vue
<template lang="pug">
  form
    h3 Select a color
    button(
      v-for="color in colors",
      :key="color",
      @click.prevent="selectColor(color)"
    ) {{ color }}
</template>
```

Now, the next thing we need to do is have vue-loader read this template as Pug instead of HTML. For this, we need to give our webpack config a rule that when it detects a Pug template, it converts the Pug code to plain HTML that the browser can work with. For this, we'll use `pug-plain-loader`, which takes in Pug and outputs HTML:

```
yarn add --dev pug pug-plain-loader
```

With that loader added, let's now add this rule to the rules section of `webpack.config.js`:

```javascript
{
  test: /\.pug$/,
  loader: 'pug-plain-loader',
},
```

Run `yarn build`, and once again, the app should still be working, and the browser has no idea that the template to our color picker used Pug code that came from inside a .vue file, rather than HTML that came from a .js file!

But wait, the `test` of that rule is looking for `.pug` files. But our Pug code lives in a `.vue` file, not `.pug`. How does webpack know that it's reading Pug?

That's where our friend `VueLoaderPlugin` comes in! It injects all our rules for file formats like Pug into the logic for processing code in `.vue` files. So we encounter ColorPicker.vue in vue-loader, and its template's opening tag looks like this: `<template lang="pug">`. Because that `lang` attribute is set to Pug, that means handling the template code is done with `pug-plain-loader`, rather than vue-loader's regular HTML loading logic!

## 🎨 Add some CSS!

We've got HTML or Pug in our Vue single-file components, and obviously we've got JavaScript. But why not some CSS too? With .vue files, you can throw that in, with a `<style>` tag! Let's say in `ColorPicker.vue`, we wanted to have our header text be in a font like Impact. First, in the template section, let's give our ColorPicker's header a CSS class:

```diff
  form
-   h3 Select a color
+   h3.select-header Select a color
    button(
      v-for="color in colors",
      :key="color"
      @click.prevent="selectColor(color)"
    ) {{ color }}
```

Now, in `ColorPicker.vue`, we can style it with some CSS. Add this code to the file, outside of the template and script tags, which will set the header in the color picker to impact font, or a similar font:

```vue
<style scoped>
.select-header {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
}
</style>
```

So far so good, this is just regular CSS. W're gonna need one more webpack rule with a couple loaders for this CSS to work. Those two loaders are `css-loader` and `vue-style-loader`.

```
yarn add --dev css-loader@3.6.0 vue-style-loader
```

⚠️ NOTE: I have experimented with css-loader, and with the current version of vue-style-loader at the current time, 4.1.2, I found we need css-loader 3.6.0 for it to successfully apply our CSS to our Vue template.

Now, if we add this rule to our webpack config to use our new loaders when we bump into some CSS while running `yarn build`...

```javascript
{
  test: /\.css$/,
  use: [
    'vue-style-loader',
    'css-loader',
  ]
}
```

it will now be applied to your app!

Notice, by the way, how the `<style>` tag we used said `style scoped`? That `scoped` part is pretty sweet. It lets you define CSS rules that **only** apply to your Vue component! If you went into `App.vue` and gave the `<h1>` tag the same `select-header` class we were styling in ColorPicker.vue, the style rule wouldn't be applied to it. Because our style rule is **scoped**, we're only applying the CSS rules in `ColorPicker.vue` to `.select-header` elements in the color picker component!

Also one other cool thing is, we can use the `lang` attribute in `<style>` tags just like we can use it in the `<script>` and `<template>`. If you prefer writing CSS with a preprocessor like Sass, you can use that preprocessor by using a tag like `<style scoped lang="scss">`, and then adding a `/\.scss$/` rule to your webpack config.

## 🚀 Build FAST with vue-cli!

We've seen how we can configure webpack to set up your .vue files to use whatever syntax you like. But how about writing a Vue app where we don't need to think so much about what webpack's doing? The Vue Team's got you covered there with [vue-cli](https://cli.vuejs.org/).

vue-cli uses webpack behind the scenes, but right from the start, it configures a broad webpack setup for you. What this means for you is, you only need to go changing the webpack code of your vue-cli app if you need webpack to do **something different** from that default config.

To show you how convenient this is, let's try setting up our Vue app with vue-cli! First, install this tool with:

```
yarn global add @vue/cli
```

Now, run `vue create with-vue-cli`. Select all the defaults (explore them later though), and a whole Vue app will be generated, with single-file components in its `src` directory. Now, all we have to do is replace the generated Vue components with our Vue components:

1. Under `src/components`, delete `HelloWorld.vue`, and add in `ColorPicker.vue`.
2. In `src/App.Vue`, replace the code that's already there, with code from the App.vue file we made already.
3. There's just one code change we need to do now. Since we now have a `components` directory where all components under App.vue live, we need to change the import statement in `App.vue`:

```diff
- import ColorPicker from './ColorPicker.vue';
+ import ColorPicker from './components/ColorPicker.vue';
```

Then, we'll just need to add Pug and pug-plain-loader to our package.json...

```
yarn add --dev pug pug-plain-loader
```

Now, with that in place, we have an app with some Vue single-file components built. Ready to try it out?

Run `yarn serve`, and go to `localhost:8080`, and you'll see...

![A browser window open with a web app displaying a big header in red that says "Now on vue-cli!", an input box for editing that message, a smaller header in impact font that says "select a color", and four buttons for picking to display the big header in black, red, green, or blue](https://dev-to-uploads.s3.amazonaws.com/i/smoko1g4jb2mt4rxuxqq.png)

your app working! We're using single-file components, and in ColorPicker.vue, we have Pug and a `<style scoped>` tag, and we didn't need to write webpack configuration for any of it; all we needed to do was one extra `yarn add`! Talk about convenient!

webpack is still being used, though. To see for yourself, try running `vue inspect > webpack.js`.

If you go into webpack.js, you'll see a massive webpack config full of rules for common things Vue developers might want configured. That means that if there's some unexpected behavior in the build process, or you need to add support for something vue-cli doesn't already cover, you can use `vue inspect` to investigate the webpack config, and then you can edit it in a `vue.config.js` file.

We've checked out how we can take the basics of vue-loader, customized our Vue files, and use vue-cli to only need to delve into webpack when you totally need to. The big takeaways are:

* Additional customization for your .vue files, like using Pug, CSS, and more, is handled with loaders; support for writing a JS with your favorite languages happens at the build process
* vue-cli makes most of the work setting up that webpack config optional
* But learning webpack wasn't for nothing; it's still important knowing webpack because that's how vue-cli works behind the scenes; it builds on both Vue and webpack concepts! And knowing webpack means you can further customize building your web app.
* Knowledge of how to make plain Vue apps transfers over to single-file components, and knowledge of making SFCs transfers over to vue-cli.

So now you've seen how you can bring your knowledge from plain Vue, to a single-file-component arrangement of Vue code that a lot of big web apps use. For where to go next with this, I recommend trying out building a web app with Vue, either with plain .vue files, or in a configuration for using your favorite frontend languages.

And when it comes to vue-cli we really only touched the surface of what vue-cli gives you, so I also recommend taking a spelunk through the other files that vue-cli generated, since that's a really powerful tool building on the basics!