Vue2 x Composition APIでアプリを開発する過程メモ
このスクラップについて
今までvue create
やrails new
のおかげで生きてきた人間が,初めてスクラッチでアプリケーションを立ててみる回です.「そんなことも知らないで書いてたの?」ということが100回くらいでてきます.
開発の途中でつまづいたことや,初めて知ったことをメモしてます.(本来の使い方と違うかもしれません)
このスクラップで主に触れる部分としては
- Vue2
- Composition API
- TypeScript
- TailwindCSS
- Babel
- Webpack
- MySQL
- Express
あたりになります.
ES6 + TypeScript環境
Babelはv7からTypeScriptのビルドに対応したが,型検査ができないのでtscを利用する必要がある.
- tscでTypeScript → ES6にbuild
- BabelでES6 → ES5にトランスパイル
する設定を/webpack.config.jsに記入.
module.export = {
<-- snip -->
module: {
rules: [
{
test: /\.ts?$/,
use: [
{ loader: "babel-loader" },
{ loader: "ts-loader" }
],
exclude: /node_modules/
}
]
}
}
use部分に設定したloaderは下から順番に処理されるらしい.
この場合,tscでコンパイル → babelでトランスパイル,となる.
Vueの単一ファイルコンポーネントをコンパイルするならvue-loaderがいるし,scssを書くならscss-loaderとかを別途書くのかな?
順番は
vue-loader → ts-loader → babel-loader → scss-loader
とかでいいんだろうか?
単一ファイルコンポーネントをコンパイルする
まだloaderの設定が全く分かっていないが,せっかくスクラップなので,記録という意味でも,ちょっと自分で考えて色々失敗してみる.
まずは
$ yarn add --dev vue-loader
上記のwebpack.config.jsのmodule.rules.useにvue-loaderを追記してみる.
use: [
{ loader: "vue-loader" }
],
とりあえず*.vueだけをコンパイルしたいので,これだけ.
あれ,templateとstyleってどうなるんだ.
ということで一旦templateとstyleなしで以下の形でApp.vueを作成
<script>
new Vue({
el: '#app',
data: () => ({
message: 'Hello, World!'
}),
template: '<h1>{{ message }}</h1>'
})
</script>
そして
$ yarn run build
~~~
Module not found: Error: Can't resolve './src/index.ts' in '/Users/youiw/environment/node_demo'
~~~
おっと,webpack.config.jsでindex.tsを指定してしまっていたので,App.vueに変えてから再度
$ yarn run build
~~~
ERROR in ./src/App.vue 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
~~~
これは,vue-loaderの設定が反映されてないのか,vue-loaderじゃこれをコンパイルできないのか.
と思って調べたら,まずvueパッケージをinstallしてませんでした.論外です,すみません.
くじけた
上の後かなり調べて,色々試したんですが,まったくできませんでした…
開発の期日(業務ではないですが)との兼ね合いで今回はVue CLIなしの単一ファイルコンポーネントのコンパイルは断念して,この部分は@vue/cli-serviceにお願いしようかと思います.
Vue CLIで初期化したプロジェクトを見てみる
- webpack.config.jsは生成されていない
さっきまでWebpackのバンドリングの設定をしていたwebpack.config.jsは生成されていませんでした.じゃあ何をしているのかと思ってpackage.jsonのscriptsを見ると,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
なるほど,バンドリングはvue-cli-serviceに包含されているんですかね?
あまりNPM周辺は詳しくないんですが,とりあえず@vue/cli-serviceパッケージの依存パッケージを確認してみます.
$ yarn info @vue/cli-service
{
<-- snip -->
dependencies: {
<-- snip -->
webpack: '^4.0.0',
'webpack-bundle-analyzer': '^3.8.0',
'webpack-chain': '^6.4.0',
'webpack-dev-server': '^3.11.0',
'webpack-merge': '^4.2.2',
'vue-loader-v16': 'npm:vue-loader@^16.1.0'
}
}
Webpackを使ってるっぽいです(確認方法として正しいかは不明).
ということでnode_modules/@vue/cli-service/
を見てみると,いました.
中身はこんな感じです.
// this file is for cases where we need to access the
// webpack config as a file when using CLI commands.
let service = process.VUE_CLI_SERVICE
if (!service || process.env.VUE_CLI_API_MODE) {
const Service = require('./lib/Service')
service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
service.init(process.env.VUE_CLI_MODE || process.env.NODE_ENV)
}
module.exports = service.resolveWebpackConfig()
vue-loader関連の設定はlib/config/base.js
で定義されていたので確認してみましたが,かなり複雑なコードがあったので,やはり自力でのコンパイルは断念.といっても,仕組みは理解したいので,アプリが完成して時間ができたらまた見にきます.
MySQLでDB作成,Expressで接続
一応,DB作成の部分からメモしておきます.
// DB作成
mysql> CREATE DATABASE <DB_NAME>;
// アプリケーション用のユーザーを作成
mysql> CREATE USER '<USER_NAME>'@'localhost' IDENTIFIED BY '<PASSWORD>';
// 作成したユーザーに,DBへの全権限を与える
mysql> GRANT ALL PRIVILEGES ON <DB_NAME>.* TO '<USER_NAME>'@'localhost';
それから,初めて触るのでExpressの動作確認.
const express = require('express');
const app = express();
app.get('/', function (req, res) {
res.send('Hello, World!');
});
app.listen(3000);
console.log('server is running on port 3000')
$ node index.js
server is runnning on port 3000
// 別タブ
$ curl localhost:3000
Hello, World!
というわけで,簡単にサーバーが立てられることがわかったところでMySQLのDBと接続します.
まずはドライバをインストール.
$ yarn add mysql
そして,さっきのファイルを編集して
const express = require('express');
const app = express();
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: '<USER_NAME>',
password: '<PASSWORD>'
})
connection.connect((err) => {
if (err) throw err;
console.log('Successfully connected to MySQL database!');
});
$ node index.js
Successfully connected to MySQL database!
という感じです.
TailwindCSS導入
順番が前後しますが,結局Vue CLIを使うことになったので,TailwindCSSの導入だけ済ませてしまおうと思います.
$ yarn add tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
postcss.config.jsを以下の内容で作成します.
const autoprefixer = require('autoprefixer');
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
tailwindcss,
autoprefixer,
],
};
postcss.config.jsは,Sassのようなcss pre-proccessorの一つであるPostCSSの設定ファイルです.単純なSassのコンパイルに比べると非常に高速らしい.
src/index.cssを作成し,以下を記入.
@tailwind base;
@tailwind components;
@tailwind utilities;
そして,main.tsでrequire('./index.css')
して完了.
動作確認
<template>
<div id="app">
<h1 class="text-center text-5xl text-red-500">{{ message }}</h1>
</div>
</template>
<script>
export default ({
data: () => ({
message: 'Hello, World!'
})
})
</script>
動いてます!
そういえば
webpack.config.jsをいじってたあたりで何かのタイミングで,.js,.tsファイルのアイコンが全てReactのアイコンになっちゃいました.なぜ?
Composition APIを使ってみる
今までちゃんと調べていなかったので,Composition APIはVue3から追加されたものだと思っていましたが,@vue/composition-apiプラグインはVue 2でも動かせるようです.
ということで,
$ yarn add @vue/composition-api
src/main.ts
import CompositionApi from '@vue/composition-api'
Vue.use(CompositionApi)
src/App.vue
<template>
<div id="app">
<div class="text-center p-5">
<h1>{{ state.count }}</h1>
<button class="rounded border-2 p-3" @click="increment">increment</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from '@vue/composition-api'
export default defineComponent({
setup () {
const state = reactive<{ count: number }>({
count: 0
})
const increment = () => {
state.count += 1
}
return {
state,
increment
}
}
})
</script>
おお〜動きました.初めて書いたので楽しい.
GIFじゃないので分かりにくいですが.