3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker + vue-cli環境を作ってみる

Last updated at Posted at 2019-10-27

■ はじめに

Node.jsのバージョンに依存せず複数プロジェクトを構築する手段の一つとして試してみた。
特にM1チップマシン上でNode.js開発環境を構築するのが大変だったので、
簡略化したかったというのが主な動機です。

今回はあくまで開発環境をDocker化するものなので、本番環境で使えるコンテナを構築するわけではないことはご留意ください。

ブラウザからは http://localhost:8080 で確認できます。

『docker-compose.yml』 及び 『vue.config.js』 で指定したポートとなります。
本記事内では8080を指定しています。

■ 事前知識

  • ほとんどの操作はターミナルで行うのでCLIの知識(というか慣れの部分が大きいかも)
  • Dockerに関する知識(イメージとコンテナの関係)
  • Node.jsのプロジェクトなのでパッケージ管理の知識(yarn.lockは編集してはいけないとか)

ホストOSの情報

自分の場合はmac環境で作業しました。
メインはM1ですが、Intel macでも大丈夫そうです。

環境情報
- OS:Big Sur (M1搭載)
- Docker:v20.10.10
- Docker Compose:v2.1.1

ホストOSにDockerのインストールが必要です。

ホストOSにNode.jsやyarnのインストールは不要です。

コンテナの操作

基本的には docker-compose.yml のあるディレクトリでコマンドを叩く。

docker-composeの基本的な使い方
# コンテナをビルド
docker compose build

# 失敗するようなら
docker compose build --no-cache

# コンテナを起動
docker compose up -d

# コンテナに入る
docker compose exec web bash

## コンテナ停止:コンテナに入っている場合
exit

## コンテナ停止:コンテナに入っていない場合
docker compose stop

## コンテナを破棄(必要に応じてやる)
docker compose down

Vue CLIの操作

Vue CLIの各コマンドを叩く場合はコンテナ内に入る必要がある。
Vue CLIをグローバルにインストールしていない場合はpackage.jsonのあるディレクトリに移動する。

# package install
yarn install

# start DevServer
yarn serve

# Compiles and minifies for production
yarn build

# Run your unit tests
yarn test:unit

# Run your end-to-end tests
yarn test:e2e

# Lints and fixes files
yarn lint

DevServerの操作

  • 起動する際はコンテナに入った状態でyarn serve
  • 終了する際は control + C で止める

■ 開発状況ごとの違い

  • プロジェクトの初期構築段階
  • 構築済みプロジェクトをクローン

それぞれの場合で Dockerfile, docker-compose.yml に多少の違いがある。

プロジェクトの初期構築段階の場合

コンテナ内でvue create を使えるようする必要がある。
この段階では node_modules のマウントはしない。

下記のページを参考にして、コンテナが起動したままになるようにDockerfileを作成

docker/web/Dockerfile
FROM node:14.18.1-slim

WORKDIR /app

RUN apt-get update && \
    # node-sassとかnode-gypの対策に入れる
  apt-get install -y python make g++ &&\
  yarn global add @vue/cli
docker-compose.yml
version: "3.8"
services:
    web:
        container_name: web
        build: ./docker/web
        ports:
            - 8080:8080
        privileged: true
        volumes:
            - ./app:/app
        tty: true
        stdin_open: true

コンテナ内でプロジェクト作成する

コンテナを起動してマウントしたappディレクトリ内にプロジェクトを構築していく。
細かい選択内容はお好みでどうぞ。

コンテナ内
# ./app 
vue create .

構築済みプロジェクトをクローンした場合

プロジェクトをクローンした場合 = package.json 及び yarn.lock がすでに存在する場合。
docker-compose up をしたタイミングで yarn install が走り node_modules にインストールされる。

docker/web/Dockerfile
FROM node:14.18.1-slim

WORKDIR /app

RUN apk update && \
    # node-sassとかnode-gypの対策に入れる
  apt-get install -y python make g++
docker-compose.yml
version: "3.8"
services:
    web:
        container_name: web
        build: ./docker/web
        ports:
            - 8080:8080
        privileged: true
        volumes:
            - ./app:/app
            - ./app/node_modules:/app/node_modules
        tty: true
        stdin_open: true
        command: /bin/sh -c "yarn install --check-files && yarn serve"
  • yarn install --check-files
    不足しているパッケージを確認して追加インストールするコマンド。
    別ブランチからプルしてきて差分があった場合に不足分をインストールするイメージです。
    参考: https://classic.yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-check-files

  • yarn serve
    vue-cliの場合です。reactnuxt の場合とコマンドが異なる可能性があります。

■ ディレクトリ構成

下記を選択すると最終的なディレクトリ構成はこうなるはず。

  • cypress
  • jest
  • babel
  • postcss
選択した内容
Vue CLI v3.4.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-proc
essors, Linter, Unit, E2E
? Use history mode for router? (Requires proper server setup for index fallback
 in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported
 by default): Sass/SCSS (with node-sass)
