DEV Community

Cover image for An introduction to Vue.js - Chapter 1 - Basic Setup
Moritz Schramm
Moritz Schramm

Posted on • Edited on

An introduction to Vue.js - Chapter 1 - Basic Setup

Series overview

Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5

Foreword

I recently started working with Vue.js in a more deeper way. I figured out that it isn't that hard to get into it but will get harder after some time to get more insides into that area.

I decided to write a series of Vue guides how you could possible handle certain things in your project. I like the way I will describe to you but of course it is not the overall solution for healing the world. It just a best practice I figured out while working with Vue.

I will always upload the code to this github repository.

So now lets start with our first chapter.

Node.js Modules

First of all we need to setup a simple Node project. I would recommend you to do this via command line by using the npm init command which will do a small wizard with you to create the package.json. I removed some parts of the generated package.json and it finally looked like that:

{
  "name": "chapter1",
  "version": "1.0.0",
  "description": "Chapter 1 of the Vue Guide",
  "author": "Moritz Schramm",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

Afterwards we would need to instal some Node modules for using Vue. The first one would be Vue itself.

npm install --save vue
Enter fullscreen mode Exit fullscreen mode

I will use webpack as my "compiler" and babel as a transpiler. Moreover we will need raw-loader to load html files via ES6 Modules.

npm install --save-dev webpack babel-core babel-loader raw-loader
Enter fullscreen mode Exit fullscreen mode

You should now have a node_modules folder and your package.json should look like that (the version strings could differ):

{
  "name": "chapter1",
  "version": "1.0.0",
  "description": "Chapter 1 of the Vue Guide",
  "author": "Moritz Schramm",
  "license": "ISC",
  "dependencies": {
    "vue": "2.4.4"
  },
  "devDependencies": {
    "babel-core": "6.26.0",
    "babel-loader": "7.1.2",
    "raw-loader": "0.5.1",
    "webpack": "3.6.0"
  }
}

Enter fullscreen mode Exit fullscreen mode

The Webpack Configuration

We will configure the webpack build through the webpack.config.js. For that we would need to create that file on the same level as the package.json.

First of all we need to define were the webpack should actually start "compiling". From my setup it should start from the file src/main.js.

module.exports = {
    entry: './src/main.js'
};
Enter fullscreen mode Exit fullscreen mode

Now we need to tell webpack were to put the bundled file. I love to put that into a separated folder called bin and the filename would be build.js.

const path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, 'bin'),
        filename: 'build.js'
    }
};
Enter fullscreen mode Exit fullscreen mode

Since webpack works with loaders we would need to define which we would like to use (we installed raw-loader and babel-loader). The babel-loader we use for our .js files and raw-loader for .html files.

const path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, 'bin'),
        filename: 'build.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.html$/,
                loader: 'raw-loader'
            }
        ]
    }
};
Enter fullscreen mode Exit fullscreen mode

Now we need to define some alias to get Vue.js to work. The first one we need to import Vue.js in the correct and full version, the second one is to avoid later import path that could look like that: ../../../common/button/button rather then doing app/components/common/button/button

