Snowpack+React+Typescriptを公式手順でinitする
趣味でVueを触っている筆者がReactに入門してみたので、調査・実施した初期構築のメモです。
最初はスタンダードにcreate-react-app
していたのですが、Vueのviteのスピード感を体験していたためwebpack環境に我慢できず、snowpackを使うことにしました。
参考までに、以下の内容を実施したリポジトリです: https://github.com/cumet04/snow-react-ts-init
はじめに; 参考
本記事と同様にSnowpack + React + Typescriptな環境を作る記事として
などがあり、これらでは利用するreactパッケージの指定やimportパス、babelのプラグインなどを設定していますが、本記事執筆時点ではsnowpack公式のCreate Snowpack App (CSA)が存在しており[1] [2]非常に簡単に入門できるようになっています。
初期公開後追記:
上記参考記事はSnowpack v1の頃の話で、本記事で対象にしているCSAはSnowpack 2.0のリリースとともに公開されたもの、ということのようです。
また本記事ではSnowpackとはなにか・そもそも何をしているのか等は一切気にせずスッとinitするだけに留まるため、そのあたりの背景が気になる方は上記参考記事、また後者の筆者の方が2.0について書かれた下記を参考にするとよいと思います。
ひとまずinitする
Create Snowpack Appを使ってプロジェクトを作成します。
公式手順の通りですが、ここではReact + Typescriptなので以下のようになります:
npx create-snowpack-app {プロジェクト名} --template @snowpack/app-template-react-typescript
実行すると
- カレントディレクトリに
{プロジェクト名}
のディレクトリが作成される - 上記ディレクトリ下にテンプレート一式が展開され、initial commitが打たれる
-
npm install
が実行される
状態になります。
作成されたディレクトリ下でnpm start
するとsnowpackのdevサーバが起動します。
なお、この時点で何もせずともHot Reloadが有効です。src/App.tsx
あたりを編集すると即時反映されるかと思います。
TypeScriptについて
create時にテンプレとしてtypescriptを指定しておけば、特に何もせずとも.ts
(.tsx
)が使えます。
本記事はタイトルにTypescriptと入っていますが、特別な操作は不要なためこれ以降tsの話はありません。
またdevサーバ実行時やビルド時にはtsc --noEmit
が走るようになっており、型チェックの面でもデフォルトのままで安心です。
(一部WSLユーザのみ)devサーバが起動するようにする
筆者がそうなのですが、WSLユーザかつWSL内のPATHにWindowsのもの含めないようにしていた場合、この初期状態ではdevサーバが起動しません。
これはcreate-react-appと同じ問題で、あちらでは起動コマンドにBROWSER=none
を足すと解決するのですが、snowpackの場合は起動コマンドに--open none
を足すことで解決できます。
{
"scripts": {
- "start": "snowpack dev",
+ "start": "snowpack dev --open none",
"build": "snowpack build",
"test": "jest",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
commit: https://github.com/cumet04/snow-react-ts-init/commit/f0561178cf73f0da0fc43822439d581f86bb3a38
postcssを動かす
プロジェクト内のcssでPostCSSが機能するようにします。
公式手順の通りなのですが、postcss-cli
パッケージの追加・snowpack.config.json
への追記を行えばよいです。
postcssの設定は特に特殊なことはなく、postcss.config.js
でもpackage.json
でも好きなところに記述できます。
{
"extends": "@snowpack/app-scripts-react",
- "scripts": {},
+ "scripts": {
+ "build:css": "postcss"
+ },
"plugins": []
}
下記commitでは、動作テストとしてpostcss-nesting
を追加しApp
のcssを変更しています。
commit: https://github.com/cumet04/snow-react-ts-init/commit/ef9ba8f7513738362dc5204c29cf4ef852010483
CSS Moduleする
cssをscopedに書きたいのでCSS Moduleします。
こちらは特に作業は必要なく、ファイル名を変更してそのまま使えます。
commit: https://github.com/cumet04/snow-react-ts-init/commit/49684b94d31fd3b8940984519edd9f9f41a275e0
bundleなproduction buildする
snowpackはasset bundleを行わないため、デフォルトではproduction buildでも全ソースが別個のファイルになります。
bundleしたい場合、公式手順としてはwebpackを使うプラグインが提供されているため[3]、これを使います。
その場合は@snowpack/plugin-webpack
をnpm install
しsnowpack.config.json
に下記追記します:
"scripts": {
"build:css": "postcss"
},
- "plugins": []
+ "plugins": [["@snowpack/plugin-webpack", {}]]
}
commit: https://github.com/cumet04/snow-react-ts-init/commit/92e15f7bba7b9c72e95c59594f94ca15b074136c
この状態でnpm run build
すると、bundleされた状態のビルドが出来上がります。
(おまけ)@octokit/request (node-fetch) を使う
別の個人プロジェクトで@octokit/restを使うとしたところ、node-fetch
パッケージのNode built-inパッケージの問題に当たりました。
通常、公式のトラブルシューティングにあるようにrollup-plugin-node-polyfills
を使うなどすればよいのかもしれませんが、この場合はrollupのplugin-node-XXX
を色々試しても解決できませんでした。
そこで「SPAだしブラウザでしか動かさないわけでnode-fetch使わず普通のfetchでよくない?」という発想の元、node_modules内の@octokit/request
のソースを直接書き換えることにしました。
#!/bin/bash
set -eu
cd $(dirname $0)/..
file="node_modules/@octokit/request/dist-web/index.js"
before=$(cat $file)
sed -i 's|^import nodeFetch|//import nodeFetch|' $file
sed -i 's|^\s*const fetch|//const fetch|' $file
# display changed lines
echo "$before" | diff - $file
commit: https://github.com/cumet04/snow-react-ts-init/commit/0aeb3d8449b65ce5c476abbffd65eb884fe82688
fetch
を使うところが抽象化されてまとまっていたため、node-fetch
のimportとfetch
の定義書き換え部分をコメントアウトするだけとなっています。
ゴリ押し解決のためnode-fetch
以外のNode built-inパッケージ問題には適用できませんが、同じようなハマり方をしているかたの参考になれば。
※もっと真っ当な方法で対応&実際に動作する方法があればご教示いただけると。。。
まとめ
基本的なところは公式が提供してくれており、ぶっちゃけ公式ドキュメントの紹介みたいになってしまいました。
まだこれでちゃんとしたプロダクトを書いたわけでは全くなく、特殊なユースケースでは難しいこともあるかもしれませんが、これらの基本的なところは安心の公式手順で楽しめそうです。
-
create-snowpack-appのinitial commitは4/22となっており、参考記事執筆時には存在しなかったようです ↩︎
-
後日追記: Snowpack 2.0としてCSAが公開されたかたちなのですが、初期執筆時に筆者がそのあたりの経緯を知らなかった(CSAがおもむろに登場したと思っていた)ため文章の表現に少し違和感があるかもしれません ↩︎
-
公式サイトではなくCSAのリポジトリによるとparcelでbundleするプラグインも提供されているようです ↩︎
Discussion