はじめに
Ruby + JekyllによるGihubPagesは既にある のですが、宮崎版コロナ対策サイトで Vue に触れ、勉強がてら実際に JS によるサイト作成をすることにしました。
自分
大学研究で cpp を利用しただけの、農学部卒。
作成に当たって
React と Next.js の tutorial と docs を一通りやりました。
サイト自体の目的
- 経歴や作成したもののリンクをまとめる
- GithubPages や Qiita、Gist への投稿物を一か所にまとめる
- Markdonw によるページ作成
リンク
技術・要件など
- React.js, Next.js
- マークダウン変換
- シンタックスハイライト
- UI コンポーネント
- ダークテーマ
環境
- vm:virtualbox + vagrant
- node -v :v12.16.1
- yarn -v :1.22.4
実作業
yarn create next-app
Example from the Next.js repo
- amp, amp-story, amp-first
- google analytics 類
- with-google-analytics, with-google-analytics-amp
- aws 類
- with-aws-Amplify, with-aws-Amplify-typescript
- その他: api 類, Custom server 類, preact および多数
- 参照:Github: vercel/next.js/example
Default starter appの場合
今回は React Next.js の勉強も兼ねているので、default の方を利用した。
Material-UI 導入
見た目重視で material-ui を導入し、主にサイドバーの permanent / swipeable drawer と Grid に使用。
create src/pages/index.jsx
src
ディレクトリを作成し、下に pages
を収める
src/components/Layout.jsx
の作成
複数ページで共通デザインとなる Layout.jsx
を作成する。ここでは省略したが、<aside />
の中には、material-ui
を利用した permanent-drawer とモバイル用の swipeable-drawer を実装した。
まだ React 等に不慣れなので、pages/index.js
にサイト 1 ページ目を作りこんで、後から component に分割する方式をとった。
色々試した結果、サイトトップにあたる pages/index.jsx
は下の様になった。また、<head><meta/></head>
用のデータは /public/manifest.json
から持ってくることにした。
_app.jsx,_document.jsx, 404.jsx
参照
Posts周辺の作成
ダイナミックルーティング
ディレクトリ構成
また、/pages/posts/[id].jsx
は
ファイル名に []
が付いてるので変に見えるが。例えば
localhost:3000/posts/hoge/
にアクセスすると pages/posts/hoge.jsx
が読み込まれる
localhost:3000/posts/foobar
だと、pages/posts/foobar.jsx
が読み込まれ、
dynamic route
と Link (next/link)
を併用するときは、href
に合わせて as
も使う。
getStaticProps, getStaticPaths
今回は md ファイルを /src/pages/docs
に入れる。
baseUrl/posts
へのアクセス時は、docs 下の md ファイルを読込み、posts 一覧の出力
baseUrl/posts/[id]
の場合は、同様にして、post 単体の出力
baseUrl/tags
の場合は、同様に posts で使用されている投稿タグ一覧の出力
baseUrl/tags/[tag]
なら、同タグを使用する posts 一覧を出力
- docs 配下に無い md ファイル名にアクセスした場合は、
404
ページ出力が src/pages/docs/xxx.md
という外部データに依存した静的ページ出力をしたいので、getStaticProps
と getStaticPaths
を使用した。
マークダウン
- 実現したいこと
- Qiita や Gist 等での投稿を可能な限り手間なく集約したい
mdxjs/mdx
なら、ファイル中に import
や export
などの js を組み込める
- 最終的に利用したもの
構文木について、しっかり学ばねばと思いました。
以前にrubyとjekyllで作ったgithubpagesと比較して、syntax-highlight が粗いので改善が必要
SNSシェアボタン
UPDATE
README.md
@ 2020-05-27
Qiita 投稿の公開に当たり、README.md
を充実させた
npm install 禁止
@ 2020-05-27
特に理由はないが npm
の仕様を禁じることにした。
Custom Domain
@ 2020-06-01
- google domain で購入
- Vercel 側でドメインを変更
- Google Domain 側で dns を vercel 用に変更
- ns1.vercel-dns.com
- ns2.vercel-dns.com
Google Analytics
@ 2020-06-05
GoogleAnalytics 側で ID を取得し、_app.jsx
と _document.jsx
を上コードに従って修正する。
PWA implimentation
next-offline
@ 2020-06-05
next-offline
を利用した。上リポジトリでも記載してあるが、Vercel( Now )の v1 と v2 で動作が違う。ただし、現在は v2 オンリーなので、同リポジトリ内にある packages/now2-example の now.json
と next.config.json
に倣えばよい。
PWA
@2020-06-25
最初に使った next-offline
は更新が遅く、また experimental な部分を利用していたなどの理由から、next-pwa
に移行した。example からわかるように、非常にシンプルになった。
TypeScirpt
@2020-06-30
Next.js の TS 化は非常に簡単で、最初のうちは Next.js Learn Typescipt などに従えば良い。
あとは、Learn 等に従って、ts 化していけば、何となく理解できる。また、tsconfig.json
で allowJs:true
にしておけば、もし仮に型がわからんものを含む js ファイルはそのままにしておいて、理解が進んでから完全に ts 化すればいいのでは。
npm-script
mizchi氏のブログ などを見ていて、npm-script や EsModule などを知った。ちょうど、sitemap.mxl
を造る必要があったので、利用することにした。
vercel は nodejs の LTS しか対応しないので、package.json 中の npm-script は build 用 と generate script用で分ける必要があった。
mjs について未だ良くわからんこと、作るのが自分用のファイルジェネレーターであることもあって、コードが汚いので…↓
pages.json
@2020-06-30
post の情報を集約した postPages.json を作成した。ファイル更新履歴等はそのうち GitHub から取得できるようにしたい。
- JSON.stringify が良くわからなかったので、読んだもの
作りたいファイル構成
postsMap generator script
sitemap.xml
@2020-07-01
サイトマップジェネレータライブラリは上記の通りあるが、xml の構造は簡単そうだったので自作した。
sitemap.xml の基本構成
xmlはファイル頭に空白行が入ると、<?xml ?>
の宣言が無いと言ってエラーを吐く
@2020-07-01
RSS 2.0 と Atom 1.0 に対応する。
RSS 2.0 フォーマット
Atom 1.0 フォーマット
RSS と Atom のジェネレーターコードは、基本的に sitemap.xml と同じなので。
RSS 2.0 ジェネレータ
Atom 1.0 ジェネレーター
Algolia search
投稿記事の検索に Algolia を利用した。postsMap.json
をデータとして投入した。
現在のデータ投入は手動で行なっているが、あとで postsMap.json
生成時に差分があれば api
で投入できるようにしたい。
To do
- CSS の統一
- AMP 対応
- コードブロックの言語またはファイル名の出力
- syntax-highlight の改善
- post ページの目次機能
- og:image 動的生成コード