nuxtのmiddlewareをjavascriptとtypescriptそれぞれで扱うには?


目的

今回はnuxtでmiddlewareを扱うときにjavascriptの場合だとチュートリアルのやり方でできますが、typescriptの場合同じようにコードを書いてもうまく動作しませんでした。
そのため今回、typescriptでも扱えるように備忘録もかねてまとめました。


環境

OS: Windows10 home
エディタ: Visual Studio Code


ディレクトリ構成

project/
     ├ layouts/
     │      └ hello.vue
     │
     ├ middleware/
     │      └ middle_hello.ts
     │
     ├ pages/
     │      ├ sub/
     │      │   └ index.vue
     │      └ index.vue
     │
     └ nuxt.config.js

※今回扱っているファイルのみ表示しています。


middlewareの実行タイミング

今回実行したいmiddlewareのタイミングとしては以下の二つ
・特定のページに限らず、ページ遷移したときに実行する
・ある特定のページに遷移したときのみ実行する


特定のページに限らず、ページを遷移したときに処理する場合

javascriptで書いた場合


layout/hello.vue

<template>
  <div>
    hello
    <div>
      <nuxt />
    </div>
  </div>
</template>

<script>
</script>


middleware/middle_hello.js

export default function (context) {
  console.log('hello')
}


pages/index.vue

<template>
  <section>
    pages.index
    <nuxt-link to="/sub">
      go to sub
    </nuxt-link>
  </section>
</template>

<script>
export default {
}
</script>


pages/sub/index.vue

<template>
  <section>
    sub.index
    <nuxt-link to="/">
      go to page.index
    </nuxt-link>
  </section>
</template>

<script>
export default {
  layout: 'hello'
}
</script>


nuxt.config.js

export default {
  ・・・
   router: {
      middleware: 'middle_hello'
   }
}

上記のファイルを用意し、npm run devを実行するとターミナルとブラウザのコンソール上にhelloの文字が表示されるはずです。

typescriptで書いた場合
  • layout/hello.vue
  • pages/index.vue
  • nuxt.config.js

上の3つはjavascriptの場合と同じです


middleware/middle_hello.ts

import { Context } from '@nuxt/types'

export default (context: Context) => {
  console.log('hello')
}


pages/sub/index.vue

<template>
  <section>
    sub.index
    <nuxt-link to="/">
      go to page.index
    </nuxt-link>
  </section>
</template>

<script lang="ts">  // <= typescriptに対応させるために lang="ts を追加する
export default {
  layout: 'hello'
}
</script>

javascriptの場合と同様に、npm run devを実行するとターミナルとブラウザのコンソール上にhelloの文字が表示されるはずです。


特定のページに遷移したときだけmiddleware(middle_hello.ts)を処理する

javascriptで書く場合


layouts/hello.vue

<template>
  <div>
    hello
    <div>
      <nuxt />
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      view: 'javascript view'
    }
  },
  middleware: 'middle_hello',
  mounted () {
    console.log(this.view)
  }
}
</script>


middleware/middle_hello.js

export default function (context) {
  console.log('hello')
}


pages/index.vue

<template>
  <section>
    pages.index
    <nuxt-link to="/sub">
      go to sub.index
    </nuxt-link>
  </section>
</template>

<script>
</script>


pages/sub/index.vue

<template>
  <section>
    sub.index
    <nuxt-link to="/">
      go to page.index
    </nuxt-link>
  </section>
</template>

<script>
export default {
  layout: 'hello'
}
</script>

上記の場合、pages/index.vueの画面からpages/sub/index.vueのページに遷移したときだけブラウザのコンソール上にhelloの文字が表示されます。
また、同時にlayouts/hello.vueの内で用意した console.logの文字('javascript view' の文字)が表示されるはずです。

typescriptで書く場合

pages/index.vueはjavascriptの場合と同じです。
layout/hello.vueもjavascriptの場合とほぼ同じですが少しだけ追加する部分があります。


layout/hello.vue

<template>
  <div>
    hello
    <div>
      <nuxt />
    </div>
  </div>
</template>

<script lang="ts">
import '../middleware/middle_hello'  // ①
import Vue from 'vue'

export default Vue.extend({
  data () {
    return {
      view: 'typescript view'
    }
  },
  middleware: 'middle_hello',  // ①を追加しないと'No overload matches this call ~~'と表示される※但し、実行時はちゃんと希望通りの処理をしてくれます。
  mounted () {
    console.log(this.view)
  }
})
</script>

※ちなみに上記のコードはVueをextendしない場合、'No overload matches this call ~~'の文句は言われなくなります。
しかし今度はmounted内のconsole.log(this.view)の部分で 'Property 'view' does not exist on type ~~' と怒られてしまいます。


middleware/middle_hello.ts

import { Context } from '@nuxt/types'

export default (context: Context) => {
  console.log('hello')
}


pages/sub/index.vue

<template>
  <section>
    sub.index
    <nuxt-link to="/">go to pages.index</nuxt-link>
  </section>
</template>

<script lang="ts">

export default {
  layout: 'hello'
}
</script>

あとはnpm run devで実行したあとにpages/index.vueページからpages/sub/index.vueのページに遷移したときmiddle_hello.tsの処理が実行され、
'hello'が表示されると同時にlayouts/hello.vueのmounted内に用意したconsole.logの 'typescript view' も表示されます。


まとめ

今回はnuxtのmiddlewareをjavascriptとtypescriptそれぞれで扱ってみました。
わたしがまとめた内容はもしかしたら冗長な部分がありミスがあるかもしれません。その際できる限り修正し、更新していきます。
またより良い方法が見つかり次第、この記事を更新または新たな記事で紹介しようと思います。
この記事を読んでいただきありがとうございます。