Nuxt.jsでClient側でしか使えないコンポーネントを使う
March 26, 2021
Nuxt.jsを勉強中です。
ざっくりvue-grid-layoutを使おうとしたら document is not defined
とエラーになりました。
色々試してみて結局動いてないですが、備忘録的にメモしておきます。
エラーになったコード
props省略していますが、エラーになるコードは以下のような感じでした。
<template>
<grid-layout
...
>
<grid-item
v-for="item in layout"
...
>
{{ item.i }}
</grid-item>
</grid-layout>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
import { GridLayout, GridItem } from 'vue-grid-layout'
export default defineComponent({
components: {
GridLayout,
GridItem,
},
// ...
})
</script>
対策
SSRの際には(window.)documentを参照できないので、クライアント側でのみレンダリングされるように設定する必要があります。
ドキュメントはこちら
具体的に行ったことは以下です。
- pluginを利用して、
GridLayout
,GridItem
をグローバルコンポーネントで使えるようにする nuxt.config.js
でpluginを指定する<client-only />
タグを使う
pluginを利用して、GridLayout
,GridItem
をグローバルコンポーネントで使えるようにする
plugins
ディレクトリにファイルを作成します。(ここではclient-only-components.ts
としました)
import Vue from 'vue';
import { GridLayout, GridItem } from 'vue-grid-layout';
Vue.component('grid-layout', GridLayout);
Vue.component('grid-item', GridItem);
nuxt.config.js
でpluginを指定する
↑で作成したpluginファイルを読み込むために、configファイル内に記述します。
このときに mode: 'client'
を指定します。
(ssr: false
でも動きますが、次のメジャーバージョンで非推奨になるようです)
{
...
plugins: [
...
{ src: '~/plugins/client-only-components.ts', mode: 'client' },
],
...
}
<client-only />
タグを使う
最終的に修正してこんな感じになりました。
<template>
<client-only placeholder="Loading...">
<grid-layout
...
>
<grid-item
v-for="item in layout"
...
>
{{ item.i }}
</grid-item>
</grid-layout>
</client-only>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
export default defineComponent({
// ...
})
</script>
ここまでで document is not defined
は出なくなり、コンポーネントが表示されるようになりました。
ただ、次は Unknown custom element: <grid-layout>
というようなエラーが出てしまい、pluginsで登録したコンポーネントが認識されないため、今度はこのあたりを調べてメモを更新したいと思います。
うまくいかなったからVue.draggableを使うようにしようかな。。