How to build an environment of [TypeScript + Vue + Express + MySQL] with Docker ~ Vue edition ~

Contents

This article is studying Vue but wants to build an app based on TypeScript! It is a content to actually build an environment from scratch for those who say! By the way, I will build it with Docker and create an application that runs in a container environment!

As for the configuration, I will aim for an environment that has module extensibility while building Docker + Vue.js + Express (Node.js) + MySQL based on TypeScript!

Aiming state

  1. Application container
  1. API server container
  1. Database container

スクリーンショット 2020-09-14 23.47.05.png

"Vue-> Vuex-> HTTP communication (Axios)-> API (Express)-> MySQL data acquisition (Sequelize)-> Store response (Express)-> Vue" It will be the flow.

Target person

--Docker, Docker-Compose is already installed (available) --Understanding the basics of JavaScript / Vue.js

The purpose is to quickly build an environment on Docker, and it does not cover Docker in detail. What is Docker in the first place? We recommend that you refer to the following article. [Illustration] Understanding the whole picture of Docker -Part 1-

Work procedure

Vue edition

  1. Create application container
  2. Build a Vue app on a container
  3. Automate app execution when container starts
  4. Introduced Vue's main library
  5. Introduced Vuetify
  6. Create a counter app for testing

MySQL edition

  1. Creating a DB container
  2. Input test data
  3. Access to MySQL

How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ MySQL edition ~

Express edition

  1. Create API container
  2. Introduction of ts-node / nodemon
  3. Express server construction
  4. Routing settings
  5. API handler settings
  6. Create API template

How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Express edition ~

Sequelize edition

  1. Set up a network between containers
  2. Introduced Sequelize
  3. Model creation
  4. Complete the GetTests API
  5. Call the API with Axios from the front side
  6. Bind and render the response to Vuex

How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Sequelize ~

1. Creating an application container

First, create a file to create a container with docker-compose. Create the required files with the following configuration.

root
├─ docker
│    └─ app
│        └─ Dockerfile
└─ docker-compose.yml

docker-compose.yml

version: "3"
services:
  app:
    container_name: app_container
    build: ./docker/app
    ports:
      - 8080:8080
    volumes:
      - ./app:/app
    stdin_open: true
    tty: true
    environment:
      TZ: Asia/Tokyo

This is the basic docker-compose configuration file. We will add API server container and DB container later, but we will create only APP container once.

Dockerfile

FROM node:12.13-alpine

RUN yarn global add @vue/cli

WORKDIR /app

This time, we will use lightweight alpine as the base image. Since vue-cli is used in the container, perform global installation.

Container build

$ docker-compose build

Build the image below the design document created earlier

Container / startup

$ docker-compose up -d

Actually start the built container. Start in detached mode (background) by adding -d.

Check the running container

$ docker ps

The following is the output result, so let's check if it is actually started.

CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS    PORTS     NAMES
//OK if the created container is displayed here

2. Launch the Vue app on the container

Now that you have a base container, you can actually go inside the container and build your app.

Access the container

$ docker exec -it app_container sh

/app #  //If this happens, you can access the container

Vue app creation

$ vue create app

Manual selection With TypeScript With Router With Vuex Babel ** None **

The version is 2.x. Use class-style component syntax? Yes ** * This is important ** yarn ** * I'm going to use Yarn for the package. ** ** The rest is your choice.

Start-up

$ cd app
$ yarn serve

If you access localhost: 8080 and it is displayed, it's OK!

スクリーンショット 2020-09-15 0.01.02.png

At this point, you have created the app inside the container and executed the app from inside the container. Since this work is troublesome every time, we will set the application inside to be automatically executed when the container is started.

Stop the app once

$ controll + c

Get out of the container

$ exit

Stop container

$ docker-compose stop

3. Automate app execution when container starts

Change directory structure

The app directory directly under root is a hindrance, so please go somewhere.

Before

root
├─ app                //Ported here(This guy is deleted)
│    └─ app           //Every directory
│        ├─ node_modules
│        ├─ public
│        ├─ src
│ Others
│
├─ docker
│    └─ app
│         └─ Dockerfile
└─ docker-compose.yml

After

root     
├─ app     
│   ├─ node_modules
│   ├─ public
│   ├─ src
│ Others
│
├─ docker
│    └─ app
│         └─ Dockerfile
└─ docker-compose.yml

Added startup command to Compose config file

docker-compose.yml

version: "3"
services:
  app:
    container_name: app_container
    build: ./docker/app
    ports:
      - 8080:8080
    volumes:
      - ./app:/app
    stdin_open: true
    tty: true
    environment:
      TZ: Asia/Tokyo
    command: yarn serve  //Add this guy

Container startup

$ docker-compose up -d

If you access localhost: 8080 in this state and the application is launched, it is successful! The app will be launched when the docker container is launched without yarn serve!

Introduction of prettier (favorite)

I hate JavaScript semicolons, so I will introduce Prettier that will automatically format it. Please feel free to use this area.

Access the container

$ docker exec -it app_container sh

Prettier installation

$ yarn add prettier --dev

