概要

Next化でコンポーネントをSSRとCSRで出しわけることができることになったので、SSRする必要のないコンポーネントが表示されるまで高さと幅を持ったスケルトンコンポーネントを表示することで、UIがカクつくのを防止する。

イメージ

スケルトンFB後.PNG

どんなコンポーネントにスケルトンを実装するか

真っ先に表示されてほしいものはSSRするのでスケルトンは必要ない

  • ページの本文とか
  • 上のイメージの例ではページパスはSSRしている

別に早く表示する必要のないものはSSRしないのでスケルトンがあるとよい

  • 上のイメージの例ではいいねボタンとか、タグの情報とか
  • 基本こっちが多めになるのか?

スケルトンの実装方法

const TagLabels = dynamic(() => import('../Page/TagLabels'), { ssr: false, loading: () => <Skelton additionalClass={`${TagLabelsStyles['grw-tag-labels-skelton']} py-1`} />, });

dynamic importにおいてNext.jsのssr: falseオプションとloading: を使うことでレンダリング中にコンポーネントを表示させることができるのでこれを活用する。

スケルトンの実装におけるルール

高さのハードコーディングはしない

.grw-page-editor-mode-manager-skelton :global { width: 213px; height: calc($btn-line-height + bs.$btn-padding-y*2 + bs.$btn-border-width*2); // こっちが理想 height: 35.99px; // これはダメ }

本物のコンポーネントの高さを変数に切り出したり、bootstrapのpaddingの値を活用したりして高さを計算して設定する。 でも本当にどうしようもない時は仕方がないかもしれない...

幅に関してはUIがカクつく原因にはあまりならないので、程よい値を設定する。

スケルトンと本物のコンポーネントのスタイルは同じファイルにあったほうがわかりやすい

PageEditorModeManager.module.scss
@use '~/styles/bootstrap/init' as bs; @use '~/styles/mixins'; $btn-line-height: 1.2rem; .grw-page-editor-mode-manager :global { .btn { width: 70px; white-space: nowrap; @include mixins.border-vertical('before', 70%, 1, true); &.view-button, &.edit-button { line-height: $btn-line-height; .grw-page-editor-mode-manager-icon { @include bs.media-breakpoint-down(sm) { font-size: 1.2rem; } } } &.hackmd-button { line-height: $btn-line-height; .grw-page-editor-mode-manager-icon { @include bs.media-breakpoint-down(sm) { font-size: 1.2rem; } } .grw-page-editor-mode-manager-label { font-size: 12px; letter-spacing: -0.6px; } } } } .grw-page-editor-mode-manager-skelton :global { width: 213px; height: calc($btn-line-height + bs.$btn-padding-y*2 + bs.$btn-border-width*2); }

cssファイルのモジュール化などを活用して、同一ファイルにまとめた方がわかりやすい。

参考PR