Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

portfolio構築の記録 #1

Open
sakelog opened this issue Dec 27, 2020 · 5 comments
Open

portfolio構築の記録 #1

sakelog opened this issue Dec 27, 2020 · 5 comments
Labels
report 作業記録

Comments

@sakelog
Copy link
Owner

sakelog commented Dec 27, 2020

portfolioサイト構築の記録を残していきます。

@sakelog
Copy link
Owner Author

sakelog commented Dec 27, 2020

2020/12/28

Markdownをパーツとして埋め込めるようにしてみた。

fsgetStaticPropsgetServerSidePropsの中からしか呼べないので、そこでちょっとつまづいた。

そして、getStaticPropsgetServerSidePropspagesからしか呼べない。

index.tsx上でgetStaticPropsを使用して取得したComponentをまとめて引数として渡して、渡した引数で対処するようにした。

markdownからhtmlへの変換は、もともと使用していたremarkとremark-htmlではなぜかうまくできなかったので、react-markdownを採用。

若干使い方をミスっているような(たまたまうまくできているだけのような)気がするので、もう少し考える。

remarkとremark-htmlで変換できなかった理由も余裕があれば考えておく。

次にやりたいこと

jsonもしくはyamlのデータを取り込めるようにする。

今後api使うこと考えたらjsonか。

@sakelog sakelog added the report 作業記録 label Dec 27, 2020
@sakelog
Copy link
Owner Author

sakelog commented Dec 29, 2020

2020/12/29

JSONファイルを埋め込めるようにしてみた

昨日実装したMarkdown取り込み機能のJSON版を作成してみた。

スタイル当てること考えるとJSONはかなり使い勝手がよく、結局全部のパーツをJSONから取り込むことに。

今後のことを考えてMarkdown取り込み機能は残しておく。

詰まったポイント

ファイルの内容をJSONとして扱えない
JSON.parse()を使う

const fileContent = fs.readFileSync(fullPath, 'utf-8');
const content = JSON.parse(fileContent);

参考:https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

改行の\nがそのまま出力されてしまう。html上で改行を改行として扱いたい
→html出力する前に改行コードを読み替える。cssで改行をそのまま活かす設定にする。

replaceを使って改行コードを置き換える。JSON上で改行したい位置には\\nを入れておく。

const result = hogehoge.replace(/\\n/g, '\n')

デフォルトのcss設定だと改行が生かされないので、cssの設定を変更する。

  .hogehoge {
    white-space: pre-line;
  }

スタイルを当ててみた

scssを使ってスタイルを当ててみた。スタイルが設定されると、かなり完成に近づいたように感じる。

Next.jsでscssを使う方法のまとめ

参考:https://nextjs.org/docs/basic-features/built-in-css-support

sassをインストールする

yarn add sass

scssの拡張子を~.module.scssで保存すると、各コンポーネントからscssをimportできる。

グローバルスタイルを反映させたい場合はnext.config.js_app.tsxの設定が必要。

next.config.js

const path = require('path')

module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
}

_app.tsx

import type { AppProps /*, AppContext */ } from 'next/app';
import '../styles/global.scss';

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;

型定義ファイルを実装した

タイプの制御が複雑になってきてしまったので、型定義のファイルを作成した。

参考:https://developer.hatenastaff.com/entry/2016/06/27/140931

@typesフォルダを作成して~.d.tsで型定義ファイルを作成すると自動で型定義が反映される。

型の宣言にはdeclareの記載が必要。

declare type func = (props:props) => JSX.Element

既存のタイプを生かして型の宣言をしたい場合はinterfaceextendsを使う。

  declare interface aboutme_jsonContent extends JSON {
    aboutme_list?: [
      {
        title: string;
        content: string;
      }
    ]
  }

コンタクトフォームを作成した

コンタクトフォームを作成。とりあえず今はデザインだけ。

サイト公開設定後、コードを見直す。

次にやりたいこと

  • 制作物のパーツを作る
  • グローバルメニューを作る

@sakelog
Copy link
Owner Author

sakelog commented Dec 30, 2020

2020/12/30

ヒーローヘッダーを作成した

ファーストビューで全画面に表示されるヘッダーを作成した。

Next.jsのnext/image背景表示のデモが参考になった。

https://image-component.nextjs.gallery/background

Githubのリポジトリ情報を取得して取り込んだ

GithubのリポジトリをAPIを使って取り込み。

トークンとか必要ない公開情報しか取り込んでいないけど、なかなか良い感じなのでは…。

