Vue-cli Webpack-Simple Tutorial

Click to share! ⬇️

Vue-cli Webpack-simple Tutorial

Vue.js has an optional command line interface for quickly building out the boilerplate for Single Page type Applications. It is similar in nature to the Angular CLI which makes building components easier. This sounds like fun, and something we should set up right away! The vue-cli tool gives us a “batteries-included” build environment that makes use of all those modern bells and whistles frontend tools you hear so much about today. Setting it up is easy and you’ll be up and running with hot-reload, lint-on-save, and production-ready builds in a snap.


Why vue-cli?

You may have had a nice introduction to Vuejs in many of the tutorials about Vue here and on the web at large. In fact, we have also seen how to use Vuejs with Laravel quite extensively. What about when you want to build a project exclusively in Vuejs and still get access to hot reloading, automatic file watching, linting, and so on? So instead of just linking to a CDN to get going in a static HTML page, we can now make use of vue-cli to build out an entire build process for us. This route optimizes our code, allowing us to make use of all the ES6 features while still building to a final application that will target all browsers. In addition to this, we’ll get access to a development server. Vuejs of course runs on the client, but the app will be served by a server nonetheless. When building your application locally, you want to be able to mimic this real-world scenario. The vue-cli tool makes this possible.


Benefits of using vue-cli

  • VueJs runs on the client
  • App is served from the server
  • App testing is now done under realistic circumstances
  • Not loading all files on startup (allows lazy loading)
  • Automatic Hot Reloading

Install vue-cli

Before we can get working with the vue-cli, we need to install it. Likely the first thing you want to do is determine where you would like to work. In our case, we have a directory named localdev, so we can cd into that directory. From here, we need to make sure node is installed.

C:localdev>node -v
v8.9.4

If you don’t have it, you can easily install node and then proceed. The following commands will get us up and running with the webpack-simple template for Vue. The following commands will install the vue-cli tool globally on your machine, initialize a vue webpack-simple template in a vue-cli folder, install all dependencies, and then finally launch the project.

C:localdev>npm install --global vue-cli
C:localdev>vue init webpack-simple vue-cli
C:localdev>cd vue-cli
C:localdev>npm install
C:localdev>npm run dev

You’ll likely see some output in the terminal such as

> vue-cli@1.0.0 dev C:localdevvue-cli
> cross-env NODE_ENV=development webpack-dev-server --open --hot

Project is running at http://localhost:8080/
webpack output is served from /dist/
404s will fallback to /index.html

If this all checks out, a new browser window should launch automatically and load up http://localhost:8080/ with this output.
vue-cli webpack-simple example

This means the development server provided by vue-cli is working perfectly and with that, you are now ready to rock and roll!


The Development Workflow

Now that we have the vue-cli tool working, we have some important benefits and changes to our workflow. Before shipping the application to the production server, we want to be able to apply special features to the project that only a development workflow can offer. A big benefit is the ability to compile single file components in the project. In other words, single files that have a .vue extension and have a <template> <script> and <style> section all in the same file. Single file templates are a really cool approach to building VueJS projects but you need this development workflow in order for them to be compiled down into usable code by a web browser.

vue-cli development workflow


The webpack-simple vue-cli folder structure

With our install and setup complete of the webpack-simple vuejs cli tool, let’s open up the directory holding our project in your favorite IDE.
vue-cli folder structure

Let’s talk a little about this folder structure and the files contained in the default webpack-simple vue-cli project.

  • babelrc file: This file sets up Babel for us so that we can easily make use of ES6 and it will be transpiled down to ES5 during the build compilation process.
    {
      "presets": [
        ["env", { "modules": false }],
        "stage-3"
      ]
    }
  • index.html file: This is the file that actually gets served. Note that the script tag references a build.js file. This file contains the code that has been built by webpack. This is what allows us to break out our source code into various components and files that make sense to us, and then everything is bundled into one file during the build process. This approach makes the developer experience more pleasant, while still allowing for a nice lightweight final product. The vue-cli tool does all the heavy lifting for you which is nice.
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>vue-cli</title>
      </head>
      <body>
        <div id="app"></div>
        <script src="/dist/build.js"></script>
      </body>
    </html>
  • package.json file: This file manages all of the dependencies for development and production. Note the inclusion of the vue-loader dependency which is what allows us to make use of those slick .vue single file templates.
    {
      "name": "vue-cli",
      "description": "A Vue.js project",
      "version": "1.0.0",
      "author": "Vegibit",
      "license": "MIT",
      "private": true,
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
        "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
      },
      "dependencies": {
        "vue": "^2.5.11"
      },
      "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
      ],
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-env": "^1.6.0",
        "babel-preset-stage-3": "^6.24.1",
        "cross-env": "^5.0.5",
        "css-loader": "^0.28.7",
        "file-loader": "^1.1.4",
        "vue-loader": "^13.0.5",
        "vue-template-compiler": "^2.4.4",
        "webpack": "^3.6.0",
        "webpack-dev-server": "^2.9.1"
      }
    }
  • webpack.config.js file: This is the configuration essentially for the webpack tool included with the vue-cli.
    var path = require('path')
    var webpack = require('webpack')
    
    module.exports = {
      entry: './src/main.js',
      output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
      },
      module: {
        rules: [
          {
            test: /.css$/,
            use: [
              'vue-style-loader',
              'css-loader'
            ],
          },      {
            test: /.vue$/,
            loader: 'vue-loader',
            options: {
              loaders: {
              }
              // other vue-loader options go here
            }
          },
          {
            test: /.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
          },
          {
            test: /.(png|jpg|gif|svg)$/,
            loader: 'file-loader',
            options: {
              name: '[name].[ext]?[hash]'
            }
          }
        ]
      },
      resolve: {
        alias: {
          'vue$': 'vue/dist/vue.esm.js'
        },
        extensions: ['*', '.js', '.vue', '.json']
      },
      devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true
      },
      performance: {
        hints: false
      },
      devtool: '#eval-source-map'
    }
    
    if (process.env.NODE_ENV === 'production') {
      module.exports.devtool = '#source-map'
      // http://vue-loader.vuejs.org/en/workflow/production.html
      module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: '"production"'
          }
        }),
        new webpack.optimize.UglifyJsPlugin({
          sourceMap: true,
          compress: {
            warnings: false
          }
        }),
        new webpack.LoaderOptionsPlugin({
          minimize: true
        })
      ])
    }