Create app / **. prettierrc **

{
  "singleQuote": true,
  "semi": false
}

4. Introducing major Vue libraries

Actually, this is my favorite this time. While writing Vue in TypeScript, we will introduce a library that can be written neatly and intuitively by using a decorator (@). In the future, Vue files will come up with some unfamiliar writing styles, but these libraries are nice and tidy.

$ yarn add vue-class-component vue-property-decorator vuex-class vuex-module-decorators

The following article is very easy to understand, so please read it if you are interested.

-Vue component starting with TypeScript (vue-class-component) -First vue-property-decorator (also supports nuxt)

Edit App.vue

src/App.vue


<template>
  <div id="app">
    <router-view />
  </div>
</template>

<style>
#app {
  width: 95%;
  margin: 0 auto;
}
</style>

I want to leave the component to be displayed to the Router side, so delete router-link and replace it with router-view.

Delete unnecessary files

├─ assets
│    └─ logo.ping        //Delete
├─ components
│     └─ HelloWorld.vue  //Delete
├─ views                 //Delete the entire directory
│      ├─ Home
│      └─ About

Please leave the files that you will not use in the future.

Create Test.vue

/pages/Test.vue


<template>
  <div class="test">
    <h1>Test Page</h1>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'

@Component
export default class Test extends Vue {}
</script>

Create a test component to check the following:

  1. Can you route correctly?
  2. Can the component load correctly?

Edit Router

/router/index.ts


import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
import Test from '../pages/Test.vue'

Vue.use(VueRouter)

const routes: Array<RouteConfig> = [
  {
    path: '/',
    name: 'Test',
    component: Test,
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
})

export default router

Set the routing so that the created Test component is called by the route.

Page confirmation

If you reload and "Test Page" is displayed, it's OK! You can freely increase the number of pages by connecting URLs and components in this way!

5. Introduced Vuetify

Library installation

yarn add vuetify
yarn add --dev sass sass-loader fibers deepmerge

If you use only vuetify, an error will occur, so install the necessary libraries as well.

Creating a plugin file

src/plugins/vuetify.ts


import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'

Vue.use(Vuetify)

const opts = {}

export default new Vuetify(opts)

This is a configuration file for applying Vuetify to the entire app.

edit main.ts


import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify' //add to
import 'vuetify/dist/vuetify.min.css' //add to

Vue.config.productionTip = false

new Vue({
  vuetify, //add to
  router,
  store,
  render: (h) => h(App),
}).$mount('#app')

By loading the plugin created above, you can use Vuetify in your application.

App.vue edit


<template>
  <v-app>  <!--add to-->
    <div id="app">
      <router-view />
    </div>
  </v-app> <!--add to-->
</template>

Finally, it is OK if you enclose the View of the application body.

Edit Test.vue


<v-btn large color="primary">test</v-btn>

スクリーンショット 2020-09-17 21.05.30.png

If the button is displayed, the installation of Vuetify is complete! Thank you for your hard work! After that, you can freely increase the number of pages in this way!

6. Create a counter app for testing

Now that the application template is complete, we will create a counter function after checking whether Vuex / Store can be used correctly.

Create Counter.vue

pages/Counter.vue


<template>
  <div class="counter">
    <h1>Counter</h1>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'

@Component
export default class Counter extends Vue {}
</script>

Creating a Counter page

--edit router / index.ts

import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
import Test from '../pages/Test.vue'
import Counter from '../pages/Counter.vue' //add to

Vue.use(VueRouter)

const routes: Array<RouteConfig> = [
  {
    path: '/',
    name: 'Test',
    component: Test,
  },
  { 
    path: '/counter',    //add to
    name: 'Counter',     //add to
    component: Counter,  //add to
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
})

export default router

Set the routing so that the above components are rendered at "localhost: 8080 / counter".

Creating a Store module

store/modules/**counter.ts**


import {
  getModule,
  Module,
  VuexModule,
  Mutation,
  Action,
} from 'vuex-module-decorators'
import store from '../index'

type CounterState = {
  count: number
}

@Module({ store, dynamic: true, namespaced: true, name: 'Test' })
class CounterModule extends VuexModule implements CounterState {
  count = 0

  @Mutation
  SET_COUNT(payload: number) {
    this.count = payload
  }

  @Action
  async increment() {
    this.SET_COUNT(this.count + 1)
  }

  @Action
  async decrement() {
    this.SET_COUNT(this.count - 1)
  }

  @Action
  async reset() {
    this.SET_COUNT(0)
  }
}

export const counterModule = getModule(CounterModule)

You can intuitively describe the Store module with "vuex-module-decorators" introduced at the beginning. This time, we will use the data "count" to check whether count changes dynamically when Action is fired.

Edit tsconfig.json

tsconfig.json


"experimentalDecorators": true, //add to

If you get angry with Linter, please set this.

Edit Counter.vue

pages/Counter.vue


<template>
  <v-card>
    <v-container>
      <v-card-title>Counter</v-card-title>
      <v-divider />

      <v-container>
        <v-avatar v-for="item in count" :key="item" color="primary">
          <span class="white--text headline">{{ item }}</span>
        </v-avatar>
      </v-container>

      <v-divider />

      <v-card-actions>
        <v-btn @click="increment">+</v-btn> <!--Execute increment method when clicked-->
        <v-btn @click="decrement">-</v-btn> <!--Execute decrement method when clicked-->
        <v-btn text @click="reset">Reset</v-btn> <!--Execute reset method when clicked-->
      </v-card-actions>
    </v-container>
  </v-card>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { counterModule } from '../store/modules/counter'

@Component
export default class Counter extends Vue {
  get count() {
    return counterModule.count //Returns the Store count as is
  }

  /**
   *Add count
   */
  increment() {
    counterModule.increment() //Fire the Store increment method
  }

  /**
   *Minus the count
   */
  decrement() {
    counterModule.decrement() //Fire the store's decrement method
  }

  /**
   *Reset the count
   */
  reset() {
    counterModule.reset() //Fire the Store reset method
  }
}
</script>

