Vue.js, Webpack, Vueitify, Electron, and vue-cli
Introduction #
Vue.js is a reactive progressive framework that allows the creation of Javascript apps. It is very
similar to React. This tutorial is a guide to using vue-cli
(which is
similar to create-react-app
) in order to create a
project that supports Material Design (thru Vuetify), Electron, and Webpack.
Here’s another tutorial that serves as an introduction to Vue.
Starter project repo #
Here’s a GitHub repo
that I created as the end result of going thru this tutorial. This project can be used as a starter
project that is built using vue-cli-3
which allows for the use of Webpack, Vue, Vuetify (Material
Design), and Electron (along w/ lodash
, and axios
).
Run the project #
Task | Command |
---|---|
Project setup | npm install |
Compiles and hot-reloads for development | npm run serve |
Compiles and minifies for production | npm run build |
Lints and fixes files | npm run lint |
Step by step guide to buiding this starter project #
Instructions on getting started w/ Vue-cli3, electron, vuetify. The following steps will guide you thru creating this project from scratch if you choose, instead of getting the GitHub repo.
Install vue-cli-3 #
fix-brew.sh
npm install -g @vue/cli
Setup the new project #
Run the project (in browser or Electron) #
- in electron -
npm run serve:electron
- in browser -
npm run serve
Add dependencies #
npm add axios lodash
- Use them by doing a simple import (eg in main.js,
import _ from 'lodash';
)
References / Documentation #
- Step by step tutorial of using vue-cli, etc
- Single file components (.vue files)
- Developing apps generated by
vue-cli
- Tool for theming and customizing Vuetify
Deep dive into the code #
Now that we have the mechanics of creating this project out of the way, let’s look at how this project is organized and some of the interesting elements in it. Here are some files that we are going to cover in depth.
src/
+--- main.js
+--- App.vue
+--- components/
+--- HelloWorld.vue
+--- plugins
+--- vuetify.js
main.js #
Webpack takes all the HTML, CSS, and JS files in the project, packages and minifies them. This
main.js
file ends up being the main entry point for the code in our project.
1. Mounting to the DOM #
new Vue({ render: (h) => h(App) }).$mount("#app")
There’s an index.html
file in the public/
folder which has a div
with id
of app
. The line
of code above mounts the root Vue component App
to this div
.
2. State or application object model #
The first thing that I do here is setup the data which serves as the application model or shared state between all the Vue components that are created.
export const appData = {
app_icon: "code",
body_message: "Hello world!",
footer_message: "Made with ❤️ in Mountain View, California",
title: "Vue, Vuetify, Webpack",
time: new Date(),
}
The appData
object is the state of the application. And when this data changes, Vue components in
this project will react and refresh themselves to stay up to date w/ the data in this object.
setInterval(() => {
appData.time = new Date()
}, 1000)
The code above updates the value of appData.time
every second w/ the current date. When you run
the code, you will see that the footer of the web app shows the current time updating every second.
Let’s take a look at the root Vue component App
to see how this is accomplished.
App.vue #
In main.js
you will find the following import statement.
import App from "./App.vue"
This loads the App
Vue component to be mounted to the DOM. Let’s take a closer look at this root
Vue component. The App.vue
file has 3 things in one place:
<template>
that contains the template that will be used to stamp out this component in the DOM.<script>
that contains the JS code that is associated w/ this component. There are some interesting things that you should watch out for as you write functions in this block (especially with regards to howthis
is handled in functions that you write within these<script
> tags).<style>
that contains CSS fragments that you can apply only to this component and not pollute the rest of your DOM.
1. Script #
In the case of App.vue
, here’s the <script>
section.
import HelloWorld from "./components/HelloWorld"
import { appData } from "./main"
export default {
name: "App",
components: {
HelloWorld,
},
data: () => {
return appData
},
}
The main thing to note here is that an object is exported via default
. This is the object which
was imported in main.js
and mounted to the DOM. This object represents options that are used by
Vue to create the Vue component itself (new Vue({render: h => h(App)}).$mount('#app');
) in
main.js
.
The data
function provides access to all the state information that will be available to App
component, and portions of this state will be passed around as props to other components that are
needed. In this case, we have HelloWorld
component that is needed by App
. You can see that this
HelloWorld
component is loaded using an import statement above.
You can see the HelloWorld
tag used in the <template>
section below.
2. Template #
And here’s the <template>
section.
<v-app dark>
<v-toolbar app dark color="primary">
<v-icon>{{app_icon}}</v-icon>
<v-toolbar-title>{{title}}</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-content>
<HelloWorld v-bind:msg="body_message" />
</v-content>
<v-footer app>
<v-spacer></v-spacer>
<span class="surface--text"> {{footer_message}} ⏱ {{time}} </span>
<v-spacer></v-spacer>
</v-footer>
</v-app>
The App
component is the root, which is why it provide data
. You will see in the HelloWord
component below, that it doesn’t have any data
. Instead it has to rely on the use of props in
order to get information.
3. Props #
The HelloWorld
component is declared and passed a props msg
via v-bind:
attribute, and the
body_message
object is passed to it. This body_message
object is loaded from the Vue component’s
data, that is just prodding access to the appData
object which was declared in main.js
.
Vue actually wraps the underlying appData
object w/ a proxy, which is how the ‘reactivity’ is
implemented in the Vue framework.
There are some other places in the template where you see code appearing between {{
and }}
.
These are all references to objects that are made available by the Vue component’s data
property
(which just provides access to appData
).
4. Material Design and Theming #
And there are quite a few tags like v-app
and v-toolbar
etc. These are all part of the Vuetify
Material Design library. Here’s a quick rundown of what these do.
v-app
This is the root tag for any Vuetify application. Thedark
attribute marks this to have the dark theme. Vuetify doesn’t really manage themes in the way that I thought it would. Eg: overriding the theme doesn’t really propagate the color choices, etc to existing components. More on this below.v-toolbar
This is the toolbar component, to which I’ve added some attributes for styling. Even though I provided a custom theme to Vuetify which is loaded viavuetify.js
inmain.js
, my color choices forprimary
,secondary
, etc didn’t propagate to the existing components 😡. So I had to explicitly provide attributes to each tag to specify my color choices. In this case I applied the background color toprimary
and then applieddark
so that the icon and text colors would be inverted, so that they would have good contrast. I shouldn’t have to do this, and will be exploring other Material Design libraries for Vue in the future (that are not Vuetify).v-content
This holds the main content of the app between the header and the footer. This is where theHelloWorld
component is rendered.v-footer
This holds the footer of the app, and has the time which gets updated. One interesting thing to note here, related to themeing is that I created a color calledsurface
in my custom them (vuetify.js
). In order to apply this color to the text, I do this:
<span class="surface--text"></span>
However, in the code you could also have done something like this:
<span class="primary--text"></span>
Get the code #
You can get the code used in this tutorial in the vue_webpack GiHub repo.
👀 Watch Rust 🦀 live coding videos on our YouTube Channel.
📦 Install our useful Rust command line apps usingcargo install r3bl-cmdr
(they are from the r3bl-open-core project):
- 🐱
giti
: run interactive git commands with confidence in your terminal- 🦜
edi
: edit Markdown with style in your terminalgiti in action
edi in action