The main.js file

The main.js file is the first file that gets executed when the bundle, or build.js, gets loaded on the index.html page. What is happening in this file is, a new Vue instance is created. We are able to do this because we are importing the Vue library from vue folder as seen in the first line of this file. We also see the familiar setting of the element to be the target of Vue, in this case, it is the element that has the id of #app. The div element in the index.html file has this id. The render function is used to overwrite the element in the index.html file with what is rendered by the App.vue file. One way to look at the code below is that the render: h => h(App) line renders a template and puts it in the place of the el: '#app', element. The App.vue file which is imported on line 2, is what is getting passed to be rendered by the h function.

import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App)
});

Single File App.vue Template

This leads us to the main purpose of using this approach. The App.vue file. Vue files will always follow a specific structure. They have three distinct sections. A <template>, a <script>, and a <style> section. Here are the three sections with the example code provided by the vue-cli tool.

<template>
    <div id="app">
        <img src="./assets/logo.png">
        <h1>{{ msg }}</h1>
        <h2>Essential Links</h2>
        <ul>
            <li><a href="https://vuejs.org" target="_blank" rel="noopener noreferrer">Core Docs</a></li>
            <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener noreferrer">Forum</a></li>
            <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener noreferrer">Community Chat</a></li>
            <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener noreferrer">Twitter</a></li>
        </ul>
        <h2>Ecosystem</h2>
        <ul>
            <li><a href="http://router.vuejs.org/" target="_blank" rel="noopener noreferrer">vue-router</a></li>
            <li><a href="http://vuex.vuejs.org/" target="_blank" rel="noopener noreferrer">vuex</a></li>
            <li><a href="http://vue-loader.vuejs.org/" target="_blank" rel="noopener noreferrer">vue-loader</a></li>
            <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener noreferrer">awesome-vue</a></li>
        </ul>
    </div>
</template>

<script>
    export default {
        name: 'app',
        data() {
            return {
                msg: 'Welcome to Your Vue.js App'
            }
        }
    }
</script>

<style>
    #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;
    }

    h1, h2 {
        font-weight: normal;
    }

    ul {
        list-style-type: none;
        padding: 0;
    }

    li {
        display: inline-block;
        margin: 0 10px;
    }

    a {
        color: #42b983;
    }
</style>

This example .vue file that ships with the webpack-simple template for the vue cli tool gives us a great example of how the workflow works, not to mention some great links to some very helpful resources of:


Getting Started

With everything installed and working great, we can now start our own application. We can empty out the template, script, and style sections and fill in a bare bones example of getting started. Think “Hello World” type stuff here.

<template>
    <h1>Welcome To Vue cli!</h1>
</template>

<script>
    export default {

    }
</script>

<style>

</style>

As long as npm run dev is still running from the terminal, your browser will hot-reload automatically thanks to the tools included with vue cli. Also, note the Vue chrome plugin is illuminated indicating that it detects a web page that is Vue enabled.
vue cli up and running


The Exported Object

Notice how in the script section of the .vue file we are exporting an object. The key to remember about this exported object is that it is a Vue instance. Therefore it behaves and encompasses everything we know about setting up a Vue instance such as using a data object, a methods object, a computed object, and so on and so forth. To be fair, when using this approach, the data object is actually returned from a function. This is so that each Vue instance has its own data, and there are no collisions between objects.


npm run build

Right now we are simply using npm run dev to work with and test out an installation of the vue cli tool. This is great for testing in the local environment, but what about if you actually want to publish your application to the web? In this case you will instead run npm run build. This will build your application for production and you’ll see a new dist folder which contains the finished bundle. In addition, many optimizations are run during the build process such as minification, transpiling, and file size compression.


Vue-cli Webpack-Simple Tutorial Summary

As you can see the vue-cli software is a really cool tool to work with. It helps us create better workflows based on the available templates provided. In our case, we made use of webpack-simple, which is a good middle ground between a bare-bones approach and a full-blown development environment. You can choose between templates such as webpack-simple, webpack, pwa, browserify, simple, and browserify-simple. You can learn all about these templates at github if you are interested. With our cli installation complete, we now have access to those fantastic .vue Single File Templates. We saw that these files contain those 3 distinct sections of template, script, and style. This is a special feature of Vuejs that makes writing your Vue instances or components very developer-friendly.

Click to share! ⬇️