<style lang="scss" scoped></style>

Let's take full advantage of Vuetify here. Edit it so that v-avatars are generated for the number of counts, and then just move it!

Operation check!

If you press [+] [-] to increase or decrease the counter, it's OK! Thank you for your hard work!

スクリーンショット 2020-09-15 0.14.03.png

I created a simple counter and checked the behavior of Vuex (Store), but by inserting API communication in the Action of the Store, it is possible to link with the actual DB. Next time, I will create a container for the API server and the DB that actually operates it!

next time

How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ MySQL edition ~

reference

How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Express edition ~ How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Sequelize ~

Recommended Posts

How to build an environment of [TypeScript + Vue + Express + MySQL] with Docker ~ Vue edition ~
How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ MySQL edition ~
How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Express ~
How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ Sequelize ~
How to build Rails + Vue + MySQL environment with Docker [2020/09 latest version]
[Rails] How to build an environment with Docker
How to build Rails 6 environment with Docker
[Road _node.js_1-1] Road to build Node.js Express MySQL environment using Docker
How to build docker environment with Gradle for intelliJ
Build an environment of Ruby2.7.x + Rails6.0.x + MySQL8.0.x with Docker
When I tried to build an environment of PHP7.4 + Apache + MySQL with Docker, I got stuck [Windows & Mac]
How to build Rails, Postgres, ElasticSearch development environment with Docker
I tried to build the environment of PlantUML Server with Docker
Build an environment with Docker on AWS
How to build an environment with Docker, which is the minimum required to start a Rails application
Build an environment of "API development + API verification using Swagger UI" with Docker
How to execute with commands of normal development language in Docker development environment
01. I tried to build an environment with SpringBoot + IntelliJ + MySQL (MyBatis) (Windows10)
[Node.js express Docker] How to define Docker environment variables and load them with node.js
How to build a Ruby on Rails development environment with Docker (Rails 5.x)
[First team development ②] Build an environment with Docker
[Error resolution] Occurs when trying to build an environment for spring with docker
Easily build a Vue.js environment with Docker + Vue CLI
How to build Java development environment with VS Code
How to boot by environment with Spring Boot of Maven
Build Rails (API) x MySQL x Nuxt.js environment with Docker
I tried to build an environment using Docker (beginner)
[Rails] [Docker] Copy and paste is OK! How to build a Rails development environment with Docker
How to use git with the power of jgit in an environment without git commands
How to quit Docker for Mac and build a Docker development environment with Ubuntu + Vagrant
Build docker environment with WSL
Easy environment construction of MySQL and Redis with Docker and Alfred
What happened in "Java 8 to Java 11" and how to build an environment
How to get started with Gatsby (TypeScript) x Netlify x Docker
How to use mysql with M1 mac Docker preview version
Build a Node-RED environment with Docker to move and understand
I tried to build the environment of WSL2 + Docker + VSCode
I tried to build an API server with Go (Echo) x MySQL x Docker x Clean Architecture
Rails + MySQL environment construction with Docker
Create a Vue3 environment with Docker!
Build Couchbase local environment with Docker
Build PlantUML environment with VSCode + Docker
Build environment with vue.js + rails + docker
Build Rails environment with Docker Compose
[Environment construction with Docker] Rails 6 & MySQL 8
Update MySQL from 5.7 to 8.0 with Docker
Build docker + laravel environment with laradock
How to build CloudStack using Docker
How to start Camunda with Docker
Build apache7.4 + mysql8 environment with Docker (with initial data) (your own memo)
I tried to build an http2 development environment with Eclipse + Tomcat
How to install Pry after building Rails development environment with Docker
Build a development environment for Django + MySQL + nginx with Docker Compose
How to crop an image with libGDX
Build a PureScript development environment with Docker
Create Rails 6 + MySQL environment with Docker compose
[Rails] How to use rails console with docker
[Docker] Building an environment to use Hugo
Deploy to heroku with Docker (Rails 6, MySQL)
Edit Mysql with commands in Docker environment
Create a MySQL environment with Docker from 0-> 1