How to write a Web application in 2021?

    • introduce
      • disclaimer
    • Language ability
    • The installation
      • Vue
      • Bundler
      • Optionals
    • Development
      • Add views and components
        • Views
        • Components
      • Dynamic pages
        • From the API for
        • The user to edit
      • Component library
    • Deployment way
    • troubleshooting
    • Q&A

introduce

In this article, I’ll walk you through the tools I use step by step. You can continue to learn, but it is more important to know why I am doing this than what I am doing. A good suggestion is to try the same steps with me in this tutorial. Then, try to change something bigger and bigger. Finally, at the end you should be able to do everything yourself again.

disclaimer

First of all, this is really important, and all of this is my bias against development. We all have a unique way of looking at things.

Web development is a huge and complex topic. This article is not intended to describe the easiest or fastest way.

But this is the approach I’ve loved since I was a child (for reasons I’m about to cover), and it’s the approach I can best explain in detail.

From here, I assume that you have a basic understanding of Java and Vue. I won’t go into the details of installing Node.js or using NPM.

Language ability

Let’s start with language.

I’ve been using Javascript for about a decade. It has a lot of detractors, but it was and remains my favorite language.

It is easy to use, has one of the largest communities, and can support huge applications.

Of course, I write in English. Although it is not my mother tongue, it is recognized as an international language.

The installation

Node.js is already installed on my computer, so I will use NPM to install all js dependencies.

The first thing I always do when starting a new project is

$ npm run init
Copy the code

This creates a package.json file. We then manually create the readme.md and.gitignore files as well as the SRC directory, which will be used later.

Preview of my project file system

Vue

I love Vue, it’s the one I use the most. Simple installation

$ npm install vue
Copy the code

Bundler

I prefer the modular template syntax provided by Vue. However, this is not native JS that browsers can understand. Therefore, it needs to be converted to use it.

I use Webpack for this. Installation is not that simple because we need more modules. First, let’s start with the Webpack itself and its CLI interface

$ npm install webpack webpack-cli
Copy the code

Then, we need to use its compiler to add plug-ins that process Vue files

$ npm install vue-loader vue-template-compiler
Copy the code

Finally, we can write the CSS, and now we need another pair of plug-ins to handle the CSS code

$ npm install css-loader style-loader
Copy the code

Now you need to configure Webpack. This is the least interesting part, but we need to understand this step to solve future problems.

Webpack can configure webpack.config.js with a file named webpack.config.js, so let’s create it.

That’s the minimum requirement. We’ll come back later if we need to extend it.

// Get the vue-loader plugin
const VueLoaderPlugin = require("vue-loader/lib/plugin");

// This is what the file exports
module.exports = {
    // My entry point
    entry: "./src/index.js".module: {
        rules: [
            // All Vue files use the vue-loader
            {
                test: /\.vue$/,
                loader: "vue-loader",},// All CSS files use css than style loaders
            {
                test: /\.css$/,
                use: [
                    "style-loader"."css-loader"
                ]
            },
        ],
    },
    plugins: [
        // Register the vue-loader plugin
        new VueLoaderPlugin(),
    ],
};
Copy the code

So that’s all over, we just have to run it on the terminal

$ webpack
Copy the code

See my project completely compressed and shrunk. This will fail temporarily, but rest assured.

Optionals

These tools are beyond the scope of this article. Maybe I’ll talk more about that in the next one.

I always use Eslint to check for potential errors in code. In order to use with my personal configuration, I run

$ npm install eslint eslint-plugin-vue @gmartigny/eslint-config
Copy the code

I tried to test my code to catch up on regressions and make sure I covered most of the use cases. I used AVA for testing and NYC for code coverage.

$ npm install ava nyc
Copy the code

Development

This is a lot of steps, and I haven’t written a line of code yet. All of this may seem like a lot, but trust me, it will make you faster in the future.

The more careful ones will remember that in my Webpack configuration, the entry file is./ SRC /index.js. So, let’s start there. Here we create an index.js file, SRC, and add a few lines of code to call Vue (with ESM).

// Import Vue, I prefer the ESM syntaxe
import Vue from "vue/dist/vue.esm.js";

// Create a new Vue instance targeted at the element with the id "app"
new Vue({
    el: "#app"});Copy the code

With this basic JS file, I can run it safely

$ webpack --mode=development --watch
Copy the code

Trigger Webpack in development mode (slower, but more descriptive of errors) with Watch (which rebuilds every time we change code). This creates a new file in the dist directory in main.js. This is the file my end user will use.

