GatsbyからNuxtJSに移行してみた
flutter-study.dev
「Flutterで始めるアプリ開発」というWebサイトを公開している。
もともとはGatsbyでSSGしていたが、Vueを使う必要が出てきたので、勉強がてらNuxtJSへと移行してみた。
Markdownで記事を書く
Gatsbyの時は@rocketseat/gatsby-theme-docs
を使っていて、Markdownで各記事を書いていた。
NuxtJSでもMarkdownで書いた記事はそのまま再利用したいので、@nuxt/content
を使うことにした。
@nuxt/content
インストール
導入は簡単でパッケージをインストールしてnuxt.config.js
でモジュールを追加すればOK。
{
modules: [
// ...
'@nuxt/content'
],
}
Markdown
Markdownファイルはcontent
ディレクトリ内に適宜配置していく。
配置したディレクトリ・ファイル名がそのままURLとなり、Gatsbyの時と同じなのでURLを変換する必要はなかった。
各記事のタイトルや説明など、メタ情報的なものはYAMLで先頭に記述できる。
Gatsbyの時も同じ要領で書かれていたので再利用できた。
---
title: Introduction
description: Learn how to use @nuxt/content.
---
記事の順番
Gatsbyの時は、サイドバーに記事の一覧を表示していて、その情報を元に前後の記事を判定していた。
@nuxt/content
では各記事にメタ情報的なものを記述しておくことで、記事の順番を管理することが出来る。
具体的には、次のようにslug
という情報をpage-01,page-02,...
といった連番で各記事に記述すると、その順番で記事を取得することが出来る。
---
title: Introduction
description: Learn how to use @nuxt/content.
slug: page-01
---
const pages = await this.$content('pages').sortBy('slug').fetch()
また、前後の記事を簡単に取得することも出来る。
各記事のslug
がpage-01,page-02,page-03
と記述してあれば、page-02
から前後のpage-01
とpage03
の記事が取得できる。
const [prev, next] = await this.$content('pages').surround('page-02').fetch()
Static Site Generation
nuxt generate
全て静的ファイルとしてFirebase Hostingにアップロードしている。
NuxtJSでSSGするのは非常に簡単で、nuxt.config.js
でtarget: true
と設定し、nuxt generate
コマンドを実行するだけで良い。
Composition API
しかし、Composition APIを使いつつSSGする時に地味に困った点がある。
もしかしたら解決方法があるのかもしれないが、useFetch()
を使っている箇所がNuxtLink
でページ遷移した際にpayload
がうまく読み込まれなかった。
export default defineComponent({
setup () {
const context = useContext()
const route = useRoute()
const doc = ref<IContentDocument>()
useFetch(async () => {
const $content = context.content
const { page } = route.value.params
doc.value = await $content(page).fetch()
})
return { doc }
}
})
</script>
しかたなく、Composition APIを使うのをやめて、asyncData
で各記事のデータ取得処理を記述することとした。
export default Vue.extend({
async asyncData ({ $content, params }): Promise<Data> {
const { page } = params
const doc = await $content(page).fetch()
return { doc }
}
})
そもそも、NuxtLink
を使わずにa
タグを使えば良いところではあるが、@nuxt/content
の内部処理的に、相対パスであればNuxtLink
に変換する仕様となっていた。
なので、@nuxt/content
自体の実装を変更するのは手間だったので、ひとまずComposition API
を使わない方向に。。。
/**
* Replace a tag with nuxt-link if relative
*/
if (node.tagName === 'a' && (node.properties.href || '').startsWith('/')) {
node.tagName = 'nuxt-link'
node.properties.to = node.properties.href
delete node.properties.href
}
TypeScript
create-nuxt-app
を使ってNuxtJSプロジェクトを作成する時に、TypeScriptを選択できるので簡単にTypeScriptで書き始めることが出来る。
しかし、NuxtというかVue側の問題であるが、TypeScriptとの相性があまりよろしくない印象をうける。
テンプレート部分は一切型定義の恩恵が受けられないのはもちろんだが、NuxtJSのasyncData
で返す値の型は明示的に記述しないと認識されなかったりする。
最後に
NuxtJSは簡単に使うことができ、ドキュメントも充実している。
また、NuxtJS用のモジュールが充実していて、多くのケースで爆速でアウトプットできる環境が整っている。
いわゆるWebサイトであったり、個人で作る小規模なWebアプリであれば、簡単かつ爆速で作れるNuxtJSが良さそうな感じがする。
また、TypeScriptとの相性が悪い点はNuxtJS/Vueの辛いところである。
TypeScriptとの相性が悪いということは、エディタ上でもソースコードを追いにくいということになる場合が多いことになると思う。
なので、業務としてWebアプリを作る場合は個人的には避けたほうが良さそうな印象ではある。
次は、Next.jsでも使ってみる。
FlexboxとGrid Layoutを使ったCSSレイアウト入門
FlexboxとGrid Layoutを使ったCSSレイアウトに関して書籍にまとめました。
作って学ぶWebサイト制作
Webサイト制作の入門サイトを作っています。
Discussion