Vue3 + Express + TypeScript でウェブサイトを作る
こんにちわ、こんばんわ。
前職で無能・無能と言われたのが地味に堪えているさとかずです。
ずいぶんひさしぶりの投稿です。
「無能 + 無職 + ボッチ + 緊急事態宣言に在住 = ひきこもり」
という式が成立したため一日在宅、256歩で生活中です。
(そろそろ転職したい!誰か雇ってください。 ご連絡お待ちしております。)
転職活動のためウェブ技術をいろいろ試しています。
(意識高い(系の)人たち、後先考えずにとりあえず発表とか
下位互換無視したバージョンアップとか、すぐによく似た機能を新しく発表するとか止めてくんね?)
あれこれ試していて、ふと疑問いました。
「node.jsでフロントエンドからサーバーサイドまで一緒に作らないの?」
無能系ボッチは、ウェブサービス一つにつき
一つのディレクトリで取り組まないとできないのです。
そこで「Vue3 + express + Typescript」を利用して
無能でもできる「ハロー, XXさん」を作ってみたいと思います。
お断り
ほとんどがOPTiM様が掲載しているブログを参考にしています。
詳しいことはぜひそちらをごらんください。
参考サイト:
環境
- OS ZorinOS (Ubuntu系)
- Node.js (v16.2.0)
作成手順
vue-cliを利用してプロジェクトの作成
$ npm -g install @vue/cli
$ cd /path/to/your/favorite/
$ vue create awesome-project
vue create を実行すると対話形式で設定を行っていきます。
基本的にお好みでいいとおもいます。
? Please pick a preset:
Default ([Vue 2] babel, eslint)
Default (Vue 3) ([Vue 3] babel, eslint)
❯ Manually select features
? Check the features needed for your project:
◉ Choose Vue version
◉ Babel
◉ TypeScript
◯ Progressive Web App (PWA) Support
◉ Router
◉ Vuex
◯ CSS Pre-processors
◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing
? Choose a version of Vue.js that you want to start the project with
2.x
❯ 3.x
? Use class-style component syntax? (y/N) N
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) Y
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) Y
? Pick a linter / formatter config:
❯ ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ Lint on save
◯ Lint and fix on commit
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files
In package.json
? Save this as a preset for future projects? (y/N) N
...
インストール後の確認
$ cd awesome-project
$ yarn serve
http://localhost:8080/ に下図のように表示できていることを確認する。
確認後、terminalに戻り Ctrl + c で終了する
@types/nodeの追加
エディタの補完機能を利用するために導入します
yarn add --dev @types/node
srcディレクトリの修正
フロントとサーバーサイド側を両方管理するために、srcディレクトリにそれぞれfrontend, backendを作成する
$ cd /path/to/your/favorite/awesome-project
$ mv src frontend
$ mv pubic frontend
$ mkdir -p src/backend
$ mv frontend src
vue.config.jsの作成
awesome-project/vue.config.jsを作成する
const path = require('path')
module.exports = {
configureWebpack: {
resolve: {
alias: {
'@': path.join(__dirname, '/src/frontend')
}
}
},
outputDir: 'dist/public',
pages: {
index: {
entry: 'src/frontend/main.ts',
template: 'src/frontend/public/index.html',
}
}
}
tsconfig.jsonの修正
@@ -17,7 +17,7 @@
],
"paths": {
"@/*": [
- "src/*"
+ "src/frontend/*"
]
},
"lib": [
@@ -28,11 +28,9 @@
]
},
"include": [
- "src/**/*.ts",
- "src/**/*.tsx",
- "src/**/*.vue",
- "tests/**/*.ts",
- "tests/**/*.tsx"
+ "src/frontend/*.ts",
+ "src/frontend/*.tsx",
+ "src/frontend/*.vue"
],
"exclude": [
"node_modules"
vueのテストとビルド
$ yarn serve
http://localhost:8080/ が表示できていることを確認後、ビルドする
$ yarn build
awesome-project/dist/public ディレクトリにビルドした内容があることを確認する
expressの追加
yarn add --dev @types/compression @types/express-session @types/lusca @types/errorhandler @types/express @types/dotenv
yarn add compression express-session lusca errorhandler express dotenv
tsconfig.backend.jsonの作成
awesome-project/tsconfig.backend.jsonを作成する
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"target": "es6",
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"src/backend/types/*"
]
}
},
"include": [
"src/backend/**/*.ts"
],
"exclude": [
"node_modules"
]
}
webpackのインストール
参考サイトには記載がないのだけれども、yarn serveしたら怒られたため導入しています。
yarn add --dev webpack @types/webpack
express用のserver.tsを作成する
awesome-project/src/backend/server.tsを作成する
envなどは使用せずにserver.tsに直接書き込んでいきます
import express from 'express'
import router from "./router";
import path from 'path'
const app = express()
app.use(router)
app.use(express.static(path.join(__dirname, "public")))
export default app.listen(3000, () => {
console.log("App is running at http://localhost:3000")
})
express用のrouter.tsを作成する
awesome-project/src/backend/router.tsを作成する
import express from "express";
const router: express.Router = express.Router()
router.get('/api/version', (req: express.Request, res: express.Response) => {
console.log("/api/version")
res.json({version: '0.0.1'})
})
export default router
expressをビルドする
$ tsc -b tsconfig.backend.json
成功すると awesome-project/dist/server.js が作成されます。
expressを実行する
$ node ./dist/server.js
http://localhost:3000/api/version/ にアクセスしてjsonが出てくることを確認する
http://localhost:3000/ にアクセスしてvueの初期表示ができていることを確認する
package.jsonの編集
yarn で簡単に実行できるようにpackage.jsonの修正を行う
"scripts": {
- "serve": "vue-cli-service serve",
- "build": "vue-cli-service build",
- "lint": "vue-cli-service lint",
- "build:backend": "tsc -b tsconfig.backend.json"
+ "serve": "node ./dist/server.js",
+ "watch:frontend": "vue-cli-service build --watch",
+ "build:frontend": "vue-cli-service build",
+ "watch:backend": "tsc-watch -b tsconfig.backend.json",
+ "build:backend": "tsc -b tsconfig.backend.json",
+ "serve:backend": "nodemon ./dist/server.js"
今後、ソースを更新したときは下のように実行する
$ yarn build:backend
$ yarn build:frontend
$ yarn serve
注意 webpack yarn build:frontendでエラーが出る場合。
package.jsonのwebpackのバージョンを変更します。
"webpack": "^4.46.0"
express に apiの内容を追加する
src/backend/router.tsを編集する
import express, {Express} from "express";
import bodyParser from 'body-parser'
const router: express.Router = express.Router()
router.get('/api/version', (req: express.Request, res: express.Response) => {
console.log("/api/version")
res.json({version: '0.0.1'})
})
router.post('/api/hello', (req, res) => {
res.send(`ハロー、 ${req.body.userName}さん`)
})
export default router
curlでPOSTのResponseを確認する
$ yarn build:backend && yarn serve:backend
# 別のterminalなどで
$ curl http://localhost:3000/api/hello/ -X POST -H "Content-Type:application/json" -d '{"userName":"鈴木一郎"}'
# ハロー、 鈴木一郎さん とレスポンスされる
axiosを追加する
frontendでajaxを簡単に使用できるようにaxiosを追加します。
yarn add axios
src/frontend/components/HelloWorld.vueを修正する
ようやくHello部分です。
名前を入力するテキストフィールドとボタンを追加します。
v-modelやv-onなどが分からない場合は、Vue3で調べてください
@@ -32,15 +32,33 @@
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
+ <form>
+ <input type="text" v-model="data.userName" />
+ <button v-on:click.prevent="hello">挨拶</button>
+ </form>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
+import axios from "axios";
export default defineComponent({
name: 'HelloWorld',
props: {
msg: String,
+ },
+ setup() {
+ const data = reactive({userName: ""})
+
+ const hello = async () => {
+ const res = await axios.post("http://localhost:3000/api/hello", {userName: data.userName})
+ alert(res.data)
+ }
+
+ return {
+ data,
+ hello,
+ }
}
});
</script>
最終的なテストを行う
$ yarn build:frontend && yarn build:backend && yarn serve
ブラウザでhttp://localhost:3000/にアクセスして、テキストフィールドに「さとかず」と入力し、挨拶ボタンをクリックする
下図のようなアラートが表示していることを確認する
動作確認を行いながらの記事作成ですが、少しでもご参考になればと思います。
それでは。
Discussion