DEV Community

Andy Haskell
Andy Haskell

Posted on

Going from .vue files to vue-cli

In the last tutorial, 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.

🏠 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:

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

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
Enter fullscreen mode Exit fullscreen mode

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

{
  test: /\.pug$/,
  loader: 'pug-plain-loader',
},
Enter fullscreen mode Exit fullscreen mode

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:

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

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:

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

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
Enter fullscreen mode Exit fullscreen mode

⚠️ 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...

{
  test: /\.css$/,
  use: [
    'vue-style-loader',
    'css-loader',
  ]
}
Enter fullscreen mode Exit fullscreen mode

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.

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
Enter fullscreen mode Exit fullscreen mode

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:
- import ColorPicker from './ColorPicker.vue';
+ import ColorPicker from './components/ColorPicker.vue';
Enter fullscreen mode Exit fullscreen mode

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

yarn add --dev pug pug-plain-loader
Enter fullscreen mode Exit fullscreen mode

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

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!

Top comments (0)