Snowpack に入門してみる
Snowpack + React + TypeScript に入門してみました。
create-snowpack-app
は使わず、全部マニュアルでやっていきます。
Snowpack に入門することがメインなので作成する web ページは簡素なものです。
基本的に公式ドキュメントを参考に進んでいきます。
最終的に作られたものはこちらです↓
Snowpack のインストール
project ディレクトリ (今回は learn-snowpack
) を作成し、npm init -y
を実行して package.json
, package-lock.json
を作成、
npm i --save-dev snowpack
でインストールします。
npm run-scripts を追加
package.json の scripts
フィールドに start
と build
を追加します
"scripts": {
"start": "snowpack dev",
"build": "snowpack build"
},
-
start
はローカルで開発用の dev server を起動します。プロジェクトルート下のindex.html
を探してそれをエントリーポイントとします。(ルート以外に置く場合は別途mount
設定が必要です。) -
build
は production 用のファイルを生成します。
snowpack.config.js の作成
先述の通り、プロジェクトルート以外に index.html
を置く場合は mount
設定を行う必要があります。今回は public/index.html
をパスとするのでその設定を行います。
module.exports = {
mount: {
public: { url: '/', static: true }
}
};
mount
は [path: string]: string | {url: string, static: boolean, resolve: boolean}
の形式で記述します。
ドキュメント
- Key (
[path: string]
) には対象とするディレクトリ名を指定 - Value (
string | {url: string, static: boolean, resolve: boolean}
) にはマウント先のディレクトリ名を指定するか、オブジェクトの形で指定します-
url
: マウント先ディレクトリ名を指定 -
static
(default:false
): true の場合は、このディレクトリ下のファイルはビルドされません -
resolve
(default:true
): false の場合は、JS、CSS、および HTML ファイル内の JS および CSS のインポートを解決せず、すべてのインポートを書かれたとおりにブラウザに送信します。(正直よくわかってない)
-
今回は public
ディレクトリをルートディレクトリにマウントしたいため url
には '/' を指定しています。また、public
ディレクトリ下には HTML 等のビルドを必要としないファイルを置くため static
を true
にしています。
また、このあと作成する TypeScript や CSS ファイルの置き場所である src
ディレクトリの mount
設定もしておきます。
module.exports = {
mount: {
public: { url: '/', static: true },
src: '/dist'
}
};
src
ディレクトリの方は単にマウント先として /dist
を設定したいだけなのでこれでOKです。
ちなみに、js ファイルもルートディレクトリにマウントしたい場合は src: '/'
と書くことで設定可能です。
public/index.html の作成
React を使うときによくやる HTML をとりあえず作って public/index.html
として保存します
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>learn snowpack</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/index.js"></script>
</body>
</html>
ここで重要なのは <script type="module" src="/dist/index.js"></script>
の部分です。
script
タグに type="module"
を指定しています。
これによりブラウザにこのファイルがモジュールであることを宣言し、 import
や export
が使えるようになります。
src/index.tsx の作成
まだ react
と react-dom
、 typescript
及び型ファイルをインストールしていなかったのでインストールしておきます。
$ npm i react react-dom
$ npm i --save-dev typescript @types/react @types/react-dom
tsconfig.json も作ります
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"jsx": "preserve",
"noEmit": true,
"skipLibCheck": true,
},
"include": ["src"]
}
続いて TypeScript のファイルを作っていきます
import React from 'react';
import { render } from "react-dom";
const App = () => {
return <h1>Learn snowpack.</h1>;
};
render(<App />, document.getElementById("root"));
これで準備完了です。
npm start
を実行して dev server を起動してみましょう。
自動でブラウザでページ表示され「Learn snowpack.」と表示されます。
スタイルを当てる
CSS も適用していきます。
そういえば CSS Module
が State of CSS 2020 で満足度1位 だったので使っていきましょう。
Snowpack で CSS Module を使用するためには CSS のファイル名を [name].module.css
とする必要があります。(ドキュメント)
src/index.module.css
を作成します。
.text {
color: red;
}
src/index.tsx
から CSS を読み込んでスタイルを当てます。
import React from 'react';
import { render } from 'react-dom';
// 追記
import styles from './index.module.css';
const App = () => {
return (
<div>
{/* className={styles.text} を追加 */}
<h1 className={styles.text}>Learn snowpack.</h1>
</div>
);
};
render(<App />, document.getElementById('root'));
このままだと CSS の import 時に TypeScript がエラーを吐いてくるのでそれを解決します。
このエラーはモジュール index.module.css
の型ファイルが見つからないことが原因なので、型ファイルを作ってやります。
types/css.d.ts
を作成します。
declare module '*.css' {
const classNames: { [className: string]: string };
export default classNames;
}
TypeScript にこの型ファイルを認識させるために tsconfig.json を編集します
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"jsx": "preserve",
"noEmit": true,
"skipLibCheck": true,
"typeRoots": ["node_modules/@types", "types"]
},
"include": ["src", "types"]
}
compilerOptions.typeRoots
の追加と include
に types
を追加しました。
これで .css
という拡張子がつくモジュールの型宣言ができました。
それでは、npm start
で起動している開発環境を見に行くと「Learn snowpack.」の色が赤くなっています。
無事にスタイルを当てることができました。
画像を表示する
ついでに画像も表示してみましょう。
snowpack 公式から配布されているロゴ を使用させていただきます。
snowpack-logo-dark.png
と snowpack-wordmark-black.png
をそれぞれ src/images
ディレクトリに配置します。
src/index.tsx
から画像を読み込んで配置します。
import React from 'react';
import { render } from 'react-dom';
import logo from './images/snowpack-logo-dark.png';
import wordmark from './images/snowpack-wordmark-black.png';
import styles from './index.module.css';
const App = () => {
return (
<h1 className={styles.text}>
Learn <img className={styles.logo} src={logo} />
<img className={styles.wordmark} src={wordmark} />
</h1>
);
};
render(<App />, document.getElementById('root'));
CSS のときと同様に、import 時にエラーが出ているので types/image.d.ts
を作成します。
declare module '*.png';
declare module '*.jpg';
declare module '*.svg';
そのまま表示すると画像が大きすぎるので適当に大きさを整えます。
.text {
color: red;
}
.logo {
width: 1em;
}
.wordmark {
width: 3.2em;
}
開発環境を見ると以下のようになっていると思います。
表示イメージ
まとめ
Snowpack + React + TypeScript の入門を簡単にやってみました。
Webpack に比べていろんな loader とか babel とか使用せずに使用できるのは良いですね!
今回はただ文字と画像を表示するだけのものだったので Snowpack の持ち味である Unbundled development の恩恵が少なかったり、 HMR + Fast Refresh の設定等はしなかったのですが、大きな web アプリケーションを作成していくとき楽しみです。
Discussion