Skip to content

Commit

Permalink
feat: content/2.concepts/5.middleware (#48)
Browse files Browse the repository at this point in the history
* wip

* feat: content/2.concepts/5.middleware
  • Loading branch information
ubugeeei authored Jul 3, 2024
1 parent a7370c3 commit b8fc224
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 1 deletion.
3 changes: 3 additions & 0 deletions content/2.concepts/5.middleware/.template/files/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<NuxtPage />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default defineNuxtRouteMiddleware(() => {
console.log('Hello from global middleware!')
})
12 changes: 12 additions & 0 deletions content/2.concepts/5.middleware/.template/files/pages/foo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script setup lang="ts">
definePageMeta({
middleware: ['hello-foo'],
})
</script>

<template>
<h1>Foo</h1>
<NuxtLink to="/">
/Index
</NuxtLink>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<h1>Index</h1>
<NuxtLink to="/foo">
/Foo
</NuxtLink>
</template>
8 changes: 8 additions & 0 deletions content/2.concepts/5.middleware/.template/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { GuideMeta } from '~/types/guides'

export const meta: GuideMeta = {
startingFile: 'pages/index.vue',
features: {
fileTree: true,
},
}
3 changes: 3 additions & 0 deletions content/2.concepts/5.middleware/.template/solutions/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<NuxtPage />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default defineNuxtRouteMiddleware((to) => {
// FIXME: import . meta . server が置換されてしまう
if (import.meta.server)
return

const isSignedIn = JSON.parse(localStorage.getItem('isSignedIn') || 'false')

if (!isSignedIn && to.path !== '/') {
return navigateTo('/')
}
else {
return true
}
})
12 changes: 12 additions & 0 deletions content/2.concepts/5.middleware/.template/solutions/pages/foo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script setup lang="ts">
definePageMeta({
middleware: ['hello-foo'],
})
</script>

<template>
<h1>Foo</h1>
<NuxtLink to="/">
/Index
</NuxtLink>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts" setup>
function setIsSignedIn() {
window.localStorage.setItem('isSignedIn', JSON.stringify(true))
}

function removeIsSignedIn() {
window.localStorage.removeItem('isSignedIn')
}
</script>

<template>
<h1>Index</h1>
<NuxtLink to="/foo">
/Foo
</NuxtLink>

<div>
<button type="button" @click="setIsSignedIn">
Set isSignedIn
</button>

<button type="button" @click="removeIsSignedIn">
Remove isSignedIn
</button>
</div>
</template>
78 changes: 77 additions & 1 deletion content/2.concepts/5.middleware/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,80 @@
ogImage: true
---

# Middleware
# ミドルウェア

Nuxt では、特定のルートにナビゲートする前にコードを実行する為のミドルウェアを提供しています。\
この機能は例えば、認証状態によってページへのアクセスを制限する場合などに便利です。

ミドルウェアにはグローバルミドルウェアとページ単位のミドルウェアの2つの種類があります。
どちらも、`middleware` ディレクトリに実装します。

## グローバルミドルウェア

グローバルミドルウェアは以下のように定義することができます。

```
middleware/
--| hello.global.ts
```

```ts
// middleware/hello.global.ts
export default defineNuxtRouteMiddleware(() => {
console.log('hello')
})
```

## ページ単位のミドルウェア

ページ単位のミドルウェアは以下のように定義することができます。

```
middleware/
--| helloA.ts
```

```ts
// middleware/hello.ts
export default defineNuxtRouteMiddleware(() => {
console.log('helloA')
})
```

```vue
<!-- pages/a.vue -->
<script setup lang="ts">
definePageMeta({
middleware: ['hello'],
})
</script>

<template>
<h1>Hello A</h1>
</template>
```

## ミドルウェアの実行タイミング

これらのミドルウェアは、クライアント上でのナビゲーション時はもちろん、SSR または SSG でのページ生成時にもサーバーサイドで実行されます。\
ミドルウェアでローカルストレージなどのクライアントサイドの API を使用する場合は、クライアントサイドのみで実行されるようにする必要があります。\
`import.meta` を使うことで実行している環境を判定することができます。サーバーサイドでの実行スキップする場合は `import.meta.server` を利用します。

```ts
export default defineNuxtRouteMiddleware((to) => {
// skip middleware on server
if (import.meta.server)
return

// some processing
window.localStorage.setItem('key', 'value')
})
```

## チャレンジ

localStorage の情報を読み取って、特定の値がある場合のみ `/foo` にアクセス可能にするミドルウェアを作成してみましょう。\
今回は例として、`isSignedIn` というキーに `true` が設定されている場合のみ `/foo` にアクセス可能にするミドルウェアを作成します。\
値のセットは `index.vue` から行えるようにボタンを設置してみましょう。

:ButtonShowSolution{.bg-faded.px4.py2.rounded.border.border-base.hover:bg-active.hover:text-primary.hover:border-primary:50}

0 comments on commit b8fc224

Please sign in to comment.