API使ってデータ加工するの楽しかったので、APIを使ってなにか作りたい。

製作物のjson取込

Webサイトなど、Github以外で取り込みたいコンテンツを取り込めるようにした。

サイトのスクリーンショットを載せたかったので、自動取得しようと考えたけど、一度サイトに接続してからでないとできないみたいで断念。

手動でスクリーンショットを取得して、読み込みをするようにした。

スムーススクロールの実装

react-scroll を使ってスムーススクロールを実装した。

ナビメニューから各コンテンツに飛ばすときにスクロール。

ついでに各コンテンツから前後するコンテンツにも飛べるようにしてみた。

トップに戻るボタンは不要かなと感じているのでとりあえずつけないでおく。

次にやりたいこと

  • SEO対策
  • PWA化
  • サイト公開

@sakelog
Copy link
Owner Author

sakelog commented Dec 31, 2020

2020/12/31

PWA化

PWA化した。使用したのはnext-pwa

公式の説明どおりに設定したのになぜかServiceWorkerとWorkboxが作成されない~~??と思っていたらファイル名が誤っているという初歩的なミスだった……。

next-config.jsnext.config.js

next.config.jsに下記記載すると無事PWA化に必要なファイルがpublicに出力される。

const withPWA = require('next-pwa')

module.exports = withPWA({
  pwa: {
    dest: 'public'
  }
})

public/sw.js*public/workbox-*を.gitignoreに追加した。

サイトマップを作成した

デプロイ時(サイト更新時)にsitemap.xmlが自動で出力されるようにした。

作成するフォーマットは下記の内容を目指す。

<?xml version="1.0" encoding="UTF-8" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>url</loc>
    <lastmod>YYYY-MM-DDThh:mmTZD</lastmod>
   <changefreq>更新頻度</changefreq>
   <priority>優先度</priority>
  </url>
</urlset>

getStaticProps()の中で設定用の関数を呼び出して制御した。

setSiteMap関数を作成した。

import fs from 'fs';
import { format } from 'date-fns';
import SiteMeta from '../config';

export function setSiteMap(fetchDate: Date) {
  let SitemapString: string;

  SitemapString = '<?xml version="1.0" encoding="UTF-8" ?>';
  SitemapString +=
    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
  SitemapString += '<url><loc>';
  SitemapString += SiteMeta.url;
  SitemapString += '</loc>';
  SitemapString += '<lastmod>';
  SitemapString += format(fetchDate, 'yyyy-MM-dd');
  SitemapString += 'T';
  SitemapString += format(fetchDate, 'hh:mmxxx');
  SitemapString += '</lastmod>';
  SitemapString += '<changefreq>monthly</changefreq>';
  SitemapString += '<priority>1.0</priority>';
  SitemapString += '</url></urlset>';

  fs.writeFile('public/sitemap.xml', SitemapString, 'utf8', () => {
    console.log('Sitemap.xml saved');
  });
}

getStaticPropsはデプロイ時に走るので、発した日を渡して、フォーマットを整えて、
publicフォルダのsitemap.xmlに書き出す。

参考:Next.js + Netlifyで作ったサイトにsitemap.xmlを設置する

サイト公開

サイト公開用の設定を行った。

ドメインはGoogleドメインで取得。

公開先はNetlifyにしようと思ったけど、next/imageを使っていると静的HTMLファイルの生成ができないらしい。

Netlifyでもなんとか解決できそうだったけど、公開設定が簡単そうなVercelにした。

Vercel

VercelのAレコードをGoogleドメインに登録することで問題なく紐付け完了した。

Netlifyを選択肢から外したので、コンタクトフォームは組み込まないことにした。

外部サービスのコンタクトフォームを使用して、リンクボタンを貼り付けた。

GoogleTagManager(GoogleAnalytics)の導入

GoogleTagManagerを使って、GoogleAnalyticsを設定した。

headタグ内に記載が必要なタグはHeadコンポーネント内に記載した。

const GTM_ID = process.env.GTM_ID;

const GTMScript = `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${GTM_ID}');`;

const CustomHead = () => {

  return (
    <Head>
      <script
        dangerouslySetInnerHTML={{
          __html: GTMScript,
        }}
      />
・
・
・
    </Head>
  );
};

export default CustomHead;

bodyタグ内に記載が必要なタグは_document.tsx内に記載した。

import Document, { Html, Head, Main, NextScript } from 'next/document';

const GTM_ID = process.env.GTM_ID;
const GTMNoScript = `<iframe src="https://www.googletagmanager.com/ns.html?id=${GTM_ID}"
height="0" width="0" style="display:none;visibility:hidden"></iframe>`;

class MyDocument extends Document {
  render() {
    return (
      <Html lang="ja">
        <Head />
        <body>
          <Main />
          <NextScript />
          {/*--- Google Tag Manager */}
          <noscript dangerouslySetInnerHTML={{ __html: GTMNoScript }} />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

スマホ・タブレットからの表示修正

スマホやタブレットからの表示を修正した。

ヒーローヘッダーの高さを100vhで指定していたけど、スマホやタブレットだとツールバー分ずれてしまう。

window.innerHeightを取得して設定することで解決した。

const HeroHeader = () => {
  const [innerHeight, setInnerHeight] = React.useState(400);

  function handleInnerHeight() {
    setInnerHeight(window.innerHeight);
  }

  React.useEffect(() => {
    handleInnerHeight();
    window.addEventListener('orientationchange', () => {
      handleInnerHeight();
    });
    window.addEventListener('resize', () => {
      handleInnerHeight();
    });
  });

  return (
    <>
      <nav className={styles.heroheader} style={{ height: innerHeight }}>
・
・
・

window.addEventListener('orientationchange')で画面の向きが変わったときにも切り替え、
window.addEventListener('resize')で画面サイズが変わったときにも切り替えするようにしている。

初期の高さはもう少し高くても良いかも。

#2 のスマホ横向きのときの表示不備があるので、合わせて考える。

スマホやタブレットで実機で開発環境確認できるようにした。

package.jsonのスクリプトに下記を追加した。

  "scripts": {
    "dev-host": "next dev -H 0.0.0.0"
}

次にやりたいこと

  • 自動更新(Github Actionsで月イチで自動コミットが走るようにしたい)
  • Readmeの充実

@sakelog
Copy link
Owner Author

sakelog commented Apr 9, 2022

かなりの期間記録が漏れてしまっていた。。

GraphQLでの情報取得

中のコンテンツはGraphCMSにコンテンツを登録して、GraphQLで取得を行うようにした。

lib > graphCMS > client.tsx

import { GraphQLClient } from 'graphql-request';

export const GraphCMSClient = new GraphQLClient(
  process.env.GRAPHCMS_API ? process.env.GRAPHCMS_API : ''
);

lib > graphCMS > getContent > AboutMe > getAboutMeItems.tsx

import { GraphCMSClient } from '@lib/graphCMS/client';
import { gql } from 'graphql-request';

export const getAboutMeItems = async () => {
  const { aboutMes }: { aboutMes: Profile.AboutMe.Items } =
    await GraphCMSClient.request(gql`
      query Query_AboutMes {
        aboutMes {
          id
          title
          detail
        }
      }
    `);

  return aboutMes;
};

GitHubの情報も@octokit/graphqlを使用してGraphQLで取得をしている。

lib > github > client.tsx

import { graphql } from '@octokit/graphql';

export const GithubAPIClient = graphql.defaults({
  headers: {
    authorization: `token ${process.env.GITHUB_PERSONAL_ACCESS_TOKEN}`,
  },
});

lib > github > getContent > Repository > getRepositorys.tsx

import { GithubAPIClient } from '@lib/github/client';

export const getRepositorys = async () => {
  const { user }: { user: Works.GitHub.User } =
    await GithubAPIClient(
      `
      query Query_Repositories{
        user(login: "sakelog") {
          repositories(last: 20, privacy: PUBLIC, orderBy: {field: UPDATED_AT, direction: DESC}) {
            nodes {
              id
              name
              description
              url
              createdAt
              updatedAt
              primaryLanguage {
                name
                color
              }
            }
          }
        }
      }
    `
    );

  const { repositories } = user;

  return repositories;
};

見返していて気づいたが、GitHubのRepository取得のクエリ内にユーザー名が直切りになっているので、変数化できないか検討が必要。

MarkdownのHTML化

一部Markdownを用いたコンテンツを登録したかったので、MarkdownからHTMLに変換する関数を作成した。

lib > util > markdownToHtml

import { unified } from 'unified';
import remarkParse from 'remark-parse/lib';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify/lib';

export const markdownToHtml = (markdown: string) => {
  const convertedHTML = unified()
    .use(remarkParse)
    .use(remarkRehype)
    .use(rehypeStringify)
    .processSync(markdown)
    .toString();

  return convertedHTML;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
report 作業記録
Projects
None yet
Development

No branches or pull requests

1 participant