Now, we create an index.html file (usually in the public directory, but not necessarily).

<! DOCTYPE html> <html lang="en">
<head>
    <meta charset="UTF-8"> <title>Test</title> </head> <body> <! -- My target element --> <main id="app"></main> <! -- The JS file from webpack --> <script src=".. /dist/main.js"></script>
</body>
</html>
Copy the code

Opening the file in a browser will not show any expected results, but all is well. This is the status of my project so far.

Add views and components

Your Vue files should be split between views (individual screens, e.g., menus, about…) And components (write your comments, e.g. buttons, footers…) The two work in the same way, but do not share the same concerns. So, let’s add two directories (views and Components) SRC for sorting.

Views

Let’s start by creating a new view. This will be the Home page, so I’ll call it the file home.vue.

I use uppercase letters in the file name to indicate that it is a class from other OOP languages such as Java.

<template>
    <h1>Home</h1>
</template>

<script>
export default {
    name: "Home"}; </script>Copy the code

To get into the view, I have to tell my Vue instance to render. In the index.js file, I’ll add the necessary lines.

import Vue from "vue/dist/vue.esm.js";
// Import the view
import Home from "./views/Home.vue";

new Vue({
    el: "#app".// Declare it as a components I'll use (I know, views are treated as components by Vue)
    components: {
        Home,
    },
    // Render the view
    template: "<Home/>"});Copy the code

In order to have more views, you need to navigate between views, so vue-Router is required. Let’s not talk about it for the moment.

Components

Imagine that I want to make a simple card (title + text) for every movie I want to see, and I don’t want to repeat the code for each card. A good rule to follow is DRY (Don’t Repeat Yourself). If you write more than twice, you should break it into one place.

Similarly, I film. vue create a new file in the Components directory.

<template>
    <div class="film">
        <h2>Title</h2>
        <p>Text</p>
    </div>
</template>

<script>
export default {
    name: "Film"}; </script> <! -- scoped because I don't want to interfere with any other component --> Copy the code

And use it home.vue in.

<template> <div> <! -- Use the component --> <Film /> <Film /> <Film /> </div> </template> <script>// Import the component
import Film from ".. /components/Film.vue";

export default {
    name: "Home",
    components: {
        // Declare the component
        Film,
    },
};
</script>
Copy the code

As you can already see, I have three cards with the same title and text. This is not what I want. If I add properties to the Card component and write data to the main view, this will allow me to define values for each card.

<template>
    <div class="film"> <! -- Use properties here --> <h2>{{ title }}</h2> <p>{{ text }}</p> </div> </template> <script> exportdefault {
    name: "Film".// Properties list declaration
    props: ["title"."text"]}; </script> <style scoped> .film { border: 1px solid blue; } </style>Copy the code
<template> <div> <! -- Loop through my data --> <Film v-for="(film, index) in films" :key="index"
              :title="film.title" :text="film.text"/>
    </div>
</template>

<script>
import Film from ".. /components/Film.vue";

export default {
    name: "Home",
    components: {
        Film,
    },
    // data should be a function
    data () {
        // that return a set of values
        return {
            films: [
                {
                    title: "Alien",
                    text: "It follows the crew of the commercial space tug Nostromo, who encounter the eponymous Alien, an aggressive and deadly extraterrestrial set loose on the ship.",
                },
                {
                    title: "Interstellar",
                    text: "In a dystopian future where humanity is struggling to survive, it follows a group of astronauts who travel through a wormhole near Saturn in search of a new home for mankind.",
                },
                {
                    title: "Reservoir Dogs",
                    text: "Diamond thieves whose planned heist of a jewelry store goes terribly wrong.",}]}; }}; </script>Copy the code

Once set up, any changes applied to my data are reflected on the screen.

Dynamic pages

For example, I could fetch data from the API, or allow the user to edit the page (or select both 😉).

From the API for

First, I’ll get the data from the online simulation API. To do this, I first empty the data array. Then, depending on the Vue lifecycle, I can use functions to execute code when the view appears on the screen.

<template> <! -... --> </template> <script>import Film from ".. /components/Film.vue";

export default {
    name: "Home",
    components: {
        Film,
    },
    data () {
        return {
            // Emtpy film list
            films: [],
        };
    },
    async mounted (a) {
        // Fetch from mock API
        const response = await fetch("https://mock-film-api-t0jk5mabvwnt.runkit.sh/");
        if (response.ok) {
            // Load result into films list
            this.films = await response.json(); }}}; </script>Copy the code

The user to edit

