スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【自作ブログ #14】GitHub Pagesでの公開(1)

自作ブログを作っています。

yushi-dev.hatenablog.com

技術スタック

  • TypeScript
  • React
  • Next.js
  • Styled Components
  • GitHub Pages

今回はGitHub Pagesで公開します。

設定

GItHub上での設定が必要です。

Settings > Pagesが設定ページです。

今回は Source = Deploy from a branch という設定で、gh-pagesというブランチをpushしたときに、/docs以下をデプロイするよう設定しました。

静的ファイル化

通常の開発時には開発サーバーを立ち上げ、その機能によって画面表示がされます。

一方本番デプロイのためには静的ファイルとしてまとめる必要があります。

今回利用しているNext.jsでは静的ファイル化の機能を提供しているため、これを呼び出すだけで済みます。

まずはnext.config.js

package.json にコマンドを追加します。

{
  ...
  "scripts": {
    ...
    "export:gh-pages": "npm run clear:gh-pages && BASE_PATH='blog' npm run export && touch out/.nojekyll && cp -r out ../docs",
    "clear:gh-pages": "rm -rf ./out ../docs",
    ...
  }
  ...
}

clear:gh-pages は、主にローカル環境での動作確認時に、生成されるファイルを削除するコマンドです。

export:gh-pages は、静的ファイル生成のためのコマンドです。

npm run export というのがNext.jsが提供しているコマンドです。

touch out/.nojekyll の記述によって、.nojekyllというファイルを生成します。
こちらがないと、デプロイ時に 生成ファイルの内_next に対してNot Foundエラーが発生してしまいます。
この問題については、下記のページの説明がわかりやすかったです。

GitHub Pagesで普通の静的ホスティングをしたいときは .nojekyll ファイルを置く #GitHub - Qiita

最後にcp -r out ../docs の箇所にて、docs ディレクトリに静的ファイルを移動します。
これは、

BASE_PATH='blog'の記述については、次の章で説明します。

path問題の解決

GitHub Pagesで公開した場合、デフォルトのURLは下記のようになります。

https://[user-name].github.io/[repository-name]

ここでの問題として、ローカル環境の場合と違ってGitHub Pages上では/[repository-name] のパスが含まれることへの対応が必要となります。

next.config.js への記述によって、base pathを指定することができます。

const basePath = process.env.BASE_PATH ? '/' + process.env.BASE_PATH : ''

const nextConfig = {
  basePath,
}

module.exports = nextConfig

process.env.BASE_PATH の箇所は環境変数で、これによって、ローカル環境では未指定としたり、GitHub Pages上では[repository-name] を指定することができます。

前章の静的ファイル化のコマンドに含めた BASE_PATH='blog'は、この[repository-name] = blogを指定していました。

デプロイ

先の設定に則り、gh-pages というブランチにpush することで公開ができます。

デプロイに成功しました。

ただ画像が表示されない問題があります。
こちらは次回解決していきます。

あとがき

あけましておめでとうございます。
年末は夫婦で体調を崩して大変でしたが、なんとか回復しました。

【自作ブログ #13】一覧ページの改善(2)

自作ブログを作っています。

yushi-dev.hatenablog.com

技術スタック

  • TypeScript
  • React
  • Next.js
  • Styled Components
  • GitHub Pages

今回は記事一覧ページをいい感じにします。
今回は後半です。

画面表示

分解してそれぞれにCSS適用します。

タイトルは大きく強調します。

import styled from 'styled-components'


const Title = styled.span`
  margin-bottom: 7px;
  font-size: 1.5rem;
`

日付は小さく、色も薄くします。

const Date = styled.small`
  margin-bottom: 2px;
  font-size: 0.6rem;
  color: #777;
`

肝となる、本文を一部表示する箇所です。
下部には擬似要素で、グラデーションのぼかしを入れています。

const ContentBeginning = styled.div`
  position: relative;
  max-height: 9.3rem;
  overflow: hidden;
  /** 下部のblur */
  &::before {
    content: '';
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 40%;
    background: linear-gradient(
      rgba(255, 255, 255, 0.3),
      rgba(255, 255, 255, 0.9)
    );
  }
`

wrapper要素として、margin, flexbox, text-decorationのresetなどを組み込みます。

const Li = styled.li`
  margin-bottom: 3rem;
`

const StyledArticleLink = styled.a`
  display: flex;
  flex-direction: column;
  text-decoration: none;
`

最後にまとめて一つのコンポーネントにします。

import { convertToPlain } from '@/utils/markdown-utils'

type Props = {
  slug: string
  title: string
  date: string
  content: string
}

const ArticleListItem = ({ slug, title, date, content }: Props) => {
  const contentText = convertToPlain(content)

  return (
    <Li key={slug}>
      <StyledArticleLink href={'/posts/' + slug}>
        <Date>{date}</Date>
        <Title>{title}</Title>
        <ContentBeginning>{contentText}</ContentBeginning>
      </StyledArticleLink>
    </Li>
  )
}

export default ArticleListItem

一覧表示

最後に一覧表示します。

type Props = {
  posts: {
    content: string
    matter: PostMatter
  }[]
}

const Index = ({ posts }: Props) => {
  const matters = posts.map(({ matter }) => matter)
  const links = (
    <ArticleList>
      {posts.map(({ content, matter }) => (
        <ArticleListItem
          key={matter.slug}
          slug={matter.slug}
          title={matter.title}
          date={matter.date}
          content={content}
        />
      ))}
    </ArticleList>
  )

  return (
    <MainContainer matters={matters}>
      <section>{links}</section>
    </MainContainer>
  )
}

export default Index

Pull Request

https://github.com/nek0meshi/blog/pull/15

あとがき

今年のM1おもしろかったな〜!!

弊社のCMが流れてました。

【自作ブログ #12】一覧ページの改善(1)

自作ブログを作っています。

yushi-dev.hatenablog.com

技術スタック

  • TypeScript
  • React
  • Next.js
  • Styled Components
  • GitHub Pages

今回は記事一覧ページをいい感じにします。
今回は前半です。

作りたいもの

現状の記事一覧ページは単にファイル名で並べているだけです。

ブログタイトル、公開日、記事内容の一部を表示するように改修します。
重要度順にフォントサイズをタイトル、記事内容、公開日としました。
記事内容については冒頭の一部を表示します。
ぶつ切りな見た目にならないように、フェードアウトするようにさせます。

ダミー記事作成

記事をダミーで作成するためのshスクリプトを作成します。
簡易なもので良いため、用意したサンプルファイルをコピーします。

.PHONY: seed-posts
seed-posts:
  echo posts/sample{3,4,5,6,7,8,9,10,11,12,13,14,15}.md | xargs -n 1 cp posts/sample.md

既存の posts/{sample1,sample2}.md に加えて、3〜15のナンバリングのファイルを自動生成します。

Markdownファイルの内容を読み出す

現状ではファイル名のみを一覧表示にしていましたが、ファイルの中身を利用します。
まずはファイル内容を読み出し、一覧にします。

matter一覧を元に、その作成日順に並べます。
次にファイル本文の内最初の300文字のみを読み出します。

// pages/index.tsx

export async function getStaticProps() {
  const posts = await Promise.all(
    (
      await postService.getMatters()
    )
      .slice()
      .sort((a, b) => (a.date < b.date ? 1 : -1))
      .map(async (matter) => ({
        content: (
          await postService.loadMarkdown(matter.slug)
        ).content.slice(0, 300),
        matter,
      }))
  )
}

あとがき

今回は方針決定や細かい準備、ファイルからの読み出しなどを進めました。
次回は表示を作っていきます。

最近は自宅のデスクが整ってきて、ついにサブモニターを導入しました。
やっぱり効率がだいぶ変わりますね。
いろいろ整ったら、いつか記事にもしてみたいと思ってます。

【プロフィールページ 第15回】Nuxt3への移行 - ファイルの移行

プロフィールページを作成していきます。 現在はNuxtのバージョンを2から3に移行しています。

プロフィールページ カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • Nuxt.js
  • SCSS
  • Tailwind CSS

今回はファイル移行していきます。

ファイルのコピー

まずは単にファイルをコピーします。

components, assets, pagesのファイルは単に新しいv3のプロジェクトに移動します。

静的ファイル(ビルド等が不要で、そのままブラウザに返すファイル)について、Nuxt2ではstaticというファイルに格納していました。

Nuxt 2 - 静的ディレクトリ

Nuxt3ではpublicというファイル名に変更されています。

Assets · Get Started with Nuxt

その他の対応

エントリーポイントはpages/index.vueに変更されるため、v3/app.vueは不要になるため削除します。

static/ディレクトリが削除されるため、pathを変更します。

- background-image: url('./static/hero.jpg');
+ background-image: url('./hero.jpg');

main.scssを各ページで読み込めるように設定します。

+ css: ['@/assets/scss/main.scss'],

以上までで、ついに画面が表示されるようになりました!

スクリーンショット

Pull Request

https://github.com/nek0meshi/profile/pull/26

【プロフィールページ 第14回】Nuxt3への移行 - ライブラリ導入

プロフィールページを作成していきます。

プロフィールページ カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • Nuxt.js
  • SCSS
  • Tailwind CSS

今回はライブラリの導入をします。

Tailwind CSS

本プロフィールページはTailwind CSSを利用していますので、導入します。

tailwindcss.com

Tailwind CSSを直接導入するのではなく、Nuxt Integration版を利用します。

tailwindcss.nuxtjs.org

npm i -D @nuxtjs/tailwindcss

設定を追加します。

(nuxt.config.ts)

 export default defineNuxtConfig({
  devtools: { enabled: true },
+  modules: ['@nuxtjs/tailwindcss'],
 })

prettier

formatterとしてprettierはほぼ必須かなと思います。

prettier.io

prettierの難点というか、意見の分かれるところと言えば、カスタマイズ性がほとんどないことです。
これはprettierの思想に関わる部分です。
実際細かいところで違和感があることもありますが、全体としてはメリットが大きいです。

prettier.io

npm i -D prettier

設定を追加します。

(.prettierrc.yml)

singleQuote: true
semi: false

コマンドを追加します。

(package.json)

{
  ...
  "scripts": {
    "prettier": "prettier -c .",
    "prettier:fix": "prettier -w .",
    ...
  }
  ...
}

Sass

Sassの除去は検討中ですが、移行のためいったんSassを導入します。

sass-lang.com

npm i -D sass

ESLint

linterとしてはESLint一択かなと思います。

eslint.org

ESLintの他、vue・TypeScript・Prettierとの連携のためのライブラリも同時に導入します。

npm i -D eslint eslint-plugin-vue @typescript-eslint/parser eslint-config-prettier

設定ファイルも追記します。

root: true
env:
  browser: true
  node: true
parser: 'vue-eslint-parser'
parserOptions:
  parser: '@typescript-eslint/parser'
extends:
  - 'eslint:recommended'
  - 'plugin:vue/vue3-recommended'
  - 'prettier'

コマンドも追加します。

(package.json)

{
  ...
  "scripts": {
    "eslint:fix": "eslint --fix '**/*.{js,ts,vue}'"
    ...
  }
  ...
}

Pull Request

https://github.com/nek0meshi/profile/pull/25

あとがき

あっという間に寒くなり、もこもこのフリースを着て過ごしています。

【プロフィールページ改修 第13回】Nuxt3への移行 - プロジェクト作成

プロフィールページを作成していきます。

プロフィールページ カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • Nuxt.js
  • SCSS
  • Tailwind CSS

今回のNuxt3のprojectを作成します。

asdf

node.jsのバージョン管理はasdfを利用します。

asdf-vm.com

node.jsのLTSを確認します。

nodejs.org

最新の20.9.0を導入します。

asdf install nodejs 20.9.0
asdf global nodejs 20.9.0

プロジェクト作成

NuxtのInstallationページをベースに進めていきます。

nuxt.com

npx nuxi@latest init v3

# v3の名前でNuxt3のプロジェクトが作成される

asdfでバージョンを固定します。

cd v3
asdf local nodejs 20.9.0

# .tool-versionsが作成される

開発サーバを起動します。

npm install
npm run dev -- -o

Pull Request

https://github.com/nek0meshi/profile/pull/24

あとがき

バージョンアップはワクワクがあって楽しいですね。

【プロフィールページ改修 第12回】Nuxt3への移行 - 計画

久しぶりに、プロフィールページを作成していきます。

プロフィールページ カテゴリーの記事一覧 - スマレジエンジニアyushiのブログ

技術スタックは下記の通りです。

  • nuxt.js
  • SCSS
  • Tailwind CSS

今回から、Nuxt3への移行を進めていきます。

Nuxt3

Vue3のリリースに続き、Vue3対応のNuxt3が2022年末にリリースされています。

本プロフィールページはNuxt2で制作されているので、Nuxt3へのアップデートや、Nodejsのバージョンなどもアップデートしていきたいです。

Nuxt2からのMigration

Nuxt.js2からNuxt.js3へのMigration Guideは、公式では詳しい記載がありません。

nuxt.com

そこで新しくNuxt3のprojectを作成し、既存のソースを移動していく方針とします。

また、Nuxt3対応と合わせて、他のいくつかの要素も更新していきます。

SCSSの除去

CSSの機能向上により、SCSSを使わなくても実現できることが増えてきています。

変数は、CSSカスタムプロパティにより実現されました。

developer.mozilla.org

階層構造はCSS nestingによって実現されました。

developer.mozilla.org

これらの採用により脱SCSSが可能なのか、調査してみたいと考えています。

Composition API

Vue3と言えばやはりComposition APIですね。
Options APIを維持することも可能かと思いますが、今回Composition APIに移行していきたいと思います。

その他の更新

その他にも、

  • Node.jsを最新のLTSに更新する
  • webpackからViteへの移行
  • yarnからnpmへの移行
  • その他の実装の改善

などを進めていきたいです。

あとがき

次回移行実際に移行を進めていきます。

最近はReactを書くことが多いので、Vueの記法を忘れていることに気づきました。