? Pick a linter / formatter config: Prettier
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <
i> to invert selection)Lint on save
? Pick a unit testing solution: Jest
? Pick a E2E testing solution: Cypress
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In packa
ge.json
? Save this as a preset for future projects? No
プロジェクトのディレクトリ構成
project_root
├── app/
│   ├── dist/ ← buildするとできる
│   ├── node_modules/ ← yarn install が成功するとできる
│   ├── public/
│   │   └── css/ ←これは自分で作る
│   │       └── reset.css
│   ├── src/
│   │   ├── assets/
│   │   │   ├── img/
│   │   │   └── scss/ ←これは自分で作る
│   │   │       ├── _colors.scss
│   │   │       ├── _global_inject.scss
│   │   │       ├── _mixins.scss
│   │   │       ├── _utility.scss
│   │   │       └── _variables.scss
│   │   ├── ...[ プロジェクトに応じた各ディレクトリ(views, componets, plugins など) ]/
│   │   ├── App.vue
│   │   ├── main.js
│   │   ├── registerServiceWorker.js
│   │   ├── router.js
│   │   └── store.js
│   ├── tests/
│   ├── babel.config.js
│   ├── cypress.json 
│   ├── jest.config.js
│   ├── package.json
│   ├── postcss.config.js
│   ├── vue.config.js ←これは自分で作る
│   └── yarn.lock
├── docker/
│   └── web/
│       └── Dockerfile
├── docker-compose.yml
├── README.md
├── .git/
└── .gitignore

追加で入れることが多いもの

これらは入れなくてもvueの動きは確認できます。

terminal
# ajax
yarn add axios

# sass global valiables and mixin
vue add sass-resources-loader

# webfont: fontawesome5.x
yarn add @fortawesome/fontawesome-svg-core
yarn add @fortawesome/free-solid-svg-icons
yarn add @fortawesome/vue-fontawesome
yarn add @fortawesome/free-regular-svg-icons
yarn add @fortawesome/free-brands-svg-icons

# vuexの永続化のためlocalstorageを使えるようにするやつ
yarn add vuex-persistedstate

# UIフレームワーク(使わないこともある)
vue add vuetify

個人的なpackage構成

バージョンはあくまで現段階のものです。

多少増えたり減ったりしますが、今のところはこの構成をテンプレートにしています。

app/package.json
{
  "name": "project_root",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e",
    "lint": "vue-cli-service lint",
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "1.2.36",
    "@fortawesome/free-brands-svg-icons": "5.15.4",
    "@fortawesome/free-regular-svg-icons": "5.15.4",
    "@fortawesome/free-solid-svg-icons": "5.15.4",
    "@fortawesome/vue-fontawesome": "2.0.6",
    "axios": "^0.24.0",
    "core-js": "^3.6.5",
    "register-service-worker": "^1.6.2",
    "vue": "^2.6.14",
    "vue-router": "^3.5.3",
    "vuex": "^3.6.2",
    "vuex-persistedstate": "^4.1.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-e2e-cypress": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-pwa": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-unit-jest": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/test-utils": "^1.0.3",
    "babel-eslint": "^10.1.0",
    "eslint": "^7.11.0",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^2.4.1",
    "sass": "^1.43.4",
    "sass-loader": "^10.2.0",
    "vue-cli-plugin-sass-resources-loader": "^1.0.0",
    "vue-template-compiler": "^2.6.14"
  }
}

packageをmain.jsにimportする。

app/src/main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import "./registerServiceWorker";

// Ajax
import axios from "axios";

// Fontawesome
import { library } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { fas } from "@fortawesome/free-solid-svg-icons";
import { fab } from "@fortawesome/free-brands-svg-icons";
import { far } from "@fortawesome/free-regular-svg-icons";

library.add(fas, far, fab);
Vue.component("font-awesome-icon", FontAwesomeIcon);

Vue.config.productionTip = false;
Vue.prototype.$axios = axios;

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app");

vuexにもpackageを追加。

app/src/store.js
import Vue from "vue";
import Vuex from "vuex";
import createPersistedState from "vuex-persistedstate"; //これを追記
Vue.use(Vuex);

export default new Vuex.Store({
  //〜中略〜
  plugins: [createPersistedState()] // これを追記
});

個人的なconfig

vue.config.jsは自分で作る必要があります。

distの中身もとりあえずgit管理する想定なので、buildした際に各ファイルにハッシュが付かないようにfalseにします。
vue.config.js は情報を見つけるのに苦労しました。

vue.config.js
const path = require("path");

module.exports = {
  // disable hashes in filenames
  filenameHashing: false,
  // devserver port
  devServer: {
    port: 8080, // well-known以外に設定しておく
    disableHostCheck: true,
  },
  // sass global variables and mixin file load...
  // SCSSを使わない場合はここから下は不要です。
  chainWebpack: (config) => {
    const ofs = ["vue-modules", "vue", "normal-modules", "normal"];
    const cssRules = config.module.rule("css");
    const postRules = config.module.rule("postcss");
    const scssRules = config.module.rule("scss");

    const addSassResourcesLoader = (rules, type) => {
      rules
        .oneOf(type)
        .use("sass-resoureces-loader")
        .loader("sass-resources-loader")
        .options({
          resources: [
            path.resolve("./src/assets/scss/_global_inject.scss"),
            path.resolve("./src/assets/scss/_colors.scss"),
            path.resolve("./src/assets/scss/_mixins.scss"),
            path.resolve("./src/assets/scss/_utility.scss"),
            path.resolve("./src/assets/scss/_variables.scss"),
          ],
        });
    };
    ofs.forEach((type) => {
      addSassResourcesLoader(cssRules, type);
      addSassResourcesLoader(postRules, type);
      addSassResourcesLoader(scssRules, type);
    });
    return config;
  },
};

■ デプロイ

yarn build でデプロイ用の静的なファイル群(.html, .css, .js)を app/dist配下に出力します。
それらのファイルをホスティングすることでインターネット上に公開されます。

Firebase へのデプロイを試すためにまとめた記事↓

■ 参考記事

■ 参考リンク

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?