概要
ポートフォリオサイト作って、いろいろと学んでみました。
備忘録もかねて残していきます。誰か参考になればと思います。
最終アウトプット
やりたかったこと
- Jamstackでサイト作りたい
- Adobe XD使いたい
- Reactやりたい(Vueとの違いを体験したい)
- Typescriptやりたい(通常のJSとの違いを体験したい)
対象者
- Jamstackなサイトを作りたいけどはじめて
- フロントはある程度できる
- マークアップはある程度できる(CSS FWは使わずに実装できる)
- React/Vue/Angularなどのモダンフロントを経験したことがある
- Gitできる
自分のレベル感
- Web系のSI会社勤務(2020.08現在)
- デザイン・ワイヤー・モックも作ったことない
- Adobe XDで作られたモックからからマークアップはやったことある
- フロントはちょっとだけできる
- HTML/CSS, JS, Vue
- Reactはやったことない
- バックエンドはまぁできる
- Rails, Node.jsなど
- GraphQLはAppSync経由で使ったことあるので今回の学習コストはなし
- 一人で一からサービスをリリースみたいなのは経験ない
- プロジェクトではあるが、全部に関わっているわけではないので
作業の流れ
ワイヤーの作成
- はじめからXDみたいなデザインツール、あるいはマークアップをやろうとすると逆に時間がかかると思います.デザインは飛ばすとしてもサクッとワイヤーは作っておきましょう.
- いろいろなポートフォリオサイトを参考に作りました
- 手書きでざっくり書く
- レスポンシブに作る場合はスマホのワイヤーも作る
- コンポーネント設計はこの段階で軽くやっておく
- 以下は実際に作成したものの一部です(それぞれOverviewページのPCとスマホ)
モックの作成
- Adobe XDで作成する
- 他に実際の業務でよく使われているのはFigmaのイメージです.現職はモックがあるときはXDがほぼ100%(イラレはつらみ)だったのでXDを採用しました
- 事前にAdobeにあるチュートリアルをSTEP2までやりました
- こちらはAdobeXDのバージョンが古すぎてあまり参考になりませんでした。
- [ちづみさんのサイト](https://zukulog098r.com/xd-design/)が参考になりましたXDのチュートリアルやってるけど、クソすぎてやばい。
— n_koyama (@naoto324) July 28, 2020
動画で進んでくんだけど
・完成イメージを見てみましょうとあるのに、完成イメージをDLするリンクがない
・アセットを作りましょうとあるけど、アセットがない(今はコンポーネントらしい)
クロームの拡張Window Resizer で予定のカンプの幅にブラウザを変更
↓
クロームの拡張Full Page Screen Captureでスクショ
↓
XDの拡張Mimicにurlをコピペ
↓
スクショを複製し1枚はトレース用に薄くひく
↓
サイトの検証も見ながら数値等を確かめつつ模写
- ある程度デザインの決め事をやっておく
- これもちづみさんのサイトが参考になりました
- marginは4の倍数
- font-sizeは12, 14, 16, 20, 34を基本にする(その他は以下参考)
- https://material.io/design/typography/the-type-system.html#type-scale
- 入力欄は14px以下にしない(スマホでズーム問題が発生する)
- ナビの高さは50pxから100px
- コンテンツ幅は900pxから1180px
フロントでどんな技術を使うか考察
- フロントでやりたいことは以下
- GraphQL
- React
- Typescript
- Jamstack
- 無料枠内に収まる
- 結果採用したのは以下のとおり
- ヘッドレスCMS: microCMS(似たサービスはstrapiとかContentfulなど)
- FW: Gasby.js(似たFWはNext.jsなど)
- ホスティング: Netlify(似たサービスはGithub Pagesなど)
- ReactでJamstackで調べると、Next.js + Netlifyがでてきたのですが、
GraphQLが対応していないらしく、Gatsby.jsを使うことにします。GatsbyもGithubのスターの数あんまり変わらないくらいで結構有名みたいです。- Next.jsとGatsby.jsの違いはこちらが参考になりました。
フロントの実装
microCMSの設定
- microCMSは(実際は違うけど)データベース + APIみたいなイメージ
- [アカウント登録](https://microcms.io/) - サービス情報を入力.今回はプロフィールサイトを作りたいので以下で登録しました - サービス名: [名前]のプロフィール - サービスID: profile-koyama.microcms.io - APIを追加 - 以下の部分を取得するAPIを作って見ます ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/dafb6aa1-7401-2881-3365-2c5d08716fe3.png) - データの定義とAPIのエンドポイントを同時に登録します.今回の例では名前や年齢などのことです - API名とエンドポイントを入力して次へ ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/81272b07-429e-3f21-ece0-f1c6c18984be.png) - APIの型は単一データなので、オブジェクト形式を選択 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/aeb37824-cfce-2988-20fa-e6ea6264d86c.png) - APIスキーマ(テーブル定義的なもの)を作成します.ユーザ情報に必要なものを登録していきます - 型は普通のテキストや数値からDBだけだと難しい画像などまでいけます - 関係はないですが、ageはアンチパターンですね。例えば生年月日のようにコトを設定する方がよいです ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/c9add60e-8261-c6d1-c50d-acbdbec59a38.png) - データを登録 - サイドバーから作成したAPI(ユーザ情報)を選択 - コンテンツ管理というタブが選択されているので、そこにデータを登録 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/cc88361b-a842-b9ed-f4bc-03adda1240d8.png) - APIプレビューを選択 > 取得を選択でレスポンスを確認(以下のようにAPI叩いたらJSONで返ってきます) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/8fc09e0f-9c69-87f3-2e50-3633b92e9aae.png) - 以下のHOBBYのような複数の項目を登録したい場合はAPIの型をリスト形式で作ればOKです ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/da6f3e19-ad44-0d73-1c2f-7a607da1353b.png) - 作ったイメージが以下です ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/36a9ca96-3c6a-dfd2-0bb4-455ce892a645.png) - JSON配列で取得することができます ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/18cb0e88-b386-e942-25d0-d02278f6d3d9.png) - api名/:idで単一で取得することもできます(REST的な考え方) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/ceb47837-47ac-6362-0f8a-6713e0b63533.png) - Favoriteは趣味に固定値として持ってもよいですが、複数コンテンツ参照を使うことで趣味の下にぶら下げることができます(完結にするために今回最終的には固定値で持つようにしました)microCMS触ってるけどなんやこれ。。。
— n_koyama (@naoto324) August 8, 2020
めちゃくちゃ便利やん。
DB + APIみたいなイメージだけどバックエンドが隠蔽されていてちょっとめんどくさい画像も簡単に登録できるし、ええやん
Gatsbyで構築
- GatsbyとはReactベースのSSG(Static Site Generator: 静的サイトジェネレータ)のこと.一言でいうと爆速なサイトが簡単に作れるようになる
プロジェクトの作成
- Gatsbyをインストールして、プロジェクトの作成
- 途中でパッケージマネージャを聞かれますが、Yarnを選択しました.
$ npm install -g gatsby-cli
$ gatsby new my-profile https://github.com/gatsbyjs/gatsby-starter-default
(省略)
✔ Which package manager would you like to use ?
yarn
(省略)
Your new Gatsby site has been successfully bootstrapped. Start developing it by running:
cd my-profile
gatsby develop
- とりあえずプロジェクトの作成が成功したか見るために上記のコマンドを実行し、画面を見ておきます
$ cd my-profile
$ gatsby develop # yarn developでもOK
(省略)
success Building development bundle - 11.356s
# http://localhost:8000/ に接続します
- 今後のためにGitHubにpushしておきましょう
- GitHubのリポジトリを追加してpush
$ git remote add origin https://github.com/naoto-koyama/my-profile.git
$ git push -u origin master
フォルダ構成
.
├── LICENSE
├── README.md
├── gatsby-browser.js # ブラウザサイドの設定.共通CSSの設定など
├── gatsby-config.js # インストールしたプラグインの設定、サイトのメタデータやタイトル等の設定など
├── gatsby-node.js # 動的なページを作成する際に設定.$ gatsby buildを実行したときに走る処理
├── gatsby-ssr.js # SSR関連の処理を設定
├── node_modules
├── package.json
├── public
| ├── icons
| ├── page-data
| └── static
├── src
| ├── components # コンポーネントの設定
| ├── images # 画像ファイルを置いておく
| └── pages # 各ページを設定.URLとファイル名が一致する
└── yarn.lock
microCMSとの連携
- プラグインの追加
$ yarn add gatsby-source-microcms
- gatsby-config.jsの設定の修正
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
--- (中略) ---
{
resolve: "gatsby-source-microcms",
options: {
apiKey: "********-****-****-****-********e8b9", // microCMSのX-API-KEY
serviceId: "profile-koyama", // はじめに設定したserviceId
endpoint: "skills", // APIのエンドポイント
},
},
{
resolve: "gatsby-source-microcms",
options: {
apiKey: "********-****-****-****-********e8b9",
serviceId: "profile-koyama",
endpoint: "userinfo",
format: 'object', // オブジェクト形式の場合必要
},
},
--- (中略) ---
],
}
$ gatsby develop
# http://localhost:8000/___graphqlに接続
-
API KeyがGitリポジトリ上で確認できるのはまずいので、環境変数として持っておきます.ローカルとNetlify両方いずれも対応させるにはプレフィックスに
GATSBY_
をつける必要があるようです
GATSBY_MICRO_CMS_API_KEY=********-****-****-****-********e8b9
require("dotenv").config() // 追加
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
--- (中略) ---
{
resolve: "gatsby-source-microcms",
options: {
apiKey: process.env.GATSBY_MICRO_CMS_API_KEY, // 環境変数に書き換え
serviceId: "profile-koyama",
endpoint: "skills",
readAll: true, // デフォルトでは最大10件
},
},
--- (中略) ---
],
}
Scoped CSSの導入
- Vue.jsではデフォルトで入っているSCSSとScoped CSSを導入します
- 以下でSCSSが使えるようになります
$ yarn add node-sass gatsby-plugin-sass
module.exports = {
--- (中略) ---
plugins: [
`gatsby-plugin-sass`, // 追加
--- (中略) ---
- 試しにindex.jsでのみに適用するSCSSを作成します.ページ名に合わせてindex.module.scssとします
.hoge {
color: green;
}
- index.jsで読み込みます
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"
import styles from "./index.module.scss" // 追加
const IndexPage = () => (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
{/* classNameを追加 */}
<p className={styles.txt}>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link> <br />
<Link to="/using-typescript/">Go to "Using TypeScript"</Link>
</Layout>
)
export default IndexPage
-
Reset.cssのようなものをimportする際にMixinするファイルも存在する場合にはGatsbyでSCSSをMixinする方法を参考にしてください
TypeScriptの導入
- 事前にReactとTypeScriptをいろんなサイトで勉強しました(2hぐらい)ので、Gatsbyに導入していきます
- 以前はgatsby-plugin-typescriptをプラグインに導入する必要がありましたが、GatsbyのTypeScriptサポートがデフォルトになったようで、必要なくなりました
- GraphQLのQuery型を自動で精製してくれるgatsby-plugin-graphql-codegenの導入
- かなりつまったのが、Gatsbyの仕様でGraphQLで取得したデータはdataという引数で取得されるのですが、それがわかっておらずdataという引数をなぜpagesが持っているのだろうと思っていました
module.exports = {
--- (中略) ---
plugins: [
--- (中略) ---
{
resolve: 'gatsby-plugin-graphql-codegen',
options: {
fileName: 'types/graphql-types.d.ts',
},
},
--- (中略) ---
- typescript用でScoped Styleを定義しようとすると、以下のエラー表示されます
import * as React from 'react'
import { Link } from 'gatsby'
// Cannot find module './header.module.scss' or its corresponding type declarations. という警告がLintから表示される
import * as styles from './header.module.scss'
- そこでtsっぽさはなくなりますが、Lintの設定を変更しrequireで取り込むようにします
--- (中略) ---
"rules": {
"react/prop-types": "off",
"no-var-requires": 0,
"@typescript-eslint/no-var-requires": 0
},
--- (中略) ---
import * as React from 'react'
import { Link } from 'gatsby'
const styles = require('./header.module.scss')
- pagesとcomponentsをTSXに書き換える、LintとPrettierの設定追加
- こちらのコミットログ参照
各ページの作成
- 上記の設定でやっと開発できるようになったので、各ページをモックを元に開発していきます
- 私はその前にNetlifyにデプロイ
- 以下が作っていてつまっていたところです.主にGatsby側の仕様になります
MicroCMSで空白で登録すると、取得できない
- gatsby-source-microcmsプラグインを使っているのですが、なぜか空白がある項目に関しては
types/graphql-types.d.ts
へ出力されませんでした - いろいろ調べたのですが、どうしようもなかったので、空白がある場合は別テーブルにするということで対応しました
- 他の解決策(とりあえずダミー項目を入れておく以外)を知っていたら教えていただきたいです
window.addEventListenerがBuildでエラー
- Localで
gatsby develop
したときにはエラーにならないのですが、Netlifyでbuildするとエラーになりました。
10:12:05 PM: failed Building static HTML for pages - 4.129s
10:12:05 PM: error "window" is not available during server side rendering.
10:12:05 PM:
10:12:05 PM: 14 |
10:12:05 PM: 15 | if (title === 'OVERVIEW') {
10:12:05 PM: > 16 | window.addEventListener('scroll', (): void => {
10:12:05 PM: | ^
10:12:05 PM: 17 | setIsTopScroll(window.scrollY === 0)
10:12:05 PM: 18 | })
10:12:05 PM: 19 | }
10:12:05 PM:
10:12:05 PM: WebpackError: ReferenceError: window is not defined
- これはBuild時にSSGしており、windowオブジェクトなんかないよって行っているだと思います
- 解決策としてはSSRのときに使いたいので、if文に`window !== 'undefined'を追加して対応しました
if (title === 'OVERVIEW' && typeof window !== 'undefined') {
window.addEventListener('scroll', (): void => {
setIsTopScroll(window.scrollY === 0)
})
}
Netlifyにデプロイ
- デプロイする前にローカルで確認してみます.以下の手順で問題なく画面が表示されることを確認してください(console側も)
$ yarn build
# public配下へ静的ファイルが出力される
$ yarn serve
# http://localhost:9000/ へ接続
- 問題なければNetlifyの登録を実施します
- 登録完了後、MyPageからNew site from Gitを選択
- GitHubを選択し、認証します(今回はすべてのリポジトリを許可しています)
- 認証が完了すると、以下のようにリポジトリが選択できるので対象のリポジトリを選択します
- 特に問題ないので、そのままDeploy siteを選択します
- Deployがはじまります
- Deployが失敗しました.赤文字になっているSite deploy failedがリンクになっているので選択します
- ログを確認します.microCMSのAPI Keyが設定していないことが原因のようでした
- Site Settings > Build & deploy > Environment > Environment variables > Edit VariablesでAPI Keyを設定します.Gastbyの設定で.envに設定したものと同じものですね
- Deploy logをみることができた場所からRetry deployができるので再デプロイします
- Deployが成功しました.URLが表示されているので遷移して確認できます
(Option)独自ドメインの設定
- こちらはお金が発生しますので、やりたい人だけ
- 公開したポートフォリオサイトに独自ドメインをつけましょう
前提条件
- Netlifyで公開できていること
- お名前.comで独自ドメインを取得できていること
Netlify側の手順
- Domain settingsを選択
- Add custom domainを選択
- まだ変更していなかったので、Options > Edit site nameからデフォルトのドメイン名も一応変えておきました
- お名前.comで取得したドメインを入力してVerifyを入力
- 「ドメイン名 already has an owner. Is it you?」と聞かれるので、「Yes, add domain」を選択
- Custom domainsに追加したドメインが表示されます
- Check DNS configurationを選択して、赤枠部分をメモしておきます
お名前.comの設定
- 管理画面からドメイン設定タブを選択
- ネームサーバーの設定からネームサーバーの変更を選択
- ドメインを選択し、ネームサーバーの選択ではその他を選択し、先ほどメモしておいたネームサーバを入力します
- NetlifyのCustom Domainで追加したドメインがNetlify Domaint表示されていることが確認できます
SSL化
- SSL化はNetlifyが自動でやってくれます
- HTTPSの方を見ると、Waiting on DNS propagationと表示されています
- L5 ~ 10分ほど待てば以下のようにYour site has HTTPS enabledと表示されるはずです
最後に
よく3日でできるとかあるんですけど、実際仕事をしながら3日の時間を作り出すのって大変なんですよね。平日は疲れてるし、土日は休みたい(そもそも子どもの世話とかしてたら平日よりも大変だ)し。しかもだいたいこういうのやるときって勉強も兼ねているから自分の持っていない技術スタックを使いがちで、そうなると全然3日でできないじゃん!てなります笑
ただそうは言ってもなんとなく知っているのと、やったことがあるは全然違います!
とりあえず手を動かすことが大切だと思います。今日から一時間でもよいのでやってみましょう!