とある勉強会のネタで使うのでHowToがてら記事にしておこうかとおもいます。
やってみること
-
Node.jsの環境構築
-
qiitaAPIを使う準備
-
Nuxt.jsの導入
-
Nuxt.jsのTypescript設定
-
Nuxt.jsからqiitaAPI叩いて画面作ってみる
Node.jsの環境構築
私はフルスタックなんですが、いろんな言語を使うので、XXenvをまとめて管理をできるanyenvなる便利なものを使ってます。
せっかくなので、それを入れてみます。
# anyenvのsetup
$ git clone https://github.com/anyenv/anyenv ~/.anyenv
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc
$ ~/.anyenv/bin/anyenv init
$ anyenv install --init
$ anyenv install nodenv
$ exec $SHELL -l
# 各envのsetup
$ nodenv install -l
$ nodenv install x.x.x # なるべく最新のを入れる
$ nodenv global x.x.x
# 記事の内容には使わないけど私のメモがてら他のenvも
$ anyenv install goenv
$ anyenv install tfenv
$ anyenv install rbenv
$ anyenv install pyenv
$ exec $SHELL -l
$ goenv install -l
$ goenv install x.x.x
$ goenv global x.x.x
$ tfenv list-remote
$ tfenv install x.x.x
$ tfenv global x.x.x
$ rbenv install -l
$ rbenv install x.x.x
$ rbenv global x.x.x
$ pyenv install -l
$ pyenv install x.x.x
$ pyenv global x.x.x
# 全部のenvのversionが表示されるので便利
$ anyenv versions
qiitaAPIを使う準備
Nuxt.jsの導入
# yarnをメインに使うので入れておく
$ brew install yarn
# nuxtのインストール
$ npx create-nuxt-app nuxt-qiita-example
? Project name # そのままenter
? Project description #そのままenter
? Author name # そのままenter
? Choose the package manager
❯ Yarn # を選択してenter
? Choose UI framework
❯ None # 今回は使わないのでこれを選択してEnter
? Choose custom server framework
❯ Express # を選択してenter(BffAPI作るときに必要なので馴染みのあるのを入れておく)
? Choose Nuxt.js modules
❯◉ Axios # をSpaceキーで選択してenter
? Choose linting tools
◉ ESLint
❯◉ Prettier # 定番ツール使いたいのでこの2つをSpaceキーで選択してenter
? Choose test framework
❯ None # 今回は使わないのでこれを選択してEnter
? Choose rendering mode
❯ Universal (SSR) # を選択してenter
Nuxt.jsのTypescript設定
$ yarn add -D @nuxt/typescript
$ yarn add ts-node
$ yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser
$ touch tsconfig.json
$ yarn run build # nuxtの起動(初回起動時にtsconfig.jsonに初期値設定値が入る)
nuxt.config.js
をnuxt.config.ts
にリネームして以下になるように書き換える
import NuxtConfiguration from '@nuxt/config'
const config: NuxtConfiguration = {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || ''
}
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [],
/*
** Plugins to load before mounting the App
*/
plugins: [],
/*
** Nuxt.js dev-modules
*/
devModules: [
// Doc: https://github.com/nuxt-community/eslint-module
'@nuxtjs/eslint-module'
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios'
],
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios: {},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {}
}
}
export default config
.eslintrc.jsをtypescriptに対応させる
module.exports = {
root: true,
env: {
browser: true,
node: true
},
plugins: ['prettier', '@typescript-eslint'],
parserOptions: {
parser: '@typescript-eslint/parser'
},
extends: [
'@nuxtjs',
'plugin:nuxt/recommended',
'plugin:prettier/recommended',
'prettier',
'prettier/vue',
'prettier/@typescript-eslint'
],
rules: {
'nuxt/no-cjs-in-config': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error'
}
}
ここまでは、公式サポートに書いてあるものの抜粋ですが、Typescriptを使う場合でも通常のJavascriptを使う場合でもcreate-nuxt-app
で初回インストールした人は、ここからがハマりどころ。
ハマりどころ その1. Packageが古い!
まず、公式のcreate-nuxt-appでinstallしたnuxt.jsですが、package.jsonをみると
"dependencies": {
"@nuxtjs/axios": "^5.3.6",
"cross-env": "^5.2.0",
"express": "^4.16.4",
"nuxt": "^2.0.0",
"ts-node": "^8.3.0"
},
あれ、nuxtのversion古い。。。となります。
create-nuxt-appのテンプレートをアップデートしてほしいところではありますが、自分で最新版にあげてきます。
packageのversionを更新するのに
yarn にyarn upgradeInteractive
はありますが、package.jsonは書き換えてくれないので、手で書き換えるのは面倒なのでncu
を使えるようにしてversionを上げます。
$ npm install -g npm-check-updates
# ターミナルを立ち上げ直して
$ ncu # 依存パッケージの最新versionを確認
$ ncu -u # 依存パッケージを最新にアップデート
$ yarn install # 最新の依存packageをインストール
ハマりどころ その2. scriptsの定義が古い
生成されたものはこれですが、nuxt-templateのソースコードを読んだところ、選択したフレームワークによって生成されるpackage.jsonの書き方が違うようで、選択したものによっては、nuxtコマンドの使い方が非常に古いです。そうなると初見だとハマりどころ。。。
公式documentのスクラッチから始める
などをみると正しいコマンド書いてありますが、全部のっていないのとあちこちのdocumentに点在してるので正しくするとこうなります。ついでに対象をtsにしておきます。
修正前
"scripts": {
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
"build": "nuxt build",
"start": "cross-env NODE_ENV=production node server/index.js",
"generate": "nuxt generate"
},
修正後
"scripts": {
"lint": "eslint --ext .ts,.vue --ignore-path .gitignore .",
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
ハマりどころ その3. server/index.jsはいらない
その2の修正で、nodemonがなくなってると思いますが最新だとnuxtコマンドがnode-serverを立ててくれるため基本的にはserver/index.jsは不要なので一度消しちゃいます。
server/index.jsを使う場合は、nuxtの
serverMiddlewares
を利用するときですね。
以上で、Nuxt.js+Typescriptの初回環境構築は完了です。
Nuxt.jsからqiitaAPI叩いて画面作ってみる
準備
Typescriptで開発始める前に公式で推奨しているvue-property-decorator
を追加したいと思うのですが、これだとnuxtが用意しているasyncData
が使えません。あとでAPI呼び出しでasyncDataを使うため、nuxt-communityが出してるnuxt-property-decoratorを入れます。
$ yarn add nuxt-property-decorator
最低限必要なもの
Nuxt.jsはコードにルールを持たせるため、ディレクトリ構造も決まっています。
今回画面を作るうえで最低限必要なpages
ディレクトリのみ使います。
他ディレクトリの説明は公式のディレクトリ構造を参照してみてください。
pages
は簡単にいうと
https://qiita.com/list
というURLがあったとして、https://qiita.com/
の
/
以降のURLの画面を表しています。
上のURLの場合、
pages
┠ list
┃ ┗ index.vue # https://qiita.com/list のページです。
┗ index.vue # https://qiita.com/ のdomainの直下のページです。
というディレクトリ構造になり、ディレクトリ名がそのままURLになります。
index.vueというファイル場合にすると、htmlでよくあるindex.htmlと同じようにURL省略できます。
(https://qiita.com/list/index
としなくていい。https://qiita.com/list
と省略可)
他にも表現方法はありますが、ここでは割愛します。詳しくみたい方は公式の
ルーティングの基礎
を参照してください。
それでは実際にページを作っていきます。
まずpages
の下にlist
ディレクトリを作り、その下に、index.vueファイルをつくります。
まずはhello world
作ったindex.vueのファイルに以下を記述し画面を表示してみます。
<template>
<h1 class="red">Hello {{ name }}!</h1>
</template>
<style>
.red {
color: red;
}
</style>
<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
@Component({})
export default class List extends Vue {
data() {
return {
name: 'World'
}
}
}
</script>
Nuxtのサーバーを起動します。
$ yarn run dev
ブラウザでhttp://localhost:3000/list
アクセスしてみると、赤文字のHello Worldが表示できたかと思います。
vueファイルについてちょっと解説します。
vueファイルの作りについて
主にこの3つのディレクティブ(タグみたいなところ)からできています。
・template: HTMLを書くところ
・style: CSS書くところ
・script: 画面で使う変数の定義や、ボタンクリック時の処理、API呼び出してデータ取得するなど、いろいろな処理を書きます
vueファイルは画面が主なので、template
は必須ですが、CSSの記載が不要ならstyle
は不要ですし、変数やイベントを持たない静的なページについては、script
も不要です。
dataメソッドについて
dataメソッドの戻り値がそのままtemplateで呼び出せます。サンプルだと
returnで name
を返してると思いますが、templateでは{{ name }}
で変数の値を表示することができます。dataメソッドは同期呼び出しのみなので、apiから返却された値を使いたい場合は、非同期呼び出しになるのでasyncData
を使います。
APIの呼び出し
APIの呼び出しはasyncDataでaxios
を呼び出して利用します。公式だとimportでaxiosを呼び出してますが、すでにnuxtのcontextにaxiosがいるのでそれを利用します。
記事の一覧を呼び出し、returnでAPIのレスポンスを返します。
async asyncData(context) {
const res = await context.$axios.get(
'https://qiita.com/api/v2/items',
{
headers: {
Authorization: 'Bearer 準備で発行した自分のトークン'
}
}
)
return {
data: res.data
}
}
記事の一覧APIはArrayで返ってくるので、templateで一覧表示をしてみます。
templateはvue.jsの構文をそのまま使えるので
v-for
を使って記事一覧のタイトルを出してみます。ついでにstyleも少し整えます。
<template>
<ul class="list">
<li v-for="item in data" :key="item.id" class="listItem">
{{ item.title }}
</li>
</ul>
</template>
<style>
.list {
padding: 0;
}
.listItem {
list-style: none;
border-bottom: 1px solid #999;
padding: 1rem 16px;
box-sizing: border-box;
}
</style>
APIから取ってきた記事一覧のタイトルが画面に表示されるかと思います。
これで基本的なAPIの呼び出しから画面の表示までの流れができました。
いかがでしたでしょうか?
今回のサンプルはgithubに上げておきます。
次回の記事を書くとしたら、serverMiddlewares
の機能利用して、APIを作って、tokenを隠してみたり、ページングなどを実装してみたりとか書けたらと思います。