20200909のvue.jsに関する記事は15件です。

FirebaseのCloud Firestoreと連携して掲示板を作る【nuxt.js】

FirebaseとNuxt.jsで掲示板を作りました。削除ボタンが機能しなかったり未完成の部分があります。

この記事は

  • Firebaseを活用してみたい
  • Nuxt.jsでアプリ作ってみたい

という人向けに書いてみました。
「こんな感じでやれば短時間でFirebaseと連携できます」的なものを記事にしました。作っていく際に参考にした記事と躓いた点も書いていきます。中途半端な出来ですが初心者向けに書いてみました!

Firebaseとは何?

Firebaseはリアルタイムでデータ同期ができるモバイルプラットフォームです。Firebaseを使うとサーバを立てたり、管理や保守がいらなくなるのでフロントサイドの作成に集中できます。

NuxtJSとは何?

NuxtJSは、Vueファイルで記述できるフレームワークです。モジュール構造で拡張でき一部分から徐々に採用することが可能で、静的なページから複雑なwebアプリケーションまで、あらゆるものの作成に使用できます。

以下公式から抜粋

本質的に汎用性があり、さまざまなターゲット(サーバー、サーバーレス、または静的)をサポートし、サーバーサイドのレンダリングは切り替えることができます。
強力なモジュールエコシステムにより拡張可能で、REST や GraphQL エンドポイント、お気に入りの CMS や CSS フレームワークなどさまざまなものに簡単に接続できます。
NuxtJS は Vue.js プロジェクトのバックボーンであり、柔軟でありながら自信を持ってプロジェクトを構築するための構造を提供します。

めちゃくちゃ簡易的な掲示板

できたもの

実際に利用できます!コメントしてみてください!
http://keiziban.tk/about/

機能

名前、コメントの投稿がきる

作成手順

任意のフォルダーに移動してVScodeのTerminalより
yarnを使って以下のコマンドでNuxtプロジェクトを作成することができます。

yarn create nuxt-app cloudfireTest

を実行すると、UIフレームワークなどの機能が必要か聞かれるので選択していき、終了したら
yarn run devで起動させます。無事に終了したら以下のアドレスにアクセスして実行されているか見ます。
http://localhost:3000

続いて

yarn add firebase

でインストールて完了です。
今回にUIフレームワークはBootstrapVueを選択したので、こちらでどのようなスタイルになるのかを調べました。

フォルダ構造

以下のフォルダとファイルで構成されています。
Image from Gyazo

pages

pagesディレクトリに.vueファイルを作成するとページのルーティングができます、index.vue/になり、about.vue/aboutでアクセスできます

about.vue
<template>
  <div class="container">
   <div class="jumbotron">
        <div class="container">
          <h1 class="display-3">掲示板</h1>
        </div>

      <div class="links">
        <client-only placeholder="Loading...">
        <Memo />
        </client-only>

      </div>
    </div>
  </div>
</template>

<script>

import Memo from '~/components/Memo.vue'


export default {
  components: {
    Memo
  }
}
</script>

以下の部分でComponents内に作るMemo.vueが呼び出されます。

<client-only placeholder="Loading...">
        <Memo />
        </client-only>

Components

何度も利用可能な.vueで構成されています。今回のFirebaseとの連携はこちらに書いていきます。まずはComponentsMemo.vueを追加。
Image from Gyazo

Memo.vue
<template>
    <div>
         <p>
            <b-form-input v-model="name" placeholder="名前"></b-form-input>
            <b-form-textarea input v-model="age" placeholder="コメント" id="button"></b-form-textarea> 
            <b-button id="button" size="sm" variant="outline-success" v-on:click="post(); removetext()">投稿</b-button>
        </p>
        <ul v-for="(data, index) in allData" :key="data.id" class="menu-list" >

            <li>

                名前:{{data.name}} <br>
                コメント:{{data.age}}<br>
                <b-button size="sm" variant="outline-danger" class="delete" @click="switchDelateAlarm(); getIndex(index)">
                削除
                </b-button>

            </li>
            </ul>
            <div v-show="showDelateAlarm" id="overlay">
                <div id="delateAlarm">
                    <p>コメントを削除します</p>
                        <b-button size="sm" variant="outline-dark" v-on:click="closeModal">
                        戻る
                        </b-button>
                        <b-button  size="sm" variant="outline-danger" @click="switchDelateAlarm(); deleteItem(data.id)">
                        削除
                        </b-button>
                </div>
            </div>
    </div>
</template>

<script>
import firebase from "firebase/app";
import "firebase/firestore";



export default {
    components: {},

    data(){
        return{
            db: {},
            allData: [],
            name: '',
            age: '',
            showDelateAlarm: false,
            id: [],

        }
    },



    methods: {
        init: () => {
            const config = {
                apiKey: "",
                authDomain: "",
                databaseURL: "",
                projectId: "",
                storageBucket: "",
                messagingSenderId: "",
                appId: "",
                measurementId: ""
            };
            firebase.initializeApp(config);
        },

        post: function(){
            const testId = firebase.firestore().collection('memos').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('memos').doc(testId);
            const setAda = docRef.set({
                name: this.name,
                age: this.age,
                createdAt: new Date()
            });
            this.get();
        },

        get: function(){
            this.allData = [];
            firebase.firestore().collection('memos').get().then(snapshot => {
                snapshot.forEach(doc => {
                    this.id = doc.id;
                    console.log(this.id); 
                    const array = [];
                    console.log(array);
                    this.allData.push(doc.data());
                })
            });

        },
        getIndex: function() {
            console.log(firebase.firestore().collection('memos'));

        },
        deleteItem: function(deleteId, getIndex) {
            const db = firebase.firestore();
            db.collection("memos").doc(deleteId).delete().then(function() {
            console.log("Document successfully deleted!");

            }).catch(function(error) {
                console.error("Error removing document: ", error);
            });
            this.showDelateAlarm = false;
            this.get();
        },


        switchDelateAlarm: function() {
            this.showDelateAlarm = true
        },
        closeModal: function(){
           this.showDelateAlarm = false
        },
        removetext: function() {
       this.name = '';
       this.age = '';

    },
    },

    mounted(){
        this.init();
        this.get();
    },


}


</script>

<style>
#delateAlarm{
  z-index:2;
  width:50%;
  padding: 1em;
  background:#fff;
}

#overlay{
  /* 要素を重ねた時の順番 */

  z-index:1;

  /* 画面全体を覆う設定 */
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background-color:rgba(0,0,0,0.5);

  /* 画面の中央に要素を表示させる設定 */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10%;

}
ul {
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    padding: 0px;
    list-style: none;
}
#button {
    margin-top: 2px;
}

</style>


Cloud Firestoreの設定

こちらの部分にファイヤーベースの設定→全般の下のほうにあるマイアプリ
からコピー&ペーストします。
Image from Gyazo

Memo.vue
const config = {
                apiKey: "",
                authDomain: "",
                databaseURL: "",
                projectId: "",
                storageBucket: "",
                messagingSenderId: "",
                appId: "",
                measurementId: ""
            };

今回はあらかじめCloud Firestoreのコレクションにmemos作成しておきます。

Image from Gyazo

設定

以下はpostの部分を抜粋しています。

Memo.vue
post: function(){
            const testId = firebase.firestore().collection('memos').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('memos').doc(testId);
            const setAda = docRef.set({
                name: this.name,
                age: this.age,
                createdAt: new Date()
            });
            this.get();
        },

Image from Gyazo

躓いた部分

削除ボタンの実装に躓きました。ボタンに紐づいたドキュメントidが取得できずボタンは配置されていますが、機能しません。

参考にした記事

終わりに

読んでいただきありがとうございました、よくわからん部分もあったと思います。私自身わかっていない部分が多いですが、とにかく一言いってやりたいという方!是非こちらで絡んでやってください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker上にvue.jsの開発環境する。docker-composeで簡単に作成する手順。

Docker上にvue.jsの開発環境する。docker-composeで簡単に作成する手順。

dockerを使ってvue.jsの開発環境を簡単に構築できるようにする。

本番に応用できるよう、DockerfileのENTRYPOINTでコンテナ内のスクリプトを実行する。

また、実行はdocker-composeを使用する。
実行順序は docker-composeファイル -> Dockerファイル -> スクリプトファイル となる。

複数人のプロジェクトを想定して、作成したファイル群をgithubにアップして、cloneしvue.jsの開発環境を立ち上げるまで。


開発手順

  1. Dcokerのインストール
  2. Dockerfileの作成
  3. シェルスクリプトの作成
  4. docker-compose.ymlの作成
  5. .dockerignoreの作成
  6. aliasの作成
  7. aliasファイルの読み込み
  8. docker-composeの実行
  9. コンテナ内に入る
  10. vueの開発環境を作成する
  11. ファイルの移動と削除
  12. vue開発環境の確認
  13. githubに作成したファイル群をプッシュ
  14. 他のプロジェクトメンバーのローカルで実行する


Dcokerのインストール

Dockerの公式ページからOSに合ったDockerをインストール

https://docs.docker.com/get-docker/

設定が完了したら、正しくインストールされているかターミナルで確認。

$docker -v
Docker version 19.03.12

$docker-compose -v
docker-compose version 1.26.2