const path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, 'bin'),
        filename: 'build.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.html$/,
                loader: 'raw-loader'
            }
        ]
    },
    resolve: {
        alias: {
            vue: 'vue/dist/vue.js',
            app: path.resolve(__dirname, 'src')
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

That's it for now with our webpack configuration.

NPM Scripts

Luckily npm offers a script function were we could execute commands from our command line with out creating a bunch of weird looking bash scripts executing stuff from the deep of our node_modules folder.

These scripts can be defined in our package.json.

{
  "name": "chapter1",
  "version": "1.0.0",
  "description": "Chapter 1 of the Vue Guide",
  "author": "Moritz Schramm",
  "license": "ISC",
  "scripts": {

  },
  "dependencies": {
    "vue": "2.4.4"
  },
  "devDependencies": {
    "babel-core": "6.26.0",
    "babel-loader": "7.1.2",
    "raw-loader": "0.5.1",
    "webpack": "3.6.0"
  }
}

Enter fullscreen mode Exit fullscreen mode

I created a script called build and one called build:js.

{
  "name": "chapter1",
  "version": "1.0.0",
  "description": "Chapter 1 of the Vue Guide",
  "author": "Moritz Schramm",
  "license": "ISC",
  "scripts": {
    "build": "npm run build:js",
    "build:js": "webpack",
  },
  "dependencies": {
    "vue": "2.4.4"
  },
  "devDependencies": {
    "babel-core": "6.26.0",
    "babel-loader": "7.1.2",
    "npm-run-all": "4.1.1",
    "raw-loader": "0.5.1",
    "webpack": "3.6.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

The build script currently calls only the build:js script but will later get more calls. The build:js executes webpack using our webpack.config.js.

Some code

After configuring a bunch of stuff we now created some code to test the whole stuff and add another step to our build script.

First of all we need to create a src folder as we configured in our webpack configuration.

index.html

Within that folder we add the index.html which should look like that:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />

    <title>Vue Guide</title>
</head>
<body>
    <div id="app"></div>

    <script src="build.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The index.html includes our build.js generated by webpack. We need to copy that file over into the bin folder a well so I added another script called deploy:resources and called it in the build script (I installed npm-run-all via npm install --save-dev npm-run-all to ease the way of calling multiple npm scripts).

{
  "name": "chapter1",
  "version": "1.0.0",
  "description": "Chapter 1 of the Vue Guide",
  "author": "Moritz Schramm",
  "license": "ISC",
  "scripts": {
    "build": "npm-run-all build:js deploy:resources",
    "build:js": "webpack",
    "deploy:resources": "cp src/index.html bin/index.html"
  },
  "dependencies": {
    "vue": "2.4.4"
  },
  "devDependencies": {
    "babel-core": "6.26.0",
    "babel-loader": "7.1.2",
    "npm-run-all": "4.1.1",
    "raw-loader": "0.5.1",
    "webpack": "3.6.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

hello component

That part I will not explain for now. You can simply copy over the code. I will go deeper into that topic in one of the next chapters.

File path: src/components/hello/hello.js

import template from './hello.html';

export default {
    name: 'vg-hello',
    template
};
Enter fullscreen mode Exit fullscreen mode

File path: src/components/hello/hello.html

<h1>Hello World</h1>
Enter fullscreen mode Exit fullscreen mode

main.js

This is not only our entry point for webpack but although our file for instantiating Vue.

import Vue from 'vue';

new Vue({
});
Enter fullscreen mode Exit fullscreen mode

We need to tell Vue were to mount the app initially (render point in the DOM which is in our case the div with the id app).

import Vue from 'vue';

new Vue({
}).$mount('#app');
Enter fullscreen mode Exit fullscreen mode

Finally we would need to tell Vue which component to render a startup.

import hello from 'app/components/hello/hello';
import Vue from 'vue';

new Vue({
    render: (h) => h(hello)
}).$mount('#app');
Enter fullscreen mode Exit fullscreen mode

Done

We you now run npm run build from your command line you should find a bin folder with a build.js and index.html. Open that index.html in your favourite web browser (e.g. Chrome or Firefox) and you should the "Hello World".

Last words

I hope you like that way of describing the setup of a Vue project. I know there are a lot of different ways to do so (e.g. not using webpack, using .vue files, ...) but I like the way using ES6 modules. If you have some feedback, feel free to add it and if you have questions, just ask them on Twitter or in the comment section. I will try to answer as much as possible.

Next Chapter: Components (Part I)

Top comments (13)

Collapse
 
maxart2501 profile image
Massimo Artizzu

I like the way using ES6 modules

Sadly you're not just using ES6 modules, because you're also doing this:

import template from './hello.html';

ES6 modules can't load HTML files. This is an extension to ES6 modules. A custom extension created in Webpack's ecosystem but ultimately custom. Which means you might think you're just using JavaScript, but actually you're not.

The problem here is that Webpack could be a thing of the past in a couple of years and you'd end up with code that needs to be fixed before updating the project. I'm really not a fan of that.

I'd rather use .vue files, at least the intent is clear. Will you explain how to use them in a future chapter?

Collapse
 
neradev profile image
Moritz Schramm

You are right. These imports are not fully ES6. That's why we needed to include the raw-loader. Since this is bundled by webpack you will not get the possibility of using the full functionality of ES6 modules (e.g. load when it is need) out of the box. Still it looks and feels like writing code for ES6 modules.

Some words about your argument Webpack could get a thing of the past in some years: It is the same with everything when we are talking about library driven development. Who knows whether Vue itself will get not maintained anymore? Then the whole code will get useless. There is never a certain guarantee that we can use the tools forever (especially in JS development).

It was not planned that I describe how to use .vue files since I personally do not work with them for certain reasons. But I will explain it in a later chapter and show you my opinion.

Thanks for your feedback.

Collapse
 
maxart2501 profile image
Massimo Artizzu

Some words about your argument Webpack could get a thing of the past in some years: It is the same with everything when we are talking about library driven development.

Sure, Vue could be a goner too, but the same Webpack stains in JavaScript code could be seen in other frameworks. The main difference is that while Vue (or React or whatever) are the core of possibly long spanning projects, Webpack is just a bundling tool - a devDependency. Something that should allow us to replace it entirely if we feel like it. So why are we adapting our core code to use a bundler, and not vice versa? Why are we locking ourselves into Webpack's ecosystem?

If I take an AngularJS project from 2012, I could switch its bundling system from Grunt to Gulp or even Webpack without touching the application's source code. It's not the same if I import html, though.

That's why I'd use .vue files instead: it's a specification from Vue, not from Webpack. So there's vue-loader for Webpack, but there's also vueify for Browserify.

Thread Thread
 
neradev profile image
Moritz Schramm

Now I got your point. That is an issue that could come up at some point in the future. I agree to your argumentation but not completely that you should not use the Webpack ecosystem to write your code. I like writing code within that ecosystem and I would have no problem with adapting the code when my ecosystem changes.

But I really respect your arguments against using Webpack.

Thanks for that great sharing :)

Thread Thread
 
maxart2501 profile image
Massimo Artizzu

you should not use the Webpack ecosystem

Well, it's not even that, actually. Webpack is fine as long as I don't bind my code to it 🙃

Thread Thread
 
neradev profile image
Moritz Schramm

Yeah I don't have a problem with that but of course some people would say it is a huge pain point. I think I found a setup with browserify. I will try it out within the next day and will give it an additional chapter.

Thread Thread
 
maxart2501 profile image
Massimo Artizzu

That would be great!

Collapse
 
martyonthefly profile image
Sylvain Marty • Edited

Hi Moritz,

Your tutorial is nice and your explanations are very clear !

I have a few questions about some choices you have made for this tutorial :

  • Why adding extra runtime scripts (build and build:js) which are only aliases to the webpack simple command ? I know that you will change this later but for now you are going to use only one of those... :)
  • Why didn't you use the VueJS template resolver with .vue files ? You have setted up Webpack and Babel but you loose some great features that provide .vue files like scoped style, template linter, etc.

Thanks for sharing ! :)

Edit: some misspelling... Oops

Collapse
 
neradev profile image
Moritz Schramm

Hi Sylvain,

thanks for your feedback. You have two very legitimate questions. Let me try to answer both.

  1. As you can see we already added one additional script for copying the index.html to the correct folder what should also be done in a build script even though it is not part of the usual Webpack compiling. Moreover I call the webpack command from the package.json to avoid installing dependencies on a global level because that could lead to version conflicts when using multiple projects.
  2. I do not prefer working .vue files for multiple reasons. Since you are not the first one asking for Single File Components, I will write a chapter just about this and why I do not like working with them.
Collapse
 
martyonthefly profile image
Sylvain Marty

I didn't thought about conflicts when installing global dependencies ! This is a good point ;)

It's very cool to have differents opinions :)

I look forward to read your next chapter !

Thread Thread
 
neradev profile image
Moritz Schramm

Yup that is something that I really like as well within the dev.to community.

The next chapter is already published. :)

Collapse
 
tamas profile image
Tamás Szelei

Very nice intro, thanks for starting this series. As an outsider to web development, it seems to me that the era of "javascript fatigue" is still not over. It takes an enormous amount of complexity (and redundancy) to set up a basic js project with npm and webpack. I understand that this complexity does not grow quickly with the size of the project, it's just that there is so much stuff going on that even a C++ project is easier to get started on.

Collapse
 
neradev profile image
Moritz Schramm

I agree it sometimes feels like there is a little bit to much overhead currently. But still I like to configure such stuff even in a more complex way. And of course I really do love Web development.

Thank you for your feedback.