Parcel使ってみようかなと思った件
普段はgulp + Webpackを使っているのですが、1年とちょっと前くらいにParcelがいいかも! と思いつつ、ファイル名にハッシュがつくことが嫌でそれを解決できずにクライアントワークでのParcelの利用は諦めていました。
※ハッシュがつくのは差分の確実な反映のためらしいので一概に悪いとは言わない。ただ、クライアント側にエンジニアがいて運用時に差し替えるということが多いので個人的にはダメというだけ。
Parcel 2 RC
つい先日、2021/8/3付けのブログでV2RCのリリースが発表されていました。
その中でおっ! と思った機能をご紹介します。
type=”module”属性
モダンブラウザでサポートされている
type="module"属性を、この属性を入れるだけで出しわけます。
type=”module”及びnomoduleがサポートされていればtype=”module”のみを読み込み、サポートされていなければ未知の属性type=”module”のscriptを無視してnomoduleのscriptだけを読み込む、という挙動になります。
polyfill.ioで必要あるブラウザだけ読み込むということをしていたのですが、同じくらい楽ですね。むしろpolyfill.ioで必要なpolyfillを選ぶ必要がない分楽かも。
パラメータで画像の変換
画像読み込みの際、クエリパラメータを付けるとwebPへの変換、またサイズや画質の変換などができます。
gulpでは画質を落としてサイズを小さくするタスクとwebP変換のタスクを作っていましたが、それだと変換が必要ないものも変換して納品時にチマチマ消すか、変換が必要ないもの用のディレクトリを別で作ったりしていました。でもこれなら、webP変換したいファイルだけにクエリパラメータを付けるだけで必要なファイルのみを変換&呼び出すことができます。
クエリパラメータの一覧
クエリパラメータ | 内容 | 例 |
---|---|---|
width | 幅を起点にリサイズ | ?width=300 |
height | 高さを起点にリサイズ | ?height=300 |
quality | 画質を指定(単位は%) | ?quality=80 |
as | 画像のタイプを変換 | ?as=webp |
picture要素をいつもpugのmixinに入れて使いまわしているのですが、今後もいい感じに使い分けれそうでGood。
画像に関しては、いつもファイル名変更などで読み込まないゴミファイルを大量に作ってしまうので、読み込んでいなければdistに入らないというのもポイント高い。
キャッシュ
全てのファイルパスがプロジェクトルートを起点とするようになったため、コンパイル時のキャッシュがさらによくなったとのこと。
プロジェクトを複製してもキャッシュがそのまま使えるらしいので、たとえばgitに.parcel-cacheディレクトリを上げれば次にクローンするひとは最初から高速ということかと思います。引継ぎならそれでいいだろうけど同時に別ファイルを開発してる場合も大丈夫なのだろうか。試していないので、知っている方がいたら教えてください。
でもキャッシュなくてもそんなに遅いと思わないので複数で同時に開発する場合にはキャッシュディレクトリは別に共有しなくてもいいのではと思う。
ハッシュ問題
前述のとおり、私は個人的にファイル名にハッシュをつけてほしくありませんでした。
そこで、見つけました、プラグイン…! parcel-namer-customです。
parcel-namer-rewriteというparcel-namer-customより1ヶ月早く公開されているプラグインもあって、正規表現が使えて詳細に指定できてよさそうだったのですが、ドキュメントの通りに指定してもエラーが起きるため諦めました。
インストール
yarn add -D parcel-namer-customでインストールします。
.parcelrc
.parcelrcに
"namers": ["parcel-namer-custom", "..."],を追加します。
.parcelrcを作っていない場合は、下記のように継承元を入れることでnamersだけを上書きできるようです。
1 2 3 4 |
{ "extends": "@parcel/config-default", "namers": ["parcel-namer-custom", "..."], } |
package.json
続いて、package.jsonに命名規則を追加します。その際、キーは、バンドルのファイルパスと一致する正規表現で、値は下記のファイル名テンプレートを使います。
出力例は、/src/assets/css/index.scssというファイルに対してルールを設定した場合にどういうファイル名/ディレクトリで出力されるかの例です。
テンプレート | 内容 | ルール例 | 出力例 |
---|---|---|---|
[dir] | プロジェクトルート基準のパス*1 | ".scss": "[dir]/style.css" | /dist/src/assets/css/style.css |
[folder] | ファイルが入っているフォルダ名 | ".scss": "[folder]/style.css" | /dist/css/style.css |
[base] | 拡張子を含むファイル名 | ".scss": "[base]" | /dist/index.scss |
[ext] | 入力ファイル(コンパイル前)の拡張子 | ".scss": "style.[ext]" | /dist/style.scss |
[name] | 拡張子を含まないファイル名 | ".scss": "[name].css" | /dist/index.css |
[type] | 出力ファイル(コンパイル後)の拡張子 | ".scss": "style.[type]" | /dist/style.css |
[hash] | ハッシュ | ".scss": "style.[hash].css" | /dist/style.e0ca0996.css |
[N] | 正規表現により合致したN個目の値 | 別表参照 | 別表参照 |
*1 ドキュメントには[path]とあるが、[dir]のようです。参考サイトによるとソースコードを見た方が確実とのこと。
[dir]だとsrcまで入ってしまうが、[folder]だと階層が深いとディレクトリ構成を保持しない。
ルート直下だけ除いてほしいので、[N]が使えるということは正規表現が試せるのではと思い試した結果、[N]の出力テスト結果一覧は下記のようになりました。
テンプレ | 入力ファイル | 出力ファイル |
---|---|---|
"src/(.*)/*.pug": "[0]/[name].[type]" | /src/index.pug | /dist/index.html |
"src/(.*)/*.pug": "[0]/[name].[type]" | /src/subdir/index.pug | /dist/subdir/index.html |
"src/(.*)/*.js": "[0]/[name].[type]" | /src/assets/js/index.js (両方のpugファイルから呼び出し) |
/dist/subdir/index.38b39b6e.js |
"src/(.*)/*.scss": "[0]/[name].[type]" | /src/assets/css/index.scss (両方のpugファイルから呼び出し) |
/dist/index.51d7c8a0.css |
pugだけ期待通りの挙動となりました。JSとCSSを同じように呼び出しているのに出力先ディレクトリが変わるのも何故なのか……。
というわけで、私の個人的な設定は下記のようになります。
1 2 3 4 5 6 |
"parcel-namer-custom": { "src/pug/(.*)/*.pug": "[0]/[name].[type]", ".(js|es6)": "assets/[folder]/[name].[type]", ".scss": "assets/[folder]/[name].[type]", ".(jpg|gif|png|webp|svg)": "assets/img/[folder]/[name].[type]" } |
ディレクトリ構成はこんな感じです。
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 |
// 入力ファイル /src /pug index.pug /subdir index.pug /js index.js /css index.scss /img /common img.png // 出力ファイル /dist index.html /subdir index.html /assets /js index.js /css index.css /img /common img.png |
今後、使えそうな案件があれば使ってみたいと思います。
参考サイト
[Parcel] hashなしファイルを生成する – kokhlog.