How to Create an App with Vue CLI

vueMarch 20, 2020

Vue has great tools to work with, starting with Vue CLI. It allows you to create a feature-rich app nearly instantly. Indeed, it helps us set our Vue project that supports a lot of popular JS tools such as Webpack, Babel, etc.

As a prerequisite, we will need Node.js installed on our machines.

Note : if you're a macOS user, you can install Node faster using Homebrew, just run brew install node.

Before creating a project, you'll need to install Vue CLI first:

npm install -g @vue/cli
  1. Run vue create example
  2. You have two choices: the default (which enables babel and eslint) or select Manually select features. For educational purposes, we will choose Manually select features.
  3. You have different options here: Babel, TypeScript, PWA, Router, etc. You can see how easy it is to add a tool to the codebase. Here, let's select Babel, Linter/Formatter
  4. Select ESLint with error prevention only
  5. Select Lint on save
  6. Select In dedicated config files for Babel, PostCSS, ESLint, etc.
  7. Answer yes or no. Depends on if you like this preset!
  8. Select your favorite package manager. Here I'll pick Use Yarn.
  9. Vue CLI will do the setup now. You should see a progress bar that is gradually filling...
  10. You see 🎉 Successfully created project example.
  11. Follow the instructions provided by Vue CLI (cd example && yarn serve)
  12. Open your browser and visit http://localhost:8080/

Congratulations! You have built your first Vue app using Vue CLI.

Open your newly created project with your favorite code editor (I recommend VS Code, it's kinda the default tool for front-end devs as of today).

The commands

As seen before, creating a default project with Vue CLI comes with Babel and ESLint enabled by default. One important thing to note is that Vue CLI projects use Webpack: a module bundler.

Basically, Webpack analyzes all your modules and JS files, preprocesses them, and bundles them into one minified file. To preprocess files, Webpack uses loaders that transform your source code. For example, Vue has their own loader because of the .vue files. We'll see that in a bit.

Your Vue CLI project comes with three package.json scripts:

  • serve: this command starts a dev server that comes with Hot-Module-Replacement. It roughly means that when you change your code, your app reloads instantly (and that's what you call a great developer experience 😄)
  • build: this command produces a production-ready bundle in a dist/ directory, minifying JS/CSS/HTML and auto vendor chunk splitting for better caching. The chunk manifest is inlined into the HTML. These complex words mean your app will be smaller and faster when deploying to production.
  • lint: lint your files using ESLint. If ESLint doesn't mean anything to you, it's a tool for identifying and reporting on patterns found in JS code, with the goal of making code more consistent and avoiding bugs. It's considered a best practice to have it in a project, and that's why Vue provides it as a default.

If you're curious, another command called inspect allows you to inspect the webpack config inside a Vue CLI project. You can run npx vue-cli-service inspect > config.js to see what's your config.

The generated files

Do you feel overwhelmed by the number of files? Don't worry. I'm going to give you a quick overview of the files Vue CLI generated.

public folder :

  • favicon.ico: do you see the little icon on the left on your current tab? That's called a favicon. It's an icon that represents your app or your website.
  • index.html: this is your main HTML file. It will contain all your Vue code. You can see at the bottom of the file this line: <div id="app"></div>. That's important since it's where Vue will mount your app.

src folder :

  • assets folder: this is where you will put your assets, say your images, your icons, etc.
  • components folder: well, this is self-explanatory here. It contains your Vue components.
  • App.vue: this is the main component mounted to the DOM.
  • main.js: this is your app entry point. This file is responsible for mounting your App component into the DOM, specifically in the #app div you saw in index.html.

.browserslistrc: this file allows us to define which browsers we want to target to generate the optimal output files. Here, the file targets all browser versions that have more than 1% of market shares (> 1%) and the last two versions of each browser (last 2 versions). You can visualize them on

.eslintrc.js: it configures which linting/formatting style guide we will follow. Linting and formatting is great to use in any projects as it allows to have a common style guide with other developers.

.gitignore: your project already includes Git if you cloned the repository. To make sure you don't put any sensitive files, build folders, or anything like this onto GitHub (or GitLab, BitBucket, etc), you just need to put in this file what you don't want to push to your repository.

babel.config.js: If you never heard of Babel before, this one might be hard to understand. JavaScript is constantly evolving. Each year you see new features coming. But these features are not available for all browsers or old browsers versions. Simply put, Babel enables us to transpile the new JavaScript code into the old one so that our code works on most browsers. Therefore, we can use the very last features of JavaScript without worries. Here, Babel will produce a JavaScript code compatible with the browsers defined in browserlistrc.

package.json: this file contains various metadata about your project : name, version but mostly dependencies and scripts. For example, when you ran yarn install, yarn fetched the dependencies using your package.json file, installed them in the node_modules folder and generated yarn.lock. that's what holds the instructions to install the app.

yarn.lock: It's a file generated by yarn that stores the dependencies version of the packages you use.

Single File Components

Look at the App.vue file. If you already played around with Vue.js you may have defined your Vue instance like this:

new Vue({
el: "#app",

And components like this:

Vue.component("my-component", {
// ...
template: `<div>...</div>`,

That worked fine. So why App.vue is structured differently?

There are many reasons:

  • Styling: how would you style your components? By defining a CSS file out of the component's scope and importing it in your HTML file? That makes the CSS global.
  • Templating: what about these template strings you use in your components? Don't they look a bit ugly?
  • Building: we can't use the latest JS features because we can't really add builds steps.

That's why Vue uses single-file components. They're structured very clearly:

  • template: Your HTML elements, Vue directives, etc.
  • script: All that is linked to the Vue instance: data, methods, etc.
  • style: Your CSS code.

For example, here is the App.vue file:

<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
  • In the <template>, there is an image and a component you imported.
  • In the <script>, you define your Vue component and specify which components you use in your <template>
  • In the <style>, you define the CSS code you use. Caution, here the CSS is global as App.vue is the main file. But if you go to HelloWorld.vue, you'll see <style scoped>: it means your CSS defined in HelloWorld.vue will be limited to it.

Note: if you're coding with VS Code, I recommend that you install the Vetur extension. It's going to make our life easier when building a Vue project (Syntax highlighting, snippets, etc).

Single-file components has many advantages over what we used to do:

  • CSS: we bring CSS directly into the component. And you know what's even more awesome? You can restrict the CSS scope to the component only. No more CSS rules conflicts!
  • Modularity: components have their own file and all is scoped to the component only. Therefore, composing components is easier to do.
  • Building: as we can include build steps to the project, we can use latest JS features, linting, etc.

Vue DevTools

When coding, it's very useful to have tools to improve your developer experience. Good news for you, Vue has dev tools that you can use! They allow you to explore your project structure (your components), filter them, visualize your tree structure, inspect your components' data, see the emitted events in real-time, inspect performances, etc. You can install them from here:

Once you installed it, you should see a "V" icon in your toolbar. Then, you can open your developer's tools (inspect) and search for the Vue tab.