TypeScript × Reactの環境構築を極限までわかりやすく
はじめにTypeScriptについて
TypeScriptはJavaScriptの上位互換としてマイクロソフトが生み出した静的型付け言語です。
JavaScriptとの大きな違いは「型」にあり、強固な型は安全で読みやすいコードを生み出します。それを踏まえたうえでTypeScriptを始めると最初は慣れなくても書き続ければどんどん美しいコードになっていきます。それでは実際に構築してみましょう!
完成したもの
完成した
環境
・node.js => 18.12.1
・typescript => 4.8.4
・react =>18.0.21
・next => 12.3.1
・yarn => 1.22.19
・prettier => 2.7.1
・eslint => 8.25.0
手順①node.jsのインストール
まずはnode.jsを導入しましょう。既に入っている人は飛ばしてください。
入っていない人はnode.js推奨版(LTS)をインストールしてください。選択肢は特にいじらず、nextを押してかまいません。
できたらnode -v
を打ち込み、v18.12.1
と表示される事を確認してください。
手順②yarnのインストール
node.jsをインストールした事でnpmが使えるようになりました。npm install -g yarn
を入力する事でインストールできます。yarn -v
でバージョンが出てくればokです!
手順③typescriptプロジェクトの作成
npx create-next-app sample --typescript
と打ち込んでください。sample
には任意のアプリ名で構いません。今はsampleと呼びます。作ったらcode sample
で開きましょう。
ターミナルにyarn dev
と打つと、localhost:3000のURLがターミナル上で表示されますのでそこにアクセスし、このような画面が表示されれば完了です!
詳細な設定
このままでも大丈夫ですが、ここからは開発をとてもスムーズにする機能を追加していきます。コードを見やすくしてくれたり、自動でデプロイしてくれたり、コードをテストしてくれたりなど、これからの開発でコーディングに集中するためにも、必ず設定することをお勧めします。
手順④eslintの設定
まずはこちらのコードをご覧ください。
また、各プロパティの意味が気になる人はこちらの記事で確認してください。
module.exports = {
root: true,
extends: [
"airbnb",
"airbnb/hooks",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"prettier",
],
plugins: ["@typescript-eslint", "react"],
parser: "@typescript-eslint/parser",
env: {
browser: true,
node: true,
es6: true,
},
settings: {
react: {
version: "detect",
},
},
parserOptions: {
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
ecmaFeatures: {
impliedStrict: true, //常にStrictMode
},
rules: {
"react/prop-types": "off",
"react/self-closing-comp": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "error",
"prefer-template": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"no-unreachable": ["error"], //到達できないコードはエラー
},
};
注意点があります!
一つ目はextends:
のプロパティです。こちらでは複数のルールをまとめたパッケージを使用しているのですが、ルールが重複する場合があります。同じの場合はともかく、異なるルールを指定しているときは後に書いたルールが優先されます。指定したのに違う動きをしているときはここを疑ってみて下さい。また、prettier
を一番最後にし、eslint:recommended
を最初にすることを覚えておいてください。
二つ目はrulesです。個別のルールはprettierで設定するのであまり凝らない方がいいです。衝突が起きたり、他の人が使う時に面倒になるからです。ここではno-unreachable
のみが個別の設定になります。
手順⑤prettierの設定
yarn add prettier --save-dev prettier eslint-config-prettier
とコマンドを打ってください。
そしてpackage.json
ファイルの"scripts"
の中に"format": "prettier --write \"./src/**/*.{ts,tsx}\""
を追加してください。
そして、.vscode
ディレクトリを作成しその中にsettings.json
を作成して以下の記述をしてください。
{
"editor.defaultFormatter": "esbenp.prettier-vscode", // フォーマッターをPrettierにする
"editor.formatOnSave": true // ファイル保存時にフォーマットを実行
}
さらにextentions.json
ファイルを作成し、以下を記述します。これでチーム開発の時に必要な拡張機能を知らせることが出来ます。
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
"styled-components.vscode-styled-components",
"Code formatter using prettier.prettier-Code formatter",
"stylelint.stylelint",
"Integrates ESLint JavaScript into VS Code.ESLint"
]
}
そして.prettierrc
ファイルを作成し、以下の設定をします。
{
"singleQuote": true,
"semi": false,
"quoteProps": "consistent",
"jsxBracketSameLine": false,
"singleAttributePerLine": true,
"arrowParens": "always"
}
詳しく知りたい人はprettierの公式ドキュメントを読んでください。
手順⑥styled-componentsを導入しよう
一つのファイルにCSSなどを記入できるようになります。コンポーネントを作り、HTMLのタグのように扱えるのです!
コマンドで以下を打ちましょう。
yarn add @types/styled-components
手順⑦MUIを使ってみよう
material-ui(MUI)はモダンで最も人気のあるUIの一つです。
これを使用すると簡単にかっこいいデザインが作れます!
ターミナルで以下を打ち込みましょう。
yarn add @mui/material @mui/styled-engine-sc styled-components
yarn add @emotion/react
yarn add @emotion/styled
これで使用できるようになりました!styled-componentと併せて```index.tsxを書き換えてみましょう!
import type { NextPage } from 'next'
import Head from 'next/head'
import React from 'react'
import styled from 'styled-components'
import { Button } from '@mui/material'
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
min-height: 100vh;
padding: 0 0.5rem;
`
const Main = styled.main`
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5rem 0;
`
const Title = styled.h1`
margin: 0;
font-size: 4rem;
line-height: 1.15;
text-align: center;
a {
color: #0070f3;
text-decoration: none;
}
a:hover,
a:focus,
a:active {
text-decoration: underline;
}
`
const Description = styled.p`
font-size: 1.5rem;
line-height: 1.5;
text-align: center;
`
const Code = styled.code<{ bgColor: string }>`
padding: 0.75rem;
font-family: Menlo, 'Monaco, Lucida Console', 'Liberation Mono',
'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace;
font-size: 1.1rem;
background: ${(props) => props.bgColor};
border-radius: 5px;
`
const Grid = styled.div`
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
max-width: 800px;
margin-top: 3rem;
@media (max-width: 600px) {
flex-direction: column;
width: 100%;
}
`
const Card = styled.a`
width: 45%;
padding: 1.5rem;
margin: 1rem;
color: inherit;
text-align: left;
text-decoration: none;
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
:hover,
:focus,
:active {
color: #0070f3;
border-color: #0070f3;
}
h2 {
margin: 0 0 1rem;
font-size: 1.5rem;
}
p {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
}
`
const Footer = styled.footer`
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100px;
border-top: 1px solid #eaeaea;
a {
display: flex;
flex-grow: 1;
align-items: center;
justify-content: center;
}
`
const Logo = styled.span`
height: 1em;
margin-left: 0.5rem;
`
const HomePage: NextPage = () => {
return (
<Container>
<Head>
<title>Create Next App</title>
<meta
name="description"
content="Generated by create next app"
/>
<link
rel="icon"
href="favicon.ico"
/>
</Head>
<Main>
<Title>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</Title>
<Description>
Get started by editing <Code bgColor="#fafafa">pages/index.js</Code>
</Description>
<Grid>
<Card href="https://nextjs.org/docs">
<h2>Documentation →</h2>
<p>Find in-depth information about Next.js features and API.</p>
</Card>
<Card href="https://nextjs.org/learn">
<h2>Learn →</h2>
<p>Learn about Next.js in an interactive course with quizzes!</p>
</Card>
<Card href="https://github.com/vercel/next.js/tree/master/examples">
<h2>Examples →</h2>
<p>Discover and deploy boilerplate example Next.js projects.</p>
</Card>
<Card href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app">
<h2>Deploy →</h2>
<p>
Instantly deploy your Next.js site to a public URL with Vercel.
</p>
</Card>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
href="https://github.com/mui/material-ui/tree/v5.10.8/docs/data/material/getting-started/templates/dashboard"
>
material-ui
</Button>
</Main>
<Footer>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<Logo>
<img
src="vercel.svg"
alt="Vercel Logo"
width={72}
height={16}
/>
</Logo>
</a>
</Footer>
</Container>
)
}
export default HomePage
そしたらyarn dev
でページを開いてみましょう!
このような画面が表示されれば完璧です!material-uiのボタンが追加されていますね!
手順⑧デプロイとテスト
この手順を終えるとコードがおかしくなっていないか。また、pushしたときに自動でデプロイしてくれる機能が付けられます!(簡単な設定が必要です)
今回はgithub pagesにデプロイできるようにします。
.github
ディレクトリを作成してください。
その中にdeploy.yml
ファイルとtest.yml
ファイルを作成し、以下を記述してください。
name: Deploy Next.js site to Pages
on:
push:
branches: ['master']
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
echo "::set-output name=manager::yarn"
echo "::set-output name=command::install"
echo "::set-output name=runner::yarn"
exit 0
elif [ -f "${{ github.workspace }}/package.json" ]; then
echo "::set-output name=manager::npm"
echo "::set-output name=command::ci"
echo "::set-output name=runner::npx --no-install"
exit 0
else
echo "Unable to determine packager manager"
exit 1
fi
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '16'
cache: ${{ steps.detect-package-manager.outputs.manager }}
- name: Setup Pages
uses: actions/configure-pages@v2
with:
static_site_generator: next
- name: Restore cache
uses: actions/cache@v3
with:
path: |
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Static HTML export with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next export
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: ./out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
次はテストファイルです。
name: Test
on: push
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: setup Node.js
uses: actions/setup-node@v1
with:
node-version: 18
- uses: actions/cache@v2
id: client-yarn-cache
with:
path: 'node_modules'
key: client-yarn-${{ hashFiles('yarn.lock') }}
- run: yarn install
if: steps.client-yarn-cache.outputs.cache-hit != 'true'
- run: yarn lint
- run: yarn typecheck
以上になります。これで必要なパッケージのインストールがまとめて完了したり、デプロイしたりの機能が出来ました!以上で設定は完了です!
追記
webpackとbabelをインストールした。手順はこちらを参照して下さい。
参考文献
https://zenn.dev/big_tanukiudon/articles/c1ab3dba7ba111/
https://mui.com/material-ui/getting-started/installation/
https://zenn.dev/jpn_asane/articles/d7f44682b74fdc/
https://prettier.io/docs/en/options.html/
https://tech.playground.style/javascript/babel-webpack/
Discussion