Next.js x ReScript
ReasonMLを利用するNext.jsのサンプルを利用
yarn create next-app --example with-reasonml with-reasonml-app
ライブラリをupgrade
yarn upgrade bs-platform@^9.0.2 reason-react@^0.9.1 react@^17.0.1 react-dom@^17.0.1
サンプルをコマンドで作った時はパッケージのバージョンが古いので更新する。
ReasonML -> ReScriptに変換
for f in pages/**/*.re; do; node_modules/.bin/bsc -format $f > ${f%.re}.res && rm $f; done;
for f in components/**/*.re; do; node_modules/.bin/bsc -format $f > ${f%.re}.res && rm $f; done;
for f in bindings/**/*.re; do; node_modules/.bin/bsc -format $f > ${f%.re}.res && rm $f; done;
で一括でReasonML形式(.re)からReScript形式(.res)に変換できる。
動作確認
以下の二つをそれぞれ別のターミナルタブ/ウィンドウで実施
yarn dev:reason
yarn dev: next
tailwind
TailwindはCSSフレームワークの一つで、Next.jsで利用する方法が公式に載っているので概ね従う。
install
yarn add --dev tailwindcss@latest postcss@latest autoprefixer@latest
yarn tailwindcss init -p
Next.jsで読めるようにする
@tailwind base;
@tailwind components;
@tailwind utilities;
import '../styles/main.css'
export default function MyApp({ Component, pageProps }) {
return(<div>
<Component {...pageProps} />
</div>);
}
module.exports = {
purge: [
'./pages/**/*.res',
'./components/**/*.res',
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
memo
_app.res
から変換できないの?と思うが、
bsconfigでsuffix
を.bs.js
にしているので_app.res
を書いても_app.bs.js
にしかならない。
suffix
を書き換えれば.js
を出力することもできるが、.bs.js
が強く推奨されている。
また、スプレッド演算子...
の利用が推奨されていない。
Props Spread
You can't.
cloneElementを利用することで、回避を試みる。
%raw(`require("../styles/main.css")`)
let make = (~component, ~pageProps) => ReasonReact.cloneElement(
component,
~props=pageProps,
[]
);
let default = make
が出て, global CSSが読み込めるのはどうあがいてもpages/_app.js
だけという事実は揺るがないとわかる。
ただ、上記のファイルのようにしてsuffixを.js
にしても動かなかったので、書き方が間違えている可能性がある[調査中]
_app.res
の例もDestructuringになってないし。
まぁ、_app.jsぐらいJavaScriptでもええじゃろ。
動作確認
Headerを以下のように変更する。外側のclassNameborder-b bg-white py-2 md:py-4
でtailwindを利用している。
@react.component
let make = () =>
<nav className="border-b bg-white py-2 md:py-4">
<div>
<Next.Link href="/">{ReasonReact.string("Home")}</Next.Link>
<Next.Link href="/about">{ReasonReact.string("About")}</Next.Link>
</div>
</nav>
let default = make
#ちなみに
yarn dev~
のところでbsbのエラーが出た場合は以下のスクリプトを実行するとと直ることがある。
touch ./node_modules/bs-platform/index.js
sed -i -e 's/^{$/{\n "main": "index.js",/g' ./node_modules/bs-platform/package.json
vercelにデプロイする場合はOVERRIDEを設定し、このスクリプトをbuildコマンドに含める。
./first.sh && yarn build
Future works
re-tailwindを用いて型を利用した設定が可能?
少し試した感じでは動かなかったので要調査。
追記
rescript用のreactライブラリがあったので、そちらを利用する。
ReasonReact -> RescriptReact
yarn
yarn remove reason-react
yarn add @rescript/react
migration
- "bs-dependencies": ["reason-react"],
+ "bs-dependencies": ["@rescript/react"],
- <Next.Link href="/">{ReasonReact.string("Home")}</Next.Link>
- <Next.Link href="/about">{ReasonReact.string("About")}</Next.Link>
+ <Next.Link href="/">{React.string("Home")}</Next.Link>
+ <Next.Link href="/about">{React.string("About")}</Next.Link>
その他の場所についても、ReasonReact.string
をReact.string
に置き換える。
他の表現についても、ライブラリのドキュメントに記載されているので確認されたし。
- "dev:reason": "bsb -clean-world -make-world -w",
+ "dev:rescript": "bsb -clean-world -make-world -w",
package.json
については変えなくても大丈夫だが変えたくなる。
#参考文献
Next.js - Example app using ReasonML & ReasonReact components
ReScript - Migrate from BuckleScript/Reason
ReScript Forum - Purpose, alternatives to next-transpile-modules in next ReScript projects
Tailwind CSS - Install Tailwind CSS with Next.js
ReScript - Configuration - suffix
ReasonReact - Props Spread
ReasonReact - cloneElement
ReScript - Destructuring
re-tailwind
rescript-react
ReScript - rescript-react - Migrate from ReasonReact