こんにちは ebi です。
前回の記事で NuxtJS と WordPress を組み合わせるようなサイト構成の検証を軽くやったんですが、あまり真面目なコーディングをやらず仕舞いでした。
今回は NuxtJS 環境をベースでやる LP や Web サイトのコーディングに少しチャレンジしてみたいと思います。
Next.js も触りたかったんだけど、前回があまりにしょぼい内容しかやってなかったので次回以降にお預けと言うことで今回も NuxtJS です。
検証用のコーディング題材
って皆さん滅茶苦茶困りませんか?
デザインスキルとかまるでないし、かと言って既存サイトをそのまま真似するのもあれだし、と無駄なプライドを持って作業を進めたところでまともなコーディングにならなくて、CSS フレームワークの適当なパーツを組み合わせたところで凡庸なページしかできなくて全く面白くないですよね?
そんな折、少し前に練習用のコーディングテンプレートを公開してくれているサイトをはてブで見かけまして......今回満を持して使わせていただきました。
ねこポンさんが運営している「無料コーディング練習所」と言うサイトです。
このサイトではコーディング練習題材用のデザインカンプのデータをいくつか配ってくれていて非常にありがたいのです。
(こう言う親切なサイト他にもあるなら教えて欲しい or 自薦してください。次回の題材に使います??)
ただ Adobe XD 環境を整えるのが面倒だったので、今回はブラウザですぐ使える Figma でデザイン作成されていた【中級編3】ゲームサイトのコーディング練習を題材にしていくことにしました。
こんな感じのデザイン。丁度良いボリューム感ですね👍
なお、コーディングを完璧にこなすこと自体は本題じゃないために半日くらいの作業で切り上げたので、作成したのは PC デザインのみで細かい仕上げやパーツの実装は適当に割愛してます。
(本来はパララックスやフィルタの指定、BGM再生やスクロールダウンのアニメーション実装などの実装も要求されています)
と言うことで最終的なソースコードは GitHub からご覧いただけます。こんな感じ。
ちゃんと作ったものデプロイできてるぜと言う証拠がてら GitHub Pages から実際の公開後のページも見れます。こんな感じ。
利用素材に関して
当たり前のことですが、デザイン中の素材は著作権的に利用OKな無料素材を使用してくれていて、拝借先のサービスへのリンクは貼ってあるのですが、具体的な素材先は分からず、どれ使ってるんだろうって思って軽く調べたら動画は以下でした。
宇宙空間に関連した惑星の幾何学的対称性のデジタル投影 - Pexels
画像は適当に画像検索でもすればヒットするでしょう。
環境構築をしていく
僕の場合は以下のような開発環境でやってます。メモ書き程度のログですが参考までにどうぞ。
- ブラウザなどを開くホスト環境: Windows 10
- コーディング素材などがある作業環境: WSL2 で構築された Ubuntu 20.04
- Docker Desktop の Docker Engine : v20.10.12
Docker 環境構築 ~ NuxtJS のセットアップまで
前回の記事でも似たようなことをやっているので駆け足で行きます。
- まずは Node が動く Docker 環境を用意する。素の Node イメージで十分なはずなのでこんな感じ
# compose.yml
services:
node:
image: node:16
user: node
working_dir: /home/node
tty: true
ports:
- 3333:3000
volumes:
- ./nuxtjs:/home/node/nuxt-sample-site
docker compose up
してdocker compose exec node bash
でコンテナ内での作業を始めるnpm install create-nuxt-app
で NuxtJS プロジェクト作成用の create-nuxt-app をインストールするnpm init nuxt-app nuxt-sample-site
で NuxtJS プロジェクトを作成する
設定はこんな感じ。GitHub Action も使ってみたいぞ!と思って適用はさせたけど今回そこまで触る機会なかったね🙈
node@04cf09a00ceb:~$ npm init nuxt-app nuxt-sample-site
create-nuxt-app v4.0.0
✨ Generating Nuxt.js project in nuxt-sample-site
? Project name: nuxt-sample-site
? Programming language: JavaScript
? Package manager: Npm
? UI framework: None
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: ESLint, Prettier, StyleLint
? Testing framework: Jest
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Continuous integration: GitHub Actions (GitHub only)
? What is your GitHub username? ebihara-tomonari
? Version control system: Git
- ホスト側のブラウザから閲覧するために
nuxt.config.js
に以下だけ追記しておく
// nuxt.config.js
server: {
host: '0'
},
cd nuxt-sample-site
とnpm run dev
して開発環境を立ち上げて、
ホスト側のブラウザでhttp://localhost:3333/
にアクセスできるようになったことを確認する。前とちょっと変わったね。
コーディングの土台を整える
適当に調べて行きながらこの辺を整えました
meta タグとかの整備
は nuxt.config.js
内でデフォルト定義すればよいらしく、適時ページ側のテンプレートで上書きとかしていけば良いようでした。
あまり面白みを感じなかったので今回は初期状態のまま触ってません。
CSS 周りの整備
- 今回は CSS フレームワークを適用しない環境だったのでコーディングのために reset.css を適用させます。
特に拘りはないのですが、今回は modern-css-reset のプロジェクトを元にした reset.css を設置します。assets/css
ディレクトリを作成して↑を設置する- 読み込み設定を追加する
// nuxt.config.js
css: [
'@/assets/css/reset.css',
],
- SCSS でコーディングしたいのでライブラリを入れます。ここに書いてある通りのことをやれば良い
npm install --save-dev sass sass-loader@10
- 各コンポーネントのコーディング時に共通で使うSCSS変数を読み込ませるために
npm install @nuxtjs/style-resources
してnuxt.config.js
にbuildModules
とstyleResources
の定義を追記します。
// nuxt.config.js
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/eslint
'@nuxtjs/eslint-module',
// https://go.nuxtjs.dev/stylelint
'@nuxtjs/stylelint-module',
'@nuxtjs/style-resources',
],
styleResources: {
scss: ['@/assets/css/_variables.scss'],
},
layout やコンポーネントの整備
Rails のようにレイアウト機能が使えるので使ってみつつ、せっかくなので積極的にコンポーネント化しちゃってコーディングしていこうと思います。
- layouts ディレクトリは最初ないっぽいので作る
default.vue
を作ればデフォルトで適用される layout になるはずなので作るのだが、vue/multi-word-component-names
に違反していると言われるので.eslintrc.js
に以下を追記する
// .eslintrc.js
// add your custom rules here
rules: {
'vue/multi-word-component-names': ['error', {
'ignores': ['default']
}]
},
- ヘッダーとフッターは固定になるようなレイアウトを作ってみる(トップレベルの要素は一つにしないといけないので、 div で全体を括らないといけないのが気になるが......)
<style scoped>
で書けばそのコンポーネント内でのみ有効なCSS定義に、 scoped を付けなければグローバルなCSS定義になるはずなので基本はscoped
で書いていく
<!-- layouts/default.vue -->
<template>
<div>
<SiteHeader />
<Nuxt />
<SiteFooter />
</div>
</template>
<!-- components/SiteHeader.vue -->
<template>
<header>
this is header.
</header>
</template>
<style scoped>
div {
height: 100px;
}
</style>
- 続いて、TOPページ用の
pages/index.vue
の方にメインコンテンツを適当にコンポーネント化してレイアウトだけ作ってしまう
<!-- pages/index.vue -->
<template>
<div>
<TopMainVisual />
<TopStorySection />
<CommonCtaArea />
<TopTrailerSection />
<CommonCtaArea />
</div>
</template>
<script>
export default {
name: 'IndexPage',
}
</script>
コーディングを実際にする
ところは特に語ることはない気がする。楽しんでいきましょう。
と言うことでなんとなく雰囲気だけでも再現したものができました。
作業中の感想
- コンポーネント単位でコーディングしていくの結構楽しかったです。作業体験が良い感じ。
人によってCSSやJSの定義順が綺麗ではなかったり、追加作業は一番最後に足されていってどこからどこまでページ中のどの辺に関する定義なんだ!😡
と憤慨することもこの管理方針なら軽減されるんじゃないかなぁと思います。
軽くコード例を挙げるとこんな感じ
<!-- components/SiteHeader.vue -->
<template>
<header class="header">
<img src="~assets/img/Necopon_games.svg" class="header__logo" />
<div class="header__links">
<a href="#story" class="header__link-text">STORY</a>
<a href="#trailer" class="header__link-text">TRAILER</a>
<CommonPlayBtn size="small" />
</div>
</header>
</template>
<style lang="scss" scoped>
.header {
position: fixed;
height: 100px;
width: 100%;
background: linear-gradient(180deg, #000 0, rgba(0 0 0 / 62%) 68.75%, rgba(0 0 0 / 0%) 100%);
z-index: 10;
&__logo {
margin-left: 30px;
margin-top: 40px;
}
&__links {
position: absolute;
top: 0;
right: 30px;
display: flex;
align-items: center;
height: 100%;
}
&__link-text {
margin-right: 30px;
color: $main-color;
font-size: 16px;
font-weight: bold;
letter-spacing: 0.1em;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
</style>
<!-- components/common/PlayBtn.vue -->
<template>
<a class="play-btn" :class="(size === 'small') ? 'play-btn--sm' : ''" href="#">PLAY NOW</a>
</template>
<script>
export default {
props: {
size: {
type: String,
default: 'normal'
}
}
}
</script>
<style lang="scss" scoped>
.play-btn {
display: block;
width: 230px;
height: 60px;
background-color: $main-color;
color: black;
font-size: 18px;
font-weight: bold;
line-height: 60px;
letter-spacing: 0.05em;
text-decoration: none;
text-align: center;
&:hover {
opacity: 0.9;
}
&--sm {
width: 164px;
height: 45px;
font-size: 15px;
line-height: 45px;
}
}
</style>
- 作業中に stylelint や eslint でのチェックも効いているので、どうやら作業を終えた時点である程度の凡ミスやお作法ミスも少なくなってるっぽいです
- 今回は一ページ分しか作ってないのでまだアレなんですが、ちゃんと複数ページ存在する小規模~中規模なサイトを作る時にレイアウトやパーツの共通化などが生きて来るとまた楽しめそうです
まさか今時 PHP や SSI で共通パーツを include しようとは思いませんよね⁉
最後に完成品のビルド
は npm run generate
の実行でしたね。
前回の復習ですが、 GitHub Pages で表示させたい場合は以下のような指定でパスを解決させます。
// nuxt.config.js
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
publicPath: '/nuxtjs/'
},
router: {
base: process.env.NODE_ENV == 'production' ? '/for-techracho/nuxtjs-site-create/nuxtjs/dist/' : '/'
},
終わり
と言うことでペライチのサイト例でしたが、 NuxtJS をベースにコーディング・管理してみるとこんな感じになるよって雰囲気は掴めたんじゃないかなと思います。
とか書いてて気付いたけど、問い合わせフォームを付けてよって言われる問題も軽く検証しておかないとな……。
今更ですが、普段は Rails エンジニアとして(かどうかよく分からない雑多な案件・役割を請け負ってますが)仕事してますので、僕自身が NuxtJS で担当する大規模サイトのサイト制作なら弊社にお任せ!採用応募を!とかそう言う宣伝記事ではありませんので悪しからず......。
(もちろん会社としては各種お問い合わせや依頼は受け付けてます)
目下は BPS さんのコーポレートサイト、くんシリーズ、超シリーズの関連サイトなんかのリニューアルや新規立ち上げなど社内案件でのお声掛けと実績記事が書ける機会を待ってます😉