Also, I can allow users to add new films to the list. A small HTML form that pushes a new entry when it submits will see the changes reflected in the view.

<template>
    <v-app>
        <Film v-for="(film, index) in films" :key="index"
              :title="film.title" :text="film.text"/ > <! -- Form that will call addFilm when submitted --> <form@submit="addFilm">
            <div>
                <label for="title">Title</label> <! -- v-model link the input value to a variable --> <input type="text" v-model="inputTitle" id="title">
            </div>
            <div>
                <label for="text">Text</label>
                <input type="text" v-model="inputText" id="text">
            </div>
            <button type="submit">Add</button>
        </form>
    </v-app>
</template>

<script>
import Film from ".. /components/Film.vue";

export default {
    name: "Home",
    components: {
        Film,
    },
    data () {
        return {
            films: [],
            // Holds the value of each input
            inputTitle: "",
            inputText: ""}; },async mounted (a) {
        // ...
    },
    methods: {
        // New method
        addFilm (event) {
            // Stop the form from reloading the page (default behavior)
            event.preventDefault();
            // Add a new film to the list
            this.films.push({
                title: this.inputTitle,
                text: this.inputText,
            });
            // Clear out input fields
            this.inputTitle = "";
            this.inputText = ""; ,}}}; </script>Copy the code

Of course, nothing will be saved online, and changes made when the page is reloaded will be lost. You can improve on this example by sending the request to a server that stores the input in a database.

Component library

I’m lazy. Being an effective developer often means being lazy. In addition to creating all the components, we can use an existing component library. This way, we can focus more on the content than on designing the date picker correctly.

Since I use Vue, I chose Vuetify, a Vue compatible library.

npm install vuetify
Copy the code

Very few changes are required to activate it index.js.

import Vue from "vue/dist/vue.esm.js";
// Get Vuetify and its CSS
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.min.css";

import Home from "./views/Home.vue";

// Prepare the usage of vuetify
Vue.use(Vuetify);
const vuetify = new Vuetify();

new Vue({
    // Pass the instance to Vue
    vuetify,
    el: "#app",
    components: {
        Home,
    },
    template: "<Home/>"});Copy the code

We can then use it anywhere in the application (film.vue).

<template> <! -- All Vuetify components are prefixed with"v-" -->
    <v-col cols="12">
        <v-card shaped>
            <v-card-title>{{ title }}</v-card-title>
            <v-card-text>{{ text }}</v-card-text>
        </v-card>
    </v-col>
</template>

<script>
    // ...</script> <! -- I don't need my crappy style anymore -->
Copy the code

Deployment way

One of my favorite recent discoveries is serverless. Basically, as long as your application is stateless (always returning the same results with the same parameters), you don’t need to have a complex, always-running server. By taking advantage of caching and resource sharing capabilities, you can reduce servers to almost zero.

With Vercel, we can freely host, deploy, and provide services with just a few clicks. Just put the project on Github.

troubleshooting

You are using the run-time build of Vue where the template compiler is not available. You are using the run-time version of Vue where the template compiler is not available.

The Vue you entered is incorrect. If you recall, there are many ways to import Vue. By default, import “vue” will call the vue.runtime.common.js file. In this code, the ESM is used in conjunction with the template (hence the need for vue.esm.js).

[Vuetify] Multiple instances of Vue detected/this.$Vuetify is undefined ([Vuetify] Multiple Vue detected/this. $vuetify not defined)

Your application and Vuetify do not import the “same” Vue. As mentioned above, it is important to import the Vue that is appropriate for your usage. A good solution is to create an alias in webpack.

// In webpack.config.js
module.exports = {
    // This will tell all your code to use the same Vue.
    resolve: {
        alias: {
            vue$: "vue/dist/vue.esm.js",}},// ...
};
Copy the code

Q&A

Why not import each Vuetify component when using them?

When we perform vue. use(Vuetify); In index.js, it will activate it throughout the project. When using them, it is possible to import only the Vuetify component. But this requires work that is beyond the scope of this tutorial.

Why not use X instead of Y?

I’m used to it. I’m sure you’ll find better alternatives to any of the tools or methods I’ve described above. But I know them. Ultimately, delivering is more important than endlessly learning new technologies.

What options do I have?

Vue:

  • React
  • Angular
  • Svelte

Vuetify:

  • Material-UI
  • Any CSS frameworks:
  • Bootstrap
  • Bulma
  • Tailwind

Webpack:

  • Rollup
  • Skypack

Vercel:

  • Netlify
  • Heroku