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"
}
Afterwards we would need to instal some Node modules for using Vue. The first one would be Vue itself.
npm install --save vue
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
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"
}
}
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'
};
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'
}
};
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'
}
]
}
};
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')
}
}
};
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"
}
}
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"
}
}
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>
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"
}
}
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
};
File path: src/components/hello/hello.html
<h1>Hello World</h1>
main.js
This is not only our entry point for webpack but although our file for instantiating Vue.
import Vue from 'vue';
new Vue({
});
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');
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');
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.
Top comments (13)
Sadly you're not just using ES6 modules, because you're also doing this:
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?
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.
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 alsovueify
for Browserify.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 :)
Well, it's not even that, actually. Webpack is fine as long as I don't bind my code to it 🙃
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.
That would be great!
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 :
build
andbuild:js
) which are only aliases to thewebpack
simple command ? I know that you will change this later but for now you are going to use only one of those... :).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
Hi Sylvain,
thanks for your feedback. You have two very legitimate questions. Let me try to answer both.
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 thewebpack
command from thepackage.json
to avoid installing dependencies on a global level because that could lead to version conflicts when using multiple projects..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.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 !
Yup that is something that I really like as well within the dev.to community.
The next chapter is already published. :)
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.
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.