Next.js + TS + Tailwindで入門してみる
はじめに
最近腹筋ローラーを買って速攻で筋肉痛になりました。The walking deadもやっとシーズン10まで見終わりそうです。
なぜNext.jsを触るのか?
在籍している会社にてNext.jsを使用する流れになり、入門はしたけども忘れてしまったから再度入門して肩慣らしでもしておこう!という気持ちになり、今回触ることにしました。 TSにしているのは、会社ではTSで実装しているため多少いじるにしてもTSの方がいいでしょう!という理由です。
Next.js
Nuxt.jsより以前から開発が行われているReactのフレームワークです。
公式に物凄い数のexampleが用意されています。
ゴール
今回は、Next.jsを開発しているVercel社が用意しているサンプルにTailwindを適用してみるの巻です。
参照
今回は、参照記事を元に公式が用意しているexampleのwith-typescript
を使用してみたいとおもいます。
準備
- nodeのversionは、
v14.15.1
を使用します。
mkdir next-ts-sample cd next-ts-sample npx create-next-app --example with-typescript .
- installが終わったので
yarn dev
を実行してみる。下記画像のような表示がされました。
- Next.jsのアプリ全ページに
Tailwind
を使えるようにするためにpages
以下に下記fileを作成します。- ComponentなどをLayoutなどでラップしてあげるといいです
import './styles/tailwind.css' function App({ Component, pageProps }) { return <Component {...pageProps} /> } export default App
Tailwind入れる
yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest npx tailwindcss init --full touch pages/styles/tailwind.css
- 作成したtailwind.cssに以下を追加します
@tailwind base;
@tailwind components;
@tailwind utilities;
tailwind.config.jsに追記
- Purge オプションを使ってビルドサイズの縮小するこができます。
const colors = require('tailwindcss/colors') module.exports = { purge: ['./components/**/*.jsx', './pages/**/*.jsx'] // 省略
postcss.config.jsの作成
module.exports = { plugins: ['tailwindcss', 'autoprefixer'], }
ブラウザで一度確認してみる
- さきほどまでと様子が違うのでtailwindがあたってそうですね。
Tailwindを感じてみよう!
- pages以下に
weather.tsx
を作成し以下を記述する
const Weather = () => ( <div className="min-h-screen flex items-center justify-center"> <div className="border-solid border-2 flex flex-col bg-white rounded p-4 w-full max-w-xs"> <div className="font-bold text-xl">Sydney</div> <div className="text-sm text-gray-500">Thursday 10 May 2020</div> <div className="mt-6 text-6xl self-center inline-flex items-center justify-center rounded-lg text-indigo-400 h-24 w-24"> <svg className="w-32 h-32" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"></path></svg> </div> <div className="flex flex-row items-center justify-center mt-6"> <div className="font-medium text-6xl">24°</div> <div className="flex flex-col items-center ml-6"> <div>Cloudy</div> <div className="mt-1"> <span className="text-sm"><i className="far fa-long-arrow-up"></i></span> <span className="text-sm font-light text-gray-500">28°C</span> </div> <div> <span className="text-sm"><i className="far fa-long-arrow-down"></i></span> <span className="text-sm font-light text-gray-500">20°C</span> </div> </div> </div> <div className="flex flex-row justify-between mt-6"> <div className="flex flex-col items-center"> <div className="font-medium text-sm">Wind</div> <div className="text-sm text-gray-500">9k/h</div> </div> <div className="flex flex-col items-center"> <div className="font-medium text-sm">Humidity</div> <div className="text-sm text-gray-500">68%</div> </div> <div className="flex flex-col items-center"> <div className="font-medium text-sm">Visibility</div> <div className="text-sm text-gray-500">10km</div> </div> </div> </div> </div> ) export default Weather
localhost:3000/weather
にアクセスするpages
以下にcard.tsxを作成し以下を記述する
const Card = () => ( <section className="flex flex-row flex-wrap mx-auto"> <div className="transition-all duration-150 flex w-full px-4 py-6 md:w-1/2 lg:w-1/3" > <div className="flex flex-col items-stretch min-h-full pb-4 mb-6 transition-all duration-150 bg-white rounded-lg shadow-lg hover:shadow-2xl" > <div className="md:flex-shrink-0"> <img src="https://www.unfe.org/wp-content/uploads/2019/04/SM-placeholder-1024x512.png" alt="Blog Cover" className="object-fill w-full rounded-lg rounded-b-none md:h-56" /> </div> <div className="flex items-center justify-between px-4 py-2 overflow-hidden"> <span className="text-xs font-medium text-blue-600 uppercase"> Web Programming </span> <div className="flex flex-row items-center"> <div className="text-xs font-medium text-gray-500 flex flex-row items-center mr-2" > <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" ></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" ></path> </svg> <span>1.5k</span> </div> <div className="text-xs font-medium text-gray-500 flex flex-row items-center mr-2" > <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" ></path> </svg> <span>25</span> </div> <div className="text-xs font-medium text-gray-500 flex flex-row items-center" > <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5" ></path> </svg> <span>7</span> </div> </div> </div> <hr className="border-gray-300" /> <div className="flex flex-wrap items-center flex-1 px-4 py-1 text-center mx-auto"> <a href="#" className="hover:underline"> <h2 className="text-2xl font-bold tracking-normal text-gray-800"> Ho to Yawn in 7 Days </h2> </a> </div> <hr className="border-gray-300" /> <p className="flex flex-row flex-wrap w-full px-4 py-2 overflow-hidden text-sm text-justify text-gray-700" > Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias, magni fugiat, odit incidunt necessitatibus aut nesciunt exercitationem aliquam id voluptatibus quisquam maiores officia sit amet accusantium aliquid quo obcaecati quasi. </p> <hr className="border-gray-300" /> <section className="px-4 py-2 mt-2"> <div className="flex items-center justify-between"> <div className="flex items-center flex-1"> <img className="object-cover h-10 rounded-full" src="https://thumbs.dreamstime.com/b/default-avatar-photo-placeholder-profile-icon-eps-file-easy-to-edit-default-avatar-photo-placeholder-profile-icon-124557887.jpg" alt="Avatar" /> <div className="flex flex-col mx-2"> <a href="" className="font-semibold text-gray-700 hover:underline"> Fajrian Aidil Pratama </a> <span className="mx-1 text-xs text-gray-600">28 Sep 2020</span> </div> </div> <p className="mt-1 text-xs text-gray-600">9 minutes read</p> </div> </section> </div> </div> </section> ) export default Card
localhost:3000/card
にアクセスする
感想
今回のゴールがあくまでTailwindの適用なのでTSである必要なかったな
フロントのキャッチアップは、目に見えてわかるから楽しい反面、エラーが発生したりすると何を言っているんだって気持ちになるんで億劫になりがちだけど
今後も入門程度でもいいからいろいろ触って経験値だけは積んでいきたいとおもった。
あとVSCodeのフォーマッターがうまく動かず。。。