dockerとdocker-composeのバージョンがそれぞれ表示されたらOK。


Dockerfileの作成

環境開発時のコマンドはdocker-composeで実行するが、独自のイメージを作成(build)する際に、Dockerfileを指定する。

Dockerfileはコンテナ内の処理となる。

プロジェクトフォルダを作成したい階層に移動。
ここでは、PJのルートディレクトリとしてvuecliを作成する。

ターミナル
#vuecliフォルダを作成し移動
$ mkdir vuecli && cd vuecli

#Dockerfileを作成
$ touch Dockerfile

#vimエディタでファイルを開く
$ vi Dockerfile

▼vimエディタの超基本コマンド

  • 貼り付け:p
  • インサートモード: i
  • インサートモード終了: esc
  • 保存して終了: :wq



▼Dockerファイルの内容
Dockerfileは拡張子不要。
Dockerfileには下記を記述。

Dockerfile
#nodeイメージをpullする
FROM node:10.15.3-alpine

#working directory
WORKDIR /app

#vuecliインストール
RUN npm install -g @vue/cli

#shファイルをコンテナにコピー
COPY ./scripts/docker.start.sh /scripts/start.sh

#shフォルダの権限追加(全員実行可)
RUN chmod +x /scripts/*

#初期実行
# ENTRYPOINT [ "/scripts/start.sh" ]

Dockerfileはイメージを作成するための元となるファイル。

FROM イメージ名:タグ

継承のような機能。指定したイメージを取得し、以下に続く処理を実行する。

タグはバージョンを指定。記載しない場合は最新版(latest)が選択される。

イメージの取得は、まずdocker公式の共有イメージ置き場であるdockerhubで該当するものがあるか探す。ない場合はローカルのDocker内のイメージを探す。

(補足) node:10.15.3-alpineとは?
本当はvue-cliのイメージを取得したいが、現状dockerhubにはないため、nodeのイメージを取得する。

バージョンは10.15.3、OSはlinux alpineを選択。

linux alpineは軽量のOS。dockerのイメージで見かけることが多い。注意点としてはbashファイルが存在せず、shファイルのみとなること。(後々の記述に影響)

WORKDIR パス

コンテナ内のワーキングディレクトリの指定。

デフォルトではルートディレクトリ(/)が指定されているが、WORKDIRで変更することができる。

RUN コマンド

コンテナ内で実行するコマンドを記述。
「npm install -g @vue/cli」で、vueを操作するコマンドラインインターフェース(cli)をインストールする。

exec形式(配列でコマンドと引数を順に記述)での記述も可能。例えば上のコマンドだと、
RUN ["npm", "install", "-g", "@vue/cli"]

COPY ホスト内パス コンテナ内パス

ホスト内のファイルをコンテナの指定したパスにコピーする。
親フォルダが存在しない場合は自動で作成される。

コンテナ内のシェルスクリプトでコマンドを実行する仕様とするため、予めホスト内でコマンドを記述したシェルスクリプトを作成しておき、それをコンテナ内にコピーする。(シェルファイルの作成は後ほど)

シェルスクリプトに実行権限を与え、ファイルパス指定で実行できるようにする。
「RUN chmod +x /scripts/*」で権限を付与。

実行権限を与えない場合は、shコマンドでないと実行できない。「$sh シェルスクリプトパス」

ENTRYPOINT [ "コマンド", "引数",,]

ENTYPOINTはコンテナ初回起動時に実行するコマンド。

コンテナ内のスクリプトファイルのパスを指定することで、コンテナ初回起動時に指定したスクリプトを実行できる。


(補足)ENTRYPOINTCMDの違い

ENTRYPOINTCMDはどちらもコンテナ初回実行時に実行するコマンド。

どちらか一つは必ず必要で、記述がないとエラーになる。

ENTRYPOINTとCMDもexec形式(配列のような形)でコマンドを渡せる。その際、引数の扱いが異なる。

  • ENTRYPOINT: 引数の変更はできない。追加の引数として処理する。
  • CMD: 引数に変数を指定できる(状況に合わせて変更可能)
コマンドの記述でよく見る例
  • CMD [ "/bin/sh" ] : shファイルを実行
  • CMD [ "/bin/bash" ] : bashファイルを実行
  • CMD [ "npm", "run", "serve" ] : 「$npm run serve」コマンドを実行(vue.jsのサーバー起動)


シェルスクリプトの作成

ローカルのPJルートディレクトリにscriptsフォルダを作成し、シェルスクリプト「docker.start.sh」を作成する。

ターミナル
#scriptsフォルダとシェルファイルを作成
$mkdir scripts && touch ./scripts/docker.start.sh

#vimエディタで開く
$vi ./scripts/docker.start.sh

▼シェルスクリプトの記述内容

docker.start.sh
#!/bin/sh

#node_modulesインストール
echo "npm install"
npm install 

#vue起動
echo "npm run serve. "
npm run serve

#メモを出力
echo "localhost:18080"

※(補足)シェルスクリプトの利用について
指定のシェルスクリプトを使用せず、DockerfileのみでCMD ["npm","run","serve"]でも実行できるが、

実際の開発で、開発環境と本番環境でインストールするライブラリを変更するなど、条件分岐(if)などを使うことを想定。

docker-compose.ymlの作成

docker-composeは複数のコンテナでプロジェクトを立ち上げる時に使う。

例えば、①ruby on rails, ②PostgreSQL, ③Redis, ④Sideqikのコンテナをまとめて立ち上げることができる。

docker-composeで立ち上げたコンテナは自動で独自のネットワーク(コンテナ同士の関連づけ)が設定される。

docker-composeファイルの拡張子はyml(ヤムル)なので、ヤムルの仕様に沿って記述する。

まずはPJのルートディレクトリにファイルを作成する。

terminal
#ファイル作成
$touch docker-compose.yml

#vimエディタで開く
$vi docker-compose.yml

▼docker-compose.ymlの記述内容

docker-compose.yml
#docker-composeのバージョンを指定
version: "3.7"

volumes:
    #volumeはホストにコピー or 表示させないもの
    ##バイナリファイル(node_module)など、OS依存があるもの

    #node_moduleを入れるvolume
    vue-cli-node-volume: 

services:
    #コンテナ詳細
    app:
        image: vuecli:1
        build:
            context: .
            dockerfile: Dockerfile
        container_name: vuecli3
        ports:
            - "18082:8080"
        volumes:
            #node_moduleを入れるボリューム
            - vue-cli-node-volume:/app/node_modules

            #コンテナ内の指定ディレクトリをホスト側と同期
            - .:/app/

        #-it
        stdin_open: true
        tty: true

version:"メジャーNo.マイナーNo"

docker-composeのファイルフォーマットのバージョンを指定する。versionにより記述方法に違いがあるため注意。今回は3.7を指定。

マイナーNoを記述しない場合、0に置き換わる。
例: version:"3" = version:"3.0"

>ファイルフォーマットとdocker-composeのバージョンの対応表
https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/compose-versioning/

volumes:

トップレベルに「volumes:」を記述すると、指定したvolume名を各コンテナで共有できるようになる。

volumeを使用すると、指定したコンテナのディレクトリやファイルをホストのdockerのストレージに保存する。

▼volumeの使い方

volumeの使い方は大きく3つ。

(1)ホスト側のPJルートディレクトリと同期する

コンテナ内のワーキングディレクトリと、PJのルートディレクトリを同期することで、viewファイルやsrcなどがリアルタイムで同期できる。

- .:/app/ (ホスト側のパス:コンテナ側のパス)
上記例では、コンテナのワーキングディレクトリ/app/を、ホスト側のdocker-composeを実行するディレクトリに同期している。

(2)ホスト側にコピーしたくないファイルやディレクトリの指定。

volume名を指定することで、.dockerignoreファイルと組み合わせ、ホスト側に同期させないようにすることができる。

例えば、バイナリファイルが該当する。
バイナリファイルはバイナリ(0,1)で書かれたPC用のテキストファイルでOS毎に内容が異なる(依存性がある)。

コンテナ内にインストールしたnodeはLinux用なので、ホスト側のOSと一致しない場合に不具合を起こす。なので、nodeの入ったnode_modulesはホスト側のPJディレクトに同期させないようにする。(.dockerignoreファイルと合わせて使う)

(3) 同期除外しなくてもいいが、ホスト側にも特に必要ないファイルやディレクトリ

ログファイルなどログ分析用ファイルに同期している場合はホストのPJディレクトリに同期する必要はない。

volumeの記述方法

volumesの記述はホスト側:コンテナ側
実際の記述方法は大きく3つ。

(1)コンテナ側のパスのみ
./logs
/var/lib/mysql

ホスト側のパスを記述しない場合、コンテナ内の指定したフォルダはホストのvolume内のどこかに保存される。

呼び出す必要もないファイルやディレクトリに使う。

(2) ボリューム名で指定
node_volume: ./node_modules

ホスト側をボリューム名で記述する方法。この場合、docker内に指定したボリューム名のディレクトリが作成され、その中に指定したフォルダやファイルが保存される。

ホスト側のPJディレクトリに保存したくない場合に使用。(.dockerignoreを合わせて使う)

(3) パスで指定
./cache:/tmp/cache

パスで指定することも可能。
上記例では、ホスト側を相対パス、コンテナ側を絶対パスで指定。

sevices:

コンテナと使用するイメージを設定する。
今回はappコンテナのみ作成。

image: イメージ名:タグ

コンテナ作成のために使用するimageを指定する。
タグはバージョン。記述しない場合はlatestとなる。

buildがある場合は、buildに記載の内容からイメージを作成する。buildの指定がない場合は、dockerhub、ローカルの順にイメージを探す。

build

イメージを作成するためのDockerfileを指定する。
記述方法は2つ。

(1)Dockerファイルのパスとファイル名で指定

build:
  context: Dockerファイルのパス
  dockerfile: ファイル名
(補足)Dockerfileのファイル名について

Dockerfileのファイル名は「Dockerfile」に限定する必要はない。指定ディレクトリの拡張子のないファイルを構築用ファイルとみなす。

誰が見てもわかりやすいように「Dokerfile」を記述するのが一般的。

▼ファイル名の例
- Dockerfile
- Dev.Dockerfile
- Dockerfile-2

(2)ファイルのパスで指定
構築用ファイル(拡張子のないファイル)がディレクトリに1つのみのとき、ディレクトリパスのみの指定もできる。

build: Dockerファイルのパス

container_name:

作成したコンテナの名前を指定する。
「docker ps -a」 でコンテナの一覧を出した時に表示される名前。

ports: - ホスト側:コンテナ側'

ポートの指定。複数設定することも可能。

「- "18082:8080"」の場合、コンテナ側の通信ポート8080と、ホスト側の18082ポートをつなげる。

ホスト側のブラウザにlocalhost:18082と打ち込むと、コンテナ内で開発用サーバーを立ち上げた時に表示されるlocalhost:8080に接続する。

stdin_open: true

コンテナ起動時のオプション。標準入力(standard in)を許可する。
コンテナ内のOSとbash(sh)を通してコマンド入力する場合に必要。

Dockerのコマンドでは「-i」

tty: true

コンテナ起動時のオプション。標準出力用の擬似ターミナルを起動する。
コンテナ内のOSとbash(sh)を通してコマンド入力する場合に必要。

Dockerのコマンドでは「-t」
基本的に「-t」と「-i」はセット(-it)で使う。


.dockerignoreの作成

ホスト側に同期したくないファイルやディレクトリのパスを記述する。(.gitignoreと同じ機能)

terminal
#ファイルの作成
touch .dockerignore

#vimエディタで開く
vi .dockerignore

▼.dockerignoreの内容

.dockerignore
#node_modulesは同期しない
node_modules

コンテナ作成を実行すると、ローカル内にnode_modulesという空のフォルダが自動作成される。コンテナ内の同じフォルダの内容を同期しなくなる。


aliasの作成

ここまでで、ようやくイメージとコンテナを作成するために必要なファイルが揃った。

  • docker-compose.yml
  • Dockerfile
  • docker.start.sh
  • .dockerignore

この時点でdocker-composeを実行することもできるが、本番を見据えてdocker-composeコマンドのaliasを作成することで、より簡単に操作できるようにする。

作成の流れは、aliases.shファイルを作成しコマンドを記述。bash_profileでファイルを読み込み、bash_profileをリロード。

terminal
#ファイルを作成
$ touch aliases.sh

#vimエディタで開く
$ vi aliases.sh

▼aliases.shの内容

aliases.sh
#イメージの作成とコンテナ起動
alias vue-pj="docker-compose up --build app"

#コンテナ内のshファイルを起動
alias vue-exec="docker exec -it vuecli sh"

alias ショートカットコマンド="本来のコマンド
イコールの前後にスペースがあるとエラーになる。

docker-compose up --build app
「docker-compose up [サービス名]」:指定したサービスの内容を実行。イメージがない場合はビルドし、コンテナを起動する。

イメージが既に存在する場合は上書きせず、それを使用する。

docker-compose.ymlの変更内容を反映したいため、「--build」オプションをつけることで、イメージが存在しても再度イメージを構築する。(docker-compose build && docker-compose up appと同じ)

▼サービス名の指定がない場合
サービス名を指定しない場合は、記述してある全てのコンテナを起動する。

今回の環境では、appの指定がなくても同じ挙動となるが、実際は開発環境や本番環境で立ち上げるコンテナを切り替えることがあるためあえて指定。

▼「-d」オプション
-dオプションをつけると、バックグラウンドモードでの起動となり、bash(or sh)が起動しない状態となる。
コンテナ内の実行内容が見えなくなってしまうため、今回は付けない。

docker exec -it コンテナ名 sh
指定したコンテナのシェルを立ち上げる。コンテナ内がbashの場合はshではなくbashを指定。

今回はlinux alpineのためshを指定。

aliasファイルの読み込み

作成したaliasが使えるように、bashで読み込む。

terminal
#bash_profileをvimエディタで開く
$ vi ~/.bash_profile

▼bash_profileの内容

bash_profile
#作成したファイルを読み込み(フルパスで記述)
source /Users/.../vuecli/aliases.sh 
terminal
#bash_profileのリロード
$ source ~/.bash_profile

#aliasの確認
$ alias
alias vue-exec='docker exec -it vuecli sh'
alias vue-pj='docker-compose up --build app'

作成したaliasが表示されていればOK。

bash_profileとは?

bash_profileはシェルをbashで起動したときに読み込まれるファイル。

設定したaliasはシェルを閉じると消えるが、bash_profileに記述することで毎回自動でロードされる。

似たファイルで、より高頻度でロードする、.bashrcというのもある。


docker-composeの実行

いよいよdocker-composeを実行し、イメージとコンテナを作成する。

docker-compose.ymlのあるディレクトリで先ほど設定したコマンドを実行。

terminal
vue-pj

これで、コンテナ内にnode.jsとvue-cliがインストールされる。


コンテナ内に入る

コンテナ内でvue-cliを使ってvue.jsの開発環境を作成するため、先ほど作成したaliasでコンテナないのシェルを起動する。

terminal
vue-exec
/app #

/app #と表示されれば、docker内に作成したワーキングディレクトリでコマンドを打ち込める状態になっている。


vueの開発環境を作成する

コンテナ内シェル
/app #vue create -d pj

vue create プロジェクト名
ここではプロジェクト名をPJとして実行。
オプションの「-d」はデフォルト設定(bavelとeslint)で作成。

「-d」を記述せず、vue-cliの対話モードでオプションを選択してくこともできる。


ファイルの移動と削除

vue createを実行するとフォルダは指定したプロジェクト名のフォルダの中に作成される。

ホスト側のプロジェクトファイルのルートディレクトリとコンテナ内のワークディレクトリを同期させたいため、コンテナ内のプロジェクトフォルダの中身を一階層上に上げる。

.dockerignoreに記述しているnode_modulesは同期するディレクトリに移動できないため、一度削除し再インストールする。

まず、コンテナ内のvue-cliが立ち上がっているので、ctrl + cでいったん終了し、コンテナ内のシェルに戻る。

コンテナ内シェル
#pjフォルダを一階層上に移動(隠しファイル含む)
##gitignoreのnode_moduelsは移動できない
mv -f ./pj/* ./pj/.* .


<br>
##node_modulesファイルを削除し、再インストール
rm -r pj && npm install 

##yarn関連ファイルを削除。
rm *yarn* 


##コンテナ内を確認
/app # ls
Dockerfile          node_modules        scripts
aliases.sh          package-lock.json   src
babel.config.js     package.json
docker-compose.yml  public

ホスト側にコンテナ内のファイルが反映されていればOK

image.png


vue開発環境の確認

これで自分のPCでの開発環境の設定が完了したので、実際にWEBページが開けるか確認する。

npm run serveでサーバーを再起動できるが、dockerの練習も兼ね一旦コンテナから出て確認してみる。

#コンテナから抜ける
/app # exit

#起動中のコンテナを確認
$docker ps -a

CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                                            NAMES
ebe0276cb7f0        vuecli:0                    "/scripts/start.sh"      36 minutes ago      Up 4 minutes        0.0.0.0:18080->8080/tcp                          vuecli
#イメージを確認
$docker images
REPOSITORY                                      TAG                 IMAGE ID            CREATED             SIZE
vuecli                                          0                   c6a23f947246        32 hours ago        338MB

#イメージの詳細
$docker image inspect vuecli:0

docker-compose.ymlに記述したコンテナ名とイメージ名のコンテナとイメージがそれぞれ存在していることがわかる。

WEBページを確認するため、再びコンテナ内に入る。

#コンテナ内に入る
$vue-exec

#サーバーを起動
/app # npm run serve


App running at:
  - Local:   http://localhost:8080/

  It seems you are running Vue CLI inside a container.
  Access the dev server via http://localhost:<your container's external mapped port>/

上記が表示されればサーバーの起動完了。

WEBブラウザでページを表示する。
docker-composer.ymlで設定したホスト側のポートを入力。
localhost:18080

image.png

WEBページが表示されれば成功。


githubに作成したファイル群をプッシュ

このままでは自分しか使えないため、複数人で開発を進められるようgithubのリモートレポジトリに作成したファイル群をプッシュする。

githubのレポジトリを指定してアップする。

git init
git commit -m "first commit"
git branch -M master
git remote add origin https://github.com/(レポジトリのフルパス)
git push -u origin master

image.png


他のプロジェクトメンバーのローカルで実行する

前提条件として、dockerとdocker-composeが入っていること。

#リモートレポジトリをclone
##クローンした際のフォルダ名をvuecli(任意)としている。
$git clone https://github.com/(レポジトリのフルパス) vuecli

#フォルダ移動
$cd vuecli

aliasファイルの読み込み

作成したaliasが使えるように、bashで読み込む。

terminal
#bash_profileをvimエディタで開く
$vi ~/.bash_profile

▼bash_profileに以下を記述

bash_profile
#作成したファイルを読み込み(フルパスで記述)
source /Users/.../vuecli/aliases.sh 
terminal
#bash_profileのリロード
$source ~/.bash_profile

#aliasの確認
$ alias
alias vue-exec='docker exec -it vuecli sh'
alias vue-pj='docker-compose up --build app'

#イメージとコンテナ作成
$vue-pj

省略
App running at:
  - Local:   http://localhost:8080/

  It seems you are running Vue CLI inside a container.
  Access the dev server via http://localhost:<your container's external mapped port>/

上記が表示されればサーバーの起動完了。

WEBブラウザでページを表示する。
docker-composer.ymlで設定したホスト側のポートを入力。
localhost:18080

image.png

WEBページが表示されれば成功。

以上。

 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vuetifyのv-data-tableで奇数行の背景色を変える

やりたいこと

Vuetifyに用意されているテーブルコンポーネント[v-data-table]がデフォルトのままだといまいち見づらかったので、
よくある奇数行だけ色が変わっている一覧にしたい

image.png

おなじみのCSSを設定してみる

普通にCSSで奇数行の色変わるように指定

App.vue
<style scoped>
.v-data-table td {
    background: #f0f8ff;
}
.v-data-table tr:nth-child(odd) td {
    background: #fff;
}
</style>

変わらない。。。
あぁ、scopedがついてるから子コンポーネントには反映されんのか。。。

App.vue
<style>
.v-data-table td {
    background: #f0f8ff;
}
.v-data-table tr:nth-child(odd) td {
    background: #fff;
}
</style>

image.png
変わった!
・・・けど、マウスオーバーしてる行の背景色が変わらなくなった。。。

tableのstyle上書きしてしまったから?
しょうがないから自分で設定してやる。

App.vue
<style>
.v-data-table td {
    background: #f0f8ff;
}
.v-data-table tr:nth-child(odd) td {
    background: #fff;
}
.v-data-table tr:hover td {
    background-color: #eee;
}
</style>

完成!

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsでおみくじアプリを作ってみた

はじめに

Vue.jsを学習中の初心者の私が理解を深めるためにおみくじアプリを作ったのでアウトプットの為に記事を書いておきます。
同じVue.js初心者の助けになれば嬉しいです。

やろうと思うこと

おみくじは大吉、中吉...と○吉の文字を配列に入力しておきます。
ブラウザ上のボタンをクリックしたら配列数以下のランダムな数を取得し、それを使って同じ数の配列を取得してアラートを出します。

コード

omikuzi.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
  </head>
  <body>
    <div id="app">
      <button @click="result">結果を見る</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="js/omikuzi.js"></script>
  </body>
</html>
omikuzi.js
new Vue({
  el: '#app',
  data: {
    list: [
      '大吉',
      '中吉',
      '小吉',
      '末吉'
    ],
  },
  methods: {
    result: function() {
      const num = Math.floor(Math.random() * this.list.length)
      alert(this.list[num])
    }
  }
});

ではhtmlからコードの説明をしていきます。
まず<div id="app">はVue.jsの影響を及ぼす範囲のルートになります。
omikuzi.jsでel: '#app'と記載しているのでそれ以外の場所には影響を与えません。
Vue.jsをシンプルに理解しよう その2
詳しくは上記記事をお読みください。

次に<button @click="result">結果を見る</button>ですが、
これはボタンをクリックした時にresultメソッドを呼び出すという意味になります。

最後に<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="js/omikuzi.js"></script>ですが、これはVue.js本体とresultメソッドを書いているomikuzi.jsを読み込むという意味になり、この読み込みが無い場合はVue.jsの機能である@clickやomikuzi.jsに書いてあるresultメソッドを呼び出せなくなるため正常に動作しません。

次にjavascriptファイルの説明をしていきます。
まずnew VueですがこれはVueインスタンスを作成しています。
Vue.jsはnew Vueで作成されたルートVueインスタンスの中にメソッドなどをツリー状にして保存しているのでnew Vueが無い限りVue.jsは動かないと思います。(Vue.js初心者の言うことだからもしかしたら違うかも?)
詳しくはVue.jsの公式ガイドをお読みください。

次にdata:の中にあるlist:に配列で大吉などの○吉を入力しています。
これでlist[0]と書くことで大吉を呼び出すことができます。

次にメソッドの説明をしていきます。
methods:の中でresult: function()と書くことでresultメソッドを作成しています。
resultメソッドに記載しているconst num = Math.floor(Math.random() * this.list.length)はnumという箱にランダムな数字を生成して入れるという意味です。
もっとわかりやすく書くとMath.floorは【小数点以下を切り捨てる】、Math.random()は【0以上1未満の数字をランダムで生成する】、this.list.lengthはlistの配列のデータの数を意味しています。

なので0以上1未満の数をランダムで生成してlistのデータの数だけ掛け算して、計算結果の小数点を切り捨ててnumに保存するという意味になります。

最後にalert(this.list[num])ですがalertは文字通りアラートを出します。
alertの()内にどのデータをアラートで表示するかを記載できるのでthis.list[num]でlistにある先ほど生成したランダムな数値を使って配列のデータを表示します。

最後に

一応私なりに頑張って書きましたが、かなり冗長になってしまいました。
ここが分かりづらいやこうするのがおすすめなどのご意見ありましたらコメントにお願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webpack関連

Vue.jsで開発でWebpack関連でつまずくことが多かったので得た情報をまとめていく

Webpack4、CopyWebpackPluginのwebpack.config.js

Webpackはバージョンアップごとに設定ファフィルの記述方式が変わるらしい
↓見出し環境下での基本的な設定方法↓

webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: "**/*.html",
          to: "./sample",
          context: ".src/sample",
        },
      ],
    }),
  ],
};

正直よくわかってない

参照ページ

https://tadtadya.com/webpack4-error-of-version-up-of-copywebpackplugin/

ValidationError: Invalid options object.

Vue.jsでnpm run dev実行時に発生したエラー

ValidationError: Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
 - options[0] misses the property 'patterns'. Should be:
   [non-empty string | object { from, to?, context?, globOptions?, filter?, toType?, force?, flatten?, transform?, cacheTransform?, t
ransformPath?, noErrorOnMissing? }, ...] (should not have fewer than 1 item)

トップディレクトリ/build/webpack.dev.conf.js内のnew CopyWebpackPlugin部分を以下のように書き換え

webpack.dev.conf.js
new CopyWebpackPlugin({
      patterns: [
        { from: 'source', to: 'dest' },
        { from: 'other', to: 'public' },
      ],
    }),

参照ページ

https://webpack.js.org/plugins/copy-webpack-plugin/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アイデアの相互評価ができるidea streamerを作りたかったああああ

アイデアの評価むつかしい問題

最近世の中でアート思考だとかデザイン思考だとかがもてはやされるようになった気がします。
でも誰か知り合いが出したアイデアって、忖度なしで評価するの結構難しいと思うんですよね。
例えば上司のアイデアだったら「いいですね!」と言ってしまいそうですし、斬新なアイデアであっても、「こいつ生意気やんけ」といって評価を下げてしまう人もいるかもしれません。

今回は「ひたすらアイデアを投稿しまくって」「それを知らない誰かに評価してもらえるidea streamerというプラットフォームを作ってみました。
途中バグがあったり画面遷移がうまくいかなかったりで、超未完成ですが一旦振り返りの意味で投稿してみたいと思います。
アイデアの相互評価」という意味で面白い仕組みだと思うので、何か刺激になればなと思います。

アプリはこちらから入って、途中で画面遷移が切れるのでアイデア評価からはこちらからお願いします!

動作デモ

アイデアのブレスト

3分間の間にひたすらアイデアを投稿しまくっていきます。
Keywordに自分の好きな単語を入れておくと、「×〇〇」の部分がランダムで変わっていきます(技術不足で途中バグってます)。
普段交じり合わない組み合わせからアイデアを発想して投稿しまくる、という感じですね。

アイデアの評価

アイデア出しが終わったら次は知らない人が投稿したアイデアの評価を行います (画面遷移の実装ができてません)。
DBにあるアイデアを見て面白い・斬新だな、などの観点で0~10の間で評価します。
現状自分のアイデアも見れるようになっていますが、そうすると自己評価になって意味がないので、他の人のアイデアだけ取り出す処理が必要そうですね。

アイデアのスコアの確認

こちらは全く実装できてません。
自分のアイデアがどう評価されたのかを確認できるようにしたいですね。

できたこととできなかったこと

実装できた

・アイデア出しする仕組み
・アイデア評価する画面
・全体の雰囲気

実装できなかった

・アイデア評価の仕組み
・自分のアイデアのスコア確認
・全部0点にしちゃうなど悪ふざけ対策
・画像がデフォルト

悔しい。。。

実装こまごま

yarnでいろいろ

今回は初めてNuxt.jsを使って実装してみました。
結構癖があるけれど使いこなせたら楽しそう。
備忘録的に記録しておきます。

$ yarn create nuxt-app myNuxtTest
Project name: myNuxtTest
Programming language: JavaScript
Package manager: Yarn
UI framework: Bootstrap
Nuxt.js modules: Axios, Progressive Web App (PWA), Content
Linking tools: (Press <space> to select, <a> to toggle all, <i> to invert election)
Testing framework: None
Rendering mode: Universal (SSR / SSG)
Deployment target: Static (Static/JAMStack hosting)
Development tools: None
$ cd myNuxtTest

pagesの中に画面を作ったり、componentsにコンポを作り終わったら、

$ yarn dev

を実行後localhost:3000へアクセスし、画面を確認します。上手く動作していれば、

$ yarn generate

でhtmlを生成し、distフォルダをデプロイ、という流れです。
generateしてフォルダ構造がどう変化するかをちゃんと把握していなかったため、画面遷移がうまくできなかったです。。。悔しい。

Netlifyにデプロイしたのち、freenomで取得したドメインでURLを生成しました。
freenomは今回初めて使いましたがこんなにお手軽にドメインが借りれるのは驚きですね。

タイマーがゼロになったら次へ

カウントダウンタイマーはこちらのサイトを参考にさせていただきました。
カウントがゼロになったら自動で画面遷移するようにしたかったものの、うまく実装ができず。。。
ひとまずはv-showで表示非表示を制御して、ユーザにクリックしてもらう作戦に変更しました。

<template>
<div>
    <div v-show="show">
        <div id="timer">
            <div class="timer">
                <div class="time">
                    {{ formatTime }}
                </div>
            </div>
        </div>

         <h3>
            <input v-model="key" placeholder="KeyWord" class="key"> × {{reactant}} = <input v-model="idea" placeholder="Input Your Idea" class="idea">
         </h3>
         <br>
         <h3>
            <button v-on:click='random' class="button--green">Pass</button>
            <button v-on:click='post' class="button--green">Post</button>
        </h3>
    </div>
    <div v-show="shownext">
        <a
            href="ScoreIdea"
            target="_blank"
            rel="noopener noreferrer"
            class="button--green"
        >
            Next Step
        </a>
    </div>
</div>
</template>

script部分はカウントダウンする部分の処理と、データをDBへPostする処理を実装しました。
vueのライフサイクルをまだ理解しておらず、createdやmountedが使いこなせていないです。。。
いやあこのあたりもちゃんと理解したい。

<script>
import firebase from "firebase/app";
import "firebase/firestore";

export default {
    components: {},

    data(){
        return{
            db: {},
            reactant: 'Click Pass',
            allData: ["文化","コロナ","","飲む","食べ物","おいしい","恋愛","決める","地面"],
            show:true,
            shownext:false,
            min: 2,
            sec: 59,
            timerOn: false,
            timerObj: null,
        }
    },

    methods: {
        //初期化
        init: () => {
            const config = {
                //firebaseの情報
                };

            // Initialize Firebase
            firebase.initializeApp(config);
            },

        //カウントダウン処理
        count: function() {
            if (this.sec <= 0 && this.min >= 1) {
                this.min --;
                this.sec = 59;
            } else if(this.sec <= 0 && this.min <= 0) {
                this.complete();
            } else {
                this.sec --;
            }
        },

        //カウントがゼロになった処理
        complete: function() {
            clearInterval(this.timerObj)
            this.show = false;
            this.shownext = true;
        },

        //ボタンを押したらランダムに表示
        random: function(){
            const rnd = Math.floor(Math.random() * this.allData.length);
            this.reactant = this.allData[rnd]
        },

        //データ追加の処理
        post: function(){
            const testId = firebase.firestore().collection('test').doc().id; //ユニークなIDを生成
            const docRef = firebase.firestore().collection('test').doc(testId);
            const setAda = docRef.set({
                key: this.key,
                reactant:this.reactant,
                idea:this.idea
            });
            this.random();
            this.idea = "";
            //window.location.href = "JoinTable";
        },

        //データ取得の処理
        get: function(){
            //this.allData = [];
            firebase.firestore().collection('test').get().then(snapshot => {
                snapshot.forEach(doc => {
                    console.log(doc);
                    this.allData.push(doc.data());
                })
            });
            this.random();
        }

    },

    //インスタンスが生成したときの処理
    created(){
        let self = this;
        this.timerObj = setInterval(function() {self.count()}, 1000)
        this.timerOn = true; //timerがOFFであることを状態として保持
    },

    //常に動く処理
    computed: {
        formatTime: function() {
        let timeStrings = [
            this.min.toString(),
            this.sec.toString()
        ].map(function(str) {
            if (str.length < 2) {
            return "0" + str
            } else {
            return str
            }
        })
        return timeStrings[0] + ":" + timeStrings[1]
        }
    },

    //マウントされたときの処理
    mounted(){
        this.init();
        this.get();
    },
}
</script> 

あとはデザイン部分ですね。
これはほとんどデフォルトのものを利用しています。

<style>
input{
    text-align: center;
}
input.key{
    width:160px;
    height:50px;
    }

input.idea{
    width:260px;
    height:50px;
    }

#timer {
  display: flex;
  align-items: center;
  justify-content: center;
}
.time {
  font-size: 100px;
}
</style>

さいごに

フレームワークの便利さを感じれるほどまだ慣れておらず、この辺りは経験積んでいくしかないですね。
この辺は精進していかなきゃなあと思います。
アイデア自体は悪くないと思うのに悔しい。。。

最後までご覧になっていただきありがとうございました!
LGTMしていただけると励みになりますので、是非是非よろしくお願いします!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Electron(+Vue)でnode-oracledbを利用する

はじめに

Windows環境でのVue+Electronアプリ開発においてOracleデータベースへのアクセスに一苦労あったので実現方法を備忘録として残す。

環境

  • Windows 10
  • npm 6.14.8
  • Vue CLI 4.5.4

プロジェクト作成

Vueプロジェクト作成

Vue CLIを利用してVueプロジェクトを作成。Vue 3.x+Typescriptを選択。その他オプションは下記の通り。

>vue create electron-oracle

Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, TS, Linter
? Choose a version of Vue.js that you want to start the project with 3.x (Preview)
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N)  No

Electron化

VueプラグインからElectron化する。途中でバージョンを聞かれるので^9.0.0を選択する。

vue add electron-builder

動作確認

ここまでで自動生成されたコードの動作確認をする。
Electronアプリケーション上にVueのいつものページが表示されていればOK。

npm run electron:serve

node-oracledbインストール

ポイント
Electronで利用する場合はElectron独自のパラメータを利用してoracledbビルドする必要があるが、npm経由でインストールした場合はそれがされておらず、またリビルドの対象にもならないため使えないらしい。(参考

そのため、ソースからインストールする必要がある。

事前準備

ビルドに必要なライブラリを事前にインストールしておく。

windows-build-tools

Windowsの場合はコンパイラセットとしてwindows-build-toolsをインストールする。コンパイラインストール時に管理者権限が必要なので「管理者として実行」したコマンドプロンプトで実行すること。

npm install --g --production windows-build-tools

(Visual C++ build toolsがうまく入らなかったのでVisual Studio Build Toolsから手動インストールした。)

node-gyp

node-gypコマンドが必要になるのでグローバルインストールしておく。

npm install -g node-gyp

インストール後はコマンドとして実行できることが確認できる。

>node-gyp --version
v7.1.0

インストール

GitHubのソースアーカイブを指定してインストールする。URLはリリースノートを参照して必要なバージョンに適宜変更すること。

npm install --save https://github.com/oracle/node-oracledb/releases/download/v5.0.0/oracledb-src-5.0.0.tgz

データベースアクセス実装

基本的な実装方法は公式のサンプルを参照のこと。

ポイント
node-oracledbはNode.jsのライブラリなので、ElectronではMainプロセスで実行する必要がある。
すなわち画面操作からキックする場合はIPC通信によりRenderプロセスからMainプロセスに処理をリクエストする必要がある。
(※RenderプロセスでipcRendererを利用するのに一工夫が必要。今回はローカルで完結するアプリケーションであったため簡単にnodeIntegration: trueとした。)

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.js css background-image を指定

vue.js で background-image を指定したい。

hoge.vue
<div v-if="bg" :style="{ 'background-image': 'url(' + bg + ')' }" style="padding-top: 16%;background: no-repeat center center;background-size: cover;"></div>


//略
data () {
    return {
        bg:'',

これで bg の値が変わるたびに 背景も変化する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

セクション13 vue router

routerの初期設定

npm install vue-router

srcファイルにrouter.jsを作る

main.jsでrouterのインポート登録

router-viewの記述

active-class
exact

ボタンでurlの移動
this.$router.push('users');

動的にurlを操る
コロンをつける
path:'/users/:id'

idにアクセスする
{{$route.params.id}}

props:true
props:["id"]
で、idだけで表示できるようになる

childrenでrouter-viewをネストすることができる

v-bindで動的にurlを変える

<router-link :to="'/users/'+(Number(id)+1)+'/profiles'">

名前月つきルートを使う
```

{path:"profiles",component:UsersProfiles,name:"users-id-profile"},
```

名前をつけると、同じページでいろんなrouter-viewが使える

routes:[
    {
        path:'/',components:{
        default:Home,
        header:HeaderHome
    }

名前つきrouter-viewを使うときはpropsをオブジェクトにする

 props:{
            default:true,
            header:false
        }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

npm関連の話

Vue.jsでの開発を行う上で遭遇したエラー等について得た情報のまとめ

目次

  • npm ERR! Cannot read property 'match' of undefined
  • パッケージのバージョン管理
    • バージョンの確認
    • npm-check-updatesが便利
  • npm audit
  • Error: Cannot find module 'webpack-cli/bin/config-yargs'
  • compilation.mainTemplate.applyPluginsWaterfall is not a function

npm ERR! Cannot read property 'match' of undefined

npm installを行った際に遭遇
package-lock.jsonとのズレがあると起こるらしいのでpackage-lock.jsonを消してやると解決

参照ページ

https://qiita.com/mojirico/items/8db742fa5f22e3e719c4
https://www.nekoni.net/Blog/Article/npm-err-cannot-read-property-match-of-undefined

パッケージのバージョン管理

バージョンの確認

通常

terminal
npm list --depth=0 # インストール済みの全てのパッケージ

npm outdated # 古くなったパッケージ
# 各列の意味
# Current => 現在インストールされているバージョン
# Wanted  => package.jsonのsemverを満たす最新のバージョン
# Latest  => 最新バージョン

npm-check-updatesが便利

terminal
npm install -g npm-check-updates # インストール

ncu # 現在のバージョンと最新バージョン
ncu -u # package.jsonの更新
ncu -a # マイナーバージョン以下アップデートについても更新

参照ページ

https://dackdive.hateblo.jp/entry/2016/10/10/095800

npm audit

npm install時などに脆弱性を警告されたパッケージについての処理
1. npm auditで脆弱性のあるパッケージを一覧表示
2. npm i [パッケージ名] -Dで修正済みパッケージをインストール
3. npm ls [パッケージ名]でパッケージの依存関係を確認
4. 上記実行時にdedupedを表記されているパッケージを削除(FinderでもOK)
5. npm dedupeで依存関係を整理

package.jsonの更新を自動化すればもっと楽らしい

参照ページ

https://qiita.com/hibikikudo/items/0af352acac85fce28ec2

Error: Cannot find module 'webpack-cli/bin/config-yargs'

sass-loader等を使い始めてからnpm run devで吐かれたエラー
webpackwebpack-cliwebpack-dev-serverのバージョンの組み合わせの問題らしい
全て最新版をインストール

terminal
npm isntall --save-dev webpack@latest # webpack

npm install webpack-cli -D # webpack-cli

npm isntall --save-dev webpack-dev-server@latest # webpack-dev-server

npm install vue-loader@latest # vue-loader

参照ページ

https://qiita.com/Shoryu_N/items/9ae2417489c9faaa271c

compilation.mainTemplate.applyPluginsWaterfall is not a function

パッケージの脆弱性を解決すると消えた

参照ページ

https://qiita.com/mitsuya_bauhaus/items/c31b146fb9649469f8d1

npmERR! code ELIFECYCLE

npm run dev実行時に発生
特定のエラーを指すものではないようなので、続くエラー文を読んで対応するのがいいと思う
一応、node_modulesフォルダを再インストールで解決はするっぽい

rm -rf node_modules
rm package-lock.json

npm install

参照ページ

https://note.com/koushikagawa/n/ne58862ebd22d

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue-property-decoratorを用いてVueXにTypeScript導入

まずは今回用いる


VueX

TypeScript

について簡単に説明します。

VueX

状態管理します。
Global変数のことを指していると自分は理解しています。

どのcomponent
からもこのvuexで管理されている

メソッド

にアクセスできるようになります。

TypeScript

スーパーJSと自分は理解しています。

javascriptにできることは全てtypescriptで対応できます。

typescriptは画面で用いられる際はjavascriptにコンパイル(変換)
されて利用できるようになります。

vue-property-decoratorとは??

自分が新規の案件でvueを用いて開発しようとしたときに用いることになったツールになります。
ツールという表現が正しいかは置いておきます。

現在VueXにも型安全を取り込もうとTs
を導入した場合

VueX内では簡単に用いさせてくれませんでした。
シンプルいVueとTsはあ仕様が悪いです。

Vue.3.0を待ちましょう。。。。

なので

vue-property-decorator

をこの度は用いました。

少しVueの書き方とは異なるclassを用いた書き方のためてこずってしまいましたが慣れてきたので今回紹介させていただきます。

導入

Vue Cli使ってください。

https://qiita.com/nunulk/items/7e20d6741637c3416dcd

この記事を参考に

tsとVueXを用いる部分を参考にしてみてください。

npm install -S vue-class-component
npm install -S vue-property-decorator

でdownloadです。

src/store/planディレクトリを作り
planでぃレクトリ配下に

plan.ts
types.ts

をそれぞれ作ります。

plan
 |
 |--plan.ts
 |--types.ts

イメージはこんな形です。

plan.ts

plan.tsの中身は本来VueXで定義している中身を記述します。

plan.ts
import {
  Module,
  VuexModule,
  Mutation,
  Action,
  getModule,
} from 'vuex-module-decorators';
import store from '../store';
import { Plan, PlanDetail, setPlan } from './types';

@Module({ dynamic: true, store, name: 'PlanModule', namespaced: true })
class PlanModule extends VuexModule {
  public plan: Plan[] = [];

  //planのgetterメソッド
  public get getPlans(): object {
    return this.plan;
  }

  @Mutation
  public setPlan(payload: setPlan) {
    console.log(payload);
    this.plan[payload.planId] = payload.payLoad;
  }

  @Action
  public addPlan(payload: object): void {
    let planCount = Object.keys(this.plan).length;
    console.log(planCount + 1, payload);
    this.setPlan({ planId: planCount + 1, payLoad: payload });
  }
}

export default getModule(PlanModule);

@Module({ dynamic: true, store, name: 'PlanModule', namespaced: true })

おまじないみたいなものなので覚えましょう。詳細は調べてみてください。

state

VueX内では
stateで定義されていたVueX内のパラメータは

plan.ts
  public plan: Plan[] = [];

に変わっています。
このPlan型はまた記述しますが型を持ったinterfaceになります。

なのでこのplan変数の中にグローバルで用いたい値が入ってきます。

getter

getterメソッドもまたVuexとは異なり

plan.ts
  //planのgetterメソッド
  public get getPlans(): object {
    return this.plan;
  }

このような形でgetを頭につけてメソッド名を定義してあげます。
でts導入しているので型を宣言してあげます。

慣れてきたでしょうか?

Mutation

plan.ts
  @Mutation
  public deletePlan(planId: number) {
    this.plan.splice(planId, 1);
  }
//stateのplanを変更する処理のみを行うメソッドになります。
//変更する値は基本的にactionから渡してもらいます。

@Mutationを記述するだけで簡単にmutationの中身をかけます。

vuexのMutationの説明になりますが

  • 基本的にstateを変更するメソッドのみ
  • 複雑ななロジックは書かない
  • stateを唯一変更することができるメソッドをかける

そういったメソッドを持っています。

なのでもし状態を管理するstateを変更したい場合は
必ずこのmutationを経由する必要があります。

Action

plan.ts
  @Action
  public addPlan(payload: object): void {
    let planCount = Object.keys(this.plan).length;
    this.setPlan({ planId: planCount + 1, payLoad: payload });
  }
//Actionの記述になります。

こちらもMutation同様に@Actionを記述するだけとなります。

  • componentから受け取った処理を記述する。
  • 非同期処理を行う + state変更は行はない

が特徴のメソッドになります。
state変更は行えますが、行わないというルールがありますので従います。
Actionで変更できるようにしてしまうと、どこが原因でエラーが起きているかなどが追いづらくなります。
stateの変更は決して行わないことに注意です。

外部で読み込み可能に

export default getModule(PlanModule);

この記述を最後に入れておかないと他のComponentで
読み込むことができなくなりますので注意です。

では先ほど作成したModuleを外部から用いていきましょう!

Componentから用いる

PlanListComponent.vue
//PlanListComponent.vueというPlanをlistにしたComponentになります。

<template>
  <div>
    <v-content v-for="(plan, index) in plans" :key="index">
      <v-hover v-slot:default="{ hover }">
        <v-card
          :elevation="hover ? 14 : 2"
          class="mx-auto pa-3"
          max-width="344"
          outlined
        >
          <v-card-title>
            {{ plan.planTitle }}
          </v-card-title>
          <v-card-text>
            {{ plan.issueContent }}
          </v-card-text>
          <v-container fluid fill-height>
            <v-row class="d-flex align-center justify-space-around">
              <v-btn>編集</v-btn>
              <v-btn @click="planDelete(index)">削除</v-btn>
            </v-row>
          </v-container>
        </v-card>
      </v-hover>
    </v-content>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import PlanModule from '../../store/plan/plan';

@Component
export default class PlanListModule extends Vue {
  public plans: object = {};

  created() {
    this.plans = this.getPlans;
  }

  protected get getPlans() {
    return PlanModule.getPlans;
  }

  planDelete(planId: number) {
    PlanModule.deletePlan(planId);
    this.plans = this.getPlans;
  }
}
</script>

上記のようなファイルを作ってみました。

肝になってくるのは

import PlanModule from '../../store/plan/plan';

で先ほど作成した

export default getModule(PlanModule);

Moduleをimportしてくる箇所です。
importさえしてしまえば

  protected get getPlans() {
    return PlanModule.getPlans;
  }

  planDelete(planId: number) {
    PlanModule.deletePlan(planId);
    this.plans = this.getPlans;
  }

Module名.Moduleで定義したメソッド名で

そのModuleのメソッドが使えてしまいます!
これでVueX内も役割ごとに大きく分割できます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MDBootstrap Vueことはじめ

プロジェクトのクローン

# ユーザーディレクトリ直下にワークスペースを作成
cd && mkdir GitHub && cd GitHub

# git cloneする
git clone https://github.com/mdbootstrap/Vue-Tutorial-Agenda-App.git

インストールと起動

# 作業ディレクトリに移動
cd ~/GitHub/Vue-Tutorial-Agenda-App/getting-started/start-here

# npmがインストールされているかチェック
npm -v

# 依存関係のインストール
npm install

# サーバーの立ち上げ
npm start

アクセスしてみる

http://localhost:8080/

Vueプロジェクトの構造について

構造

.
├── License.pdf
├── README.md
├── build
├── config
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── App.vue
│   ├── assets
│   └── main.js
└── static

主要な要素

要素 役割
node_modules Vueをビルドするために必要なライブラリー
src アプリケーションのソースコード
assets 画像やアイコンなどの静的アセットが配置される
App.vue ルートコンポーネント(他の全てのコンポーネントがネストされる)
main.js App.vueコンポーネントをレンダリングし、DOMにマウントする
index.html アプリのメインファイル
  • コンポーネントとは、構成要素のこと

App.vueのシングルファイルコンポーネント

  1. Template
  2. Scripts
  3. Styles

=> 詳しくは次の投稿で解説

参考

Getting started - Material Design for Bootstrap

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ゴリゴリのSIerのSEが初めての個人開発で公開まで頑張ってみた過程

ゴリゴリのSIerのSEが個人開発でWebサービスを作ってみた
の続き、みたいな。

前回「Webサービスを作ってみた」話を書きました。
書いたやつを見て思ったんですが、ほとんどWebサービスの紹介でSIerの要素があんまり入ってない。
前回の意図としては、Webサービスそのものをアピールするというより「SIerはBPに投げるだけでプログラミングなんてしないよ」なんていう声をたまに聞くので、SIerの経験しかないSEがプログラミングやってWebサービスっぽいものを作るとこんな感じになりますよ、というひとつの実験結果をお見せしたかったのです。

それが成功か失敗かは置いといて。

ただ、「こんなの作りました」しか書いてない気がするので、大まかにどんな過程で開発を進めていったかを書きますので、何かの参考になれば…と思います。

ほんと大まかです。
モダンではありません。
読み物的な感じです。
「ポエム」タグです。

1.動機づけ

今回は「作りたいもの」が自分の開発のきっかけになりました。
なぞるように一から体系的に学ぶのもいいですが、「作りたいもの」に必要な機能、その機能に必要な技術は何か?って考えながら進めていくと結構時間を忘れてどんどん形になっていきました。
とはいえ「作りたいもの」はそんな簡単に出てこない気もするので、いろんな人に「何か欲しいもの」をひたすら聞くのも良いと思ってます。
それを「作りたいもの」にすればもうあとは手が勝手に動くと思います。

2.開発環境

そう思い立って、では何から始めるか…
本番環境をイメージしました。
私はモダンな経験はしていません。
「まぁ最初の個人開発だしサーバーは1台でいいか~、で、Web/APサーバーに Apache Tomcat、DBはMySQLでもいいけど今回は触ったことのないMariaDBの方で!」
みたいな。
あとは言語。
言語は前に書いた通り、未経験のVueと経験のあるJavaでバランスよく学んでいこうという思いでフロントはVue、バックエンドはJava(Spring Boot)にしました。
そしてエディタ。
私はC#とJavaの経験があり、業務で使った経験があるのはVisual StudioとEclipseです。
Visual Studioのライセンスは持ってません。
Eclipseは経験上、重くて起動時にたまにコケてたのが気になります。
よく目にするVS Codeが軽くてJavaにも使いやすそうなのでVS Codeにしました。
ソースのバージョン管理は特にしていません。
コンテナ的なものもありません。

3.Javaで開発スタート

まず、ログイン画面から作り始めました。
最初にログイン画面って…あんまりおもしろくないですね。
Spring Bootの機能を利用して実装しました。

次にSIerの基本、マスタメンテナンス画面。
SIerが開発を学ぶためにまず最初に作らされるのがマスメン画面というイメージ。
経験があるのでとりえず実装完了。
このときはまだ見た目に何の装飾もしていません。
ヨメに「こんなのできたんだけど」とログイン画面とマスメン画面を見せてみました。
反応は「こんなのに何時間かけてんの?」みたいな反応でした。
機能がどうのこうのというより、見た目のしょぼさのインパクトが強かったみたいです。
これは私のモチベーションが下がったぁぁ
…ということでこの時点になってVueを導入しました、

私は、Vue未経験者です。(素のJavaScriptはそれなりに扱ってます)
何かライブラリになってて、ファイルをどこかに置いて参照する感じ?って思ってました。
学習用ならそんな感じでもいいかもしれませんが、Node.js、Vue CLIをインストールし、Vue CLIからプロジェクトを作成すると想像と違うものが出てきました。
単体で動かす感じ…
な私のVueレベル。
※あとで公式を見たら「初心者が vue-cliで始めることは推奨しません」って書いてある…
とりあえず見た目を何とかしたいので業務で扱ったことのあるBootstrapでも入れればいいのかなと思いましたが、調べるとElementというコンポーネントライブララリがVueとセットになってる記事をよくみかけたので、Elementを採用。
Vueの説明の最初らへんで「リアクティブ」って言葉をよく見かけましたが、その言葉に最初はピンときませんでした。
今は「動的に変わる」ってことだと思ってます。

4.開発の流れ

業務では仕様書を書いてレビューしてもらって直してまたレビュー…の繰り返しですが、今回はそんな細かくやってません。
SIerとして「要件定義→外部設計→内部設計→実装→テスト色々→リリース」まで一通り経験してるので、頭の中では色々やってたかもしれません。
今回の流れとしては、機能ごとに
・画面イメージのメモ
・画面遷移図のメモ
・DBのテーブル設計のメモ
を作ったくらいです。
しかもそれらは今現在手元にありません。
紛失です。
業務の引継ぎ時は「仕様書はありません。ソース見てください」って伝える必要があります。
画面イメージや画面遷移が変わってもだいたい機能内で閉じてたので影響は少なかったのですが、テーブルの項目が変わると他の機能への影響が大きかったり色々面倒臭かったので、そっちはもう少しちゃんと考えてたほうがよかったな…と今は思ってます。

5.いきなりAPI

さて、Node.jsとTomcatという二つの実行環境ができました。
今さらですがここらへんでバックエンドをREST API化するイメージが固まりました。
開発時はJavaのプロジェクトにVueのプロジェクトを突っ込んで、Node.jsとTomcat両方立ち上げてました。
本番環境ではビルドしたVueのファイルがwarファイルに含まれるようにして、全部Tomcatに乗せました。
※APIのURLの先頭を/api/… にしないとVue側とURLがかぶってしまう問題が発生したのは後のこと…

6.Vue + Java(Spring Boot)で開発スタート

ログイン画面とマスメン画面をVue + Spring Boot(REST API)で作り直し。
ここら辺は探すと色々やり方が出てくるのでそこまで詰まることはなかったです。

バリデーションには最初Elementを使ってましたが、サーバーサイドのエラーを扱おうとしたとき上手く使えなかったので、VeeValidateに切り替えました。
VeeValidateでなんとかやってます。

実装の流れはだいたいルーティーン化していました。
画面作成(Vue)→テーブル作成(DB)→リポジトリクラス作成(Java)→サービスクラス作成(Java)→コントローラークラス作成(Java)→REST APIアクセス部分作成(Vue)→画面調整(Vue)
これを機能ごとに繰り返す感じです。

ちなみに私のSIerとしての経験的に、ちょっとデザイナーと仕事をしたことがあるくらいで私にはデザインの知見がほとんどありません。なのでデザインに関しては何とも言えない仕上がりになっています。

7.その他各機能の作成

各機能の作成は経験と世にあふれてるサービスを参考にしました。
排他制御は細かくやりました…
あと、世にあふれてるサービスを参考にしなくても、チャットなんかは実装方法を教えてくれてるサイトがたくさんありました。
ただシンプルなチャットが多いので、メンバーがオンラインかとか削除機能とかアイコンの表示とかは自力で考えました。

チャットのメッセージを削除する機能をあとから実装しようとしたら、テーブルの構造上消せないということが判明しました。
その時点でチャットに関するテーブルの構造を結構見直したので、影響範囲が大きかったです。
メッセージの削除はあとでいいかな~と思ってましたが、テーブルの構造はある程度そこも考慮に入れるべきだったな~と思ったりもしました。

ちょくちょくヨメに見せてましたが、けっこう辛辣なことを言ってくれました。
特にデザインと操作性ですね。
そこまで言う?くらい。
まあユーザーにとって大事なのはそこなんですよね。
ヨメの身も蓋もない指摘でダメージを受けつつ良くなった部分もあるので感謝です。

8.迫りくるネガティブ

開発中、ときどきあいつはやってきます。
「こんなサービス誰が使うのか…?」という蠢き。
それは大きな影となり、視界を闇で包みます。
レビュー「クソサービスですね」
レビュー「使えない」
レビュー「バグ多すぎ」
頭の中をマイナスの評価が駆け巡ります。
そして手を止めて、すべてを捨て去りたくなります。
そうやって途中で止めて放置状態になった作りかけのアプリは至る所で眠っているでしょう。

こういうときは本来ユーザー目線でやりがいを取り戻すべきなのかもしれませんが、私はプログラミングの楽しさに逃げました。
で、気持ちが落ち着いてきたらまたユーザー目線に戻ります。
それの繰り返しでなんとかモチベーションを保っていました。

9.ちょっと苦労したユーザー間で同期するタスク管理

チャットみたいにWebSocketでユーザー同士の画面を同期させる機能をタスク管理にもつけてみようかな~と思い、Vue.Draggable + WebSocket で実現しようと思ったのですが、一つ微妙に、いやかなり気になる現象が発生しました。

Vue.Draggable の奇妙な動きを対症療法でなんとかする

動きが微妙なのです。
結局丸2日くらい悩んで対症療法で何とかしました。

10.公開準備

サーバーはAWS EC2 を利用しました。
最初は無料枠のインスタンスを利用していましたが、メモリが少なすぎてパフォーマンスに影響が出たので、有料でも少しスペックのいいものにしました。
勉強代、勉強代…
ここにDBとWeb/APサーバーをセットアップして、ビルドしたモジュールを乗せるだけ。

一通り機能を作り終えたら、公開に必要なドメイン取得、HTTPS化にとりかかりました。
何か大変なんだろうな~と思っていましたが、AWSでドメイン取得、HTTPS化はあっさり完結しました。
.comドメインは年1,000円くらいかかるみたいですが…
無料より手軽さを優先しました。

準備が整ったら、あとは告知するのみ。
今回は自分がアカウントを持ってるSNSで告知しました。
このボタンを押せば告知…って思うとなかなかの指プルプル状態でした。

11.公開後

さほど変わりはありません。
辛辣なコメントをいただき沈むこともありますが…
利用してもらうのはなかなか難しいと思ってます。
今後、どうすべきかあまり決まっていません。
公開してからが一番大事な気がしますが。

12.最後に

開発するぞ!と決めてから公開するまで大まかにこんな感じです。
技術的な要素はほとんどありませんが、ポエムということで。
やってて思ったのは、「あ~これ絶対に解決しなさそう!」って思っても長くても一週間以内にはなんとかなるということです。
意外に解決します。
ベタですがお風呂とかトイレの中で思いついたり。

やってて「こんなサービス誰か使うのか…?」という疑問は常に付きまといます。
実際誰も使わない気もします。
でもやっぱり一回公開まで経験することは大事だと思います。
ダメならまた作ればいいだけですし。
私は心臓が剛毛なメンタル強者ではないですが、へこみつつも何とか前に進む気はあります。
なのでこれまで一度も公開用のアプリを作ったことの無い方も、一度作ってみてはどうでしょうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.js コンポーネントの書き方

Vue cliを使わないcdn版でのコンポーネントの書き方です。
いくつか書き方があり迷うので自分メモ的に投稿致します。
大きくわけてグローバル登録とローカル登録があります。

コンポーネントの書き方(グローバル登録)

コンポーネント名はHTMLタグになるもの
テンプレート名は直接HTMLタグを書くか、HTML内に記述したx-templateの対応するidを設定

//コンポーネント1
Vue.component('コンポーネント名A', {
    template: 'HTMLタグを記述、もしくはテンプレートのid',
    data: function() {
        return {
            number: 12
        }
    }
})

//コンポーネント2
Vue.component('コンポーネント名B', {
    template: 'HTMLタグを記述、もしくはテンプレートのid',
    data: function() {
        return {
            msg: 'hello!'
        }
    }
})

//HTML内で表示したいブロック
new Vue({ el: '#app' })

new Vue({ el: '#app2' })

グローバルなので#app、#app2どちらのブロックでもすべてのコンポーネント名がHTMLタグとして使用できます。

  <div id="app">
    <コンポーネント名A></コンポーネント名A>
  </div>
  <div id="app2">
    <コンポーネント名A></コンポーネント名A>
    <コンポーネント名B></コンポーネント名B>
  </div>

コンポーネントの書き方(ローカル登録) 推奨

定義したコンポーネントの定数名を、new Vue内で使いたいel:に使いたいタグ名で登録する

//コンポーネントを定義
const 定数名 = {
    template: 'HTMLタグを記述、もしくはテンプレートのid',
    data: function() {
      return {
        msg: 'キーワードを入力してください',
      }
    }
  }

new Vue({
  el: 'HTML内の使いたいブロックをCSSセレクタで記述',
  components: {
//上のelでマウントしたHTML内のブロックに
//下の 'HTMLタグ名':定数名 を使います宣言
    'search-component': Search
  }
})

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option. - did you register the component correctly? For recursive components, make sure to provide the "name" option.

というエラーを吐かれたときはコンポート名が間違っていないか確認してください。

まとめ

基本的にローカル登録を推奨

多くの場合、グローバル登録は理想的ではありません。例えば Webpack のようなビルドシステムを利用しているときに、グローバルに登録した全てのコンポーネントは、たとえ使用しなくなっても、依然として最終ビルドに含まれてしまうことでしょう。これは、ユーザがダウンロードしなくてはならない JavaScript のファイルサイズを不要に増加させてしまいます。
このような場合に、コンポーネントを素の JavaScript オブジェクトとして定義することができます。

ローカル登録手順まとめ

  • constでコンポーネントを定義
  • templateを作成(HTML内にx-templateかコンポーネントのtemplate:に直接記述)
    ※vue cli で使える.vueファイルだとファイル毎にコンポーネントをまとめて書くやり方が使える
  • template:でテンプレートを定義(直接記述でない場合x-templateのidを指定する)
  • data、methodsなどオプションを定義
    ※dataはコンポーネント側に記述する(new Vueの方にdataを記述した場合反映されない感じ?)
  • new Vue で使いたいブロックをel:に、使いたいコンポーネントをcomponents:に
  • el:複数登録不可、components:は複数登録可能
  • components:に登録したコンポーネントだけがそのel:内で使える
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js で TypeScriptを使う

vue-cli

vue-cli は vue.js のプロジェクトを準備するとき等に利用するツールです。
vue-cli でプロジェクトを作りましょう。

vue-cli を利用するには node.js をインストールして npm を利用して vue-cli をインストールします。

npm install -g @vue/cli

インストールが終わったら早速 vue-cli のプロジェクトテンプレートを利用してプロジェクトを作りましょう。
プロジェクトは vue create コマンドで作成します。
コマンドは vue create <project-name> で指定します。

vue create vue-ts-practice

起動するとプリセット選択に移ります。
Typescript を利用するために Manually select features を選択します。

Vue CLI v4.5.4
? Please pick a preset: (Use arrow keys)
> Default ([Vue 2] babel, eslint)
  Default (Vue 3 Preview) ([Vue 3] babel, eslint)
  Manually select features

とりあえず、全部チェックしておきます。

Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Choose Vue version
 (*) Babel
 (*) TypeScript
 (*) Progressive Web App (PWA) Support
 (*) Router
 (*) Vuex
 (*) CSS Pre-processors
 (*) Linter / Formatter
 (*) Unit Testing
 (*) E2E Testing

Vue.jsのversionを聞かれるので3.x (Preview)を選択します。

Vue CLI v4.5.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, PWA, Router, Vuex, CSS Pre-processors, Lint
er, Unit, E2E
? Choose a version of Vue.js that you want to start the project with
  2.x
> 3.x (Preview)

以降設定について聞かれるので お好みで設定したら、プロジェクト作成が始まるので完了するまで待ちます。

完了すると以下のような画面になると思います。

  Successfully created project vue-ts-practice.
  Get started with the following commands:

 $ cd vue-ts-practice
 $ npm run serve

記述されているように

cd <プロジェクト名>
npm run serve

と実行すると構築されたプロジェクトが起動されます。

 DONE  Compiled successfully in 23867ms


  App running at:
  - Local:   http://localhost:8080/
  - Network: http://172.16.0.66:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

No issues found.

表示されているアドレス(http://localhost:8080) にブラウザで接続してみると Vue.js のウェルカムページに遷移します。
6.jpg
このプロジェクトを利用して Typescript で Vue.js を書いていきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む