Blog

<Gulp+esbuild> webpackからesbuildに変更したら、爆速だった!

前提として、Gulpをメインにして、それにいろいろ付け足す形で、納品形態に合わせてWebサイトを制作しています。

たまにバージョンアップしたときにいろいろ悩まされながらも、自由度が高くてパッケージの豊富なGulpには、いろいろとお世話になっております。

JavaScriptは長らくwebpackを使ってビルドしていました。
Gulpでwebpackを動かすという仕組みです。モジュールを使うのが必須になってきているので、その時々でメンテしながら頑張ってきました

…が、

ビルドが遅い。

一度の保存で、生成されるのに10秒くらいかかります。
JSを書くモチベーションがだんだん下がってくるほどに遅い。

最近は、HTMLファイルでパッケージをCDNで読み込んで、そのHTMLファイルに<script>で書き込んでテストしてから、OKならJSファイルに移し替えるみたいなことをし始めてました。(末期…)

esbuildは、実はちょっと前から知ってて、一度取り入れようとしたのですが失敗。

webpack.config.jsesbuild-loaderを指定するだけで行けるんかな…と思ってやってみたのですが、ダメでした。
内部的にどうなっているのか、適用されてるのかはわからないですが、遅いまま。

その時は諦めましたが、もうそんなこと言ってられないくらい気になってきたのでようやく腰を据えてやってみました。

Gulp+esbuildの記事はまだ少ないと思うので、興味ある方の参考になればと思います。

ちなみに、esbuildはes5には対応していません。
また、CSSモジュールも対応していません(2022/2/10現在)。今の所、エントリポイントのapp.jsを生成すると、app.jsが参照するすべてのCSSファイルを含むapp.cssが生成されるという形です。jsファイルにバンドルされるようになってくれたら嬉しいのですが…、一応ロードマップにはあるようです。

https://esbuild.github.io/content-types/#css

使用するパッケージはgulp-esbuild

gulp用パッケージのgulp-esbuildというものがあるので、これを使います。

インストールは、npmなら

npm install gulp-esbuild

yarnなら

yarn add gulp-esbuild

gulpfile.jsに追記

関係あるところだけ記載しています。

const gulpEsbuild = require('gulp-esbuild')

〜〜省略

const esbuild = () => {
  return gulp.src(baseDir + '/js/app.js')
    .pipe(gulpEsbuild({
      bundle: true,
      outfile: "bundle.js",
      minify:true,
      target: [
        'es2020',
      ],
      platform:'node'
      // sourcemap: true,
    }))
    .pipe(gulp.dest(dist + '/js/'))
    .pipe(browserSync.stream());
}

// watch
const watch = () => {
  〜〜省略
  gulp.watch(baseDir + '/js/**/*.{js,ts}', gulp.series('esbuild'));
};

gulp.task('esbuild', esbuild);

exports.default = gulp.parallel('watch', 'browser-sync');

エントリポイント

gulp.src(baseDir + '/js/app.js') のところで、エントリポイントを指定します。
esbuildのマニュアルでは、オプションでエントリポイントが指定できるとあるのですが、そちらでエントリポイントをentryPoints: ['/js/app'],のように設定すると、一つしか指定してないのに複数扱いになり、

error: Must use "outdir" when there are multiple input files

とエラーが出てしまいました。
エントリポイントが一つの場合は、srcに指定するとうまくいきます。

各オプションについて

オプション名設定した値説明
bundletrueファイルをバンドルするかどうか
(デフォルトはfalse)
outfile'bundle.js'アウトプットするファイル名
minifytrue最適化するかどうか
target['es2020'],生成されるJavaScriptおよび/またはCSSコードのターゲット環境を設定
platform'node'-

targetを指定しないと、コンパイル時に下記エラーが出ます。

Transforming const to the configured target environment ("ES5") is not supported yet

「constを構成済みのターゲット環境(「ES5」)に変換することはまだサポートされていません」と、constを使った箇所に出てしまいました。

デフォルトは一応esnextのはずなのですが…

デフォルトのターゲットはesnextで、esbuildはデフォルトで最新のJavaScriptとCSSの機能がすべてサポートされていると見なすという意味です。

https://esbuild.github.io/api/#target

何故なのかわからないですが、targetは指定しないとだめでした。

また、今回追加しませんでしたが、ソースマップも追加できます。

sourcemap: true,

こうすると、アウトプットされたファイルと同じディレクトリにソースマップファイルが吐き出されます。

まとめ

esbuildが、ES6をES5に変換したりすることは今後もなさそう(予想)なので、IE11対応が必須の場合は、その時だけwebpackの設定に戻そうと思います。

それにしても速い。

おすすめの記事 recommend blog

新着 new blog

github