next.jsはnowと合わせると秒単位でWEBアプリを公開できるような超速フレームワークですが、それなりの規模のものを作ろうと思うと色々設定が必要です。
大分慣れてきたので振り返りもかねてプロジェクト初期設定の備忘録。
プロジェクト作成からGit設定、各種コンフィグ類の設定、必須ライブラリの導入とカスタムページの用意まで。
初期設定
プロジェクトの作成
コマンド1つで初期設定済みのフォルダを作ってくれます。
これは本当に便利なのでちょっとReact試したいときにも重宝します。
1 |
> npx create-next-app projectName |
色々と自動作成してくれますが、個人的にはsrc/
を作成してcomponents/
とpages/
はそこに入れたい。
Gitの設定
上の操作でプロジェクトではローカルリポジトリが出来てるのでBitbucketやらgithubなんかにつなぐ。
1 2 3 |
git remote add origin https://github.com/user/someProject.git git fetch && git merge origin/master --allow-unrelated-histories origin/master git push -u origin master |
やってることは以下の通り。
- リモートリポジトリをoriginにする
- (READMEなど作っていたら)リモートリポジトリの情報をとってきてマージ
- origin/masterを既定にしつつプッシュ
コンフィグ
Next.jsのポート番号設定でやったようにポート番号指定を行います。windowsなので%%
にしてますがUnix系なら$npm_package_config_PORT
です。
1 2 3 4 5 6 7 8 9 10 11 |
{ ... "scripts": { "dev": "next dev -p %npm_package_config_PORT%", "build": "next build", "start": "next start -p %npm_package_config_PORT%" }, "config": { "PORT": 8008 } } |
ついでに処理中で使う環境変数なんかも設定する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const { PHASE_DEVELOPMENT_SERVER } = require("next/constants"); const PROD_URL = "https://xxx.yyy.zz"; module.exports = phase => { const DEV = phase === PHASE_DEVELOPMENT_SERVER; const PORT = process.env.npm_package_config_PORT || 3000; return { distDir: "build", env: { PORT, DEV, BASE_URL: DEV ? `http://localhost:${PORT}` : PROD_URL } }; }; |
process.env.BASE_URL
などが処理で使えます。
ライブラリの追加
フレームワーク
新規でフレームワークを使わずデザインを作るのは苦行です。
個人的にはBootstrapが好き※なのですがReactとは主にjQuery部分で相性が悪い。
依存のないReact Bootstrapなんてのもありますが、色々と悪いとこどりしているようで正直使いにくいように感じます。
※Bootstrap臭がするなどと言われがちですがそれだけ使われているということだと思います。
ReactといえばMaterial uiといっても過言ではないらしいので本体、アイコン、テーブルライブラリ※を追加します。
※多少リッチなテーブルを使うならライブラリを使うことになると思う。
1 |
> yarn add @material-ui/core @material-ui/icons material-table |
Typescript
基本的にjavascriptの自由度(という名の闇)を取り払うTypescriptは好きではないですが、Reactに関しては使わざるを得ない※感じがします。
※現状の私だとPros/Consが拮抗してますが、もっと習熟すればメリットの方が大きくなるはず。
1 |
> yarn add --dev typescript @types/react @types/react-dom @types/node |
tsconfigをサンプルのwith-typescriptからとってきます。
そこに好きなパスを設定するためにbaseUrl
とpaths
を追加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
{ "compilerOptions": { "allowJs": true, "alwaysStrict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "jsx": "preserve", "lib": ["dom", "es2017"], "module": "esnext", "moduleResolution": "node", "noEmit": true, "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "esnext", "baseUrl": ".", "paths": { "~*": ["./src*"], "@src*": ["./src*"], "@components*": ["./src/components*"], "@contexts*": ["./src/contexts*"], "@data*": ["./src/data*"], "@libs*": ["./src/libs*"], "@server*": ["./src/server*"] }, }, "exclude": ["node_modules"], "include": ["**/*.ts", "**/*.tsx"] } |
この辺の設定はのちに必要に応じてググりつつ変えていくことになります。
paths
は相対パス以外でモジュールの指定をするために必須(ないとCannot find module : ts(2307)
)ですが、最終的な解決をしてくれるものではないのでこれだけ定義しても意味はないです(次のBabelも参照)。
Babel plugin
絶対パスや指定パスでモジュールを読み込めるようにプラグインを追加します。
階層が深くなると相対パスでimport
するのが面倒になるのでわりと重要です。
またサーバーをそのまま使う場合、pages/
内がそのままルーティングになるため配置換えしたくなる状況が多々ありますが、その時の面倒さが全く違います。
typescriptでエイリアスを設定しましたがそれだけだとコンパイルできる(Typescriptでエラーが出ない)だけで実行はできません。さらにいえばjsで作るならこっちの設定だけでいいです。
1 |
> yarn add --dev babel-plugin-module-resolver |
.babelrcを作成してコンポーネントなどをエイリアス設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{ "presets": ["next/babel"], "plugins": [ [ "module-resolver", { "root": ["."], "alias": { "~": "./src", "@src": "./src", "@components": "./src/components", "@contexts": "./src/contexts", "@data": "./src/data", "@libs": "./src/libs", "@server": "./src/server" } } ] ] } |
これでimport xx from "src/components/xx";
やimport yy from "@libs/yy";
のように書けて、深い階層からひたすら../
する人生からおさらばできる。
root
を設定しているのでsrc/components/xxx
とかでインポートできるんですが、node_modules
や他フォルダとの兼ね合いとかでModule not found
となることがあるのでエイリアスを使ってインポートする方がよさそう。ライブラリと被らないような特殊なパスだと分かりやすいですし。
src
直下のフォルダ(pages/
以外)をパッケージ名と被らないようにして@
を付けるのが今のところ使いやすいです。
ページ設定
_document.js
Material UI関連の諸々を書いておきます。
詳細はNext.jsで外部ライブラリのスタイルシート適応で。
この他にもベースをいじりたくなることはあると思うので_document.js
は必須。
_app.js
使わなくてもいいけど共通レイアウトやcss normarizeに使ってみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import CssBaseline from "@material-ui/core/CssBaseline"; import Page from "@components/layout/page"; function MyApp({ Component, pageProps }) { return ( <> <CssBaseline /> <Page> <Component {...pageProps} /> </Page> </> ); } export default MyApp; |
getInitialProps
を使うと全ページでSSRがかかるためできれば使わない。
ここまでやった後、Pageレイアウトを作るところから開発を始めています。