このページの本文へ

webpackよりもシンプルで高速!最新モジュールバンドラー「FuseBox」超入門

2017年07月20日 15時00分更新

文●Feras Khoursheed

  • この記事をはてなブックマークに追加
本文印刷
SPAなどモダンな Web開発に欠かせないモジュールバンドラー。高速でシンプル、webpackに代わる次世代ツールとして注目の「FuseBox」の使い方を解説します。

急速に発展しているフロントエンドの環境は、JavaScriptのモジュールシステムの理解が必要不可欠です。モジュールを利用してコードを組織化することで、メンテナンス性と再利用性が向上します。残念ながら、ES modulesのブラウザーサポートはあまり進んでいないため、モジュールバンドラーでモジュールを1つのファイルにつなぎ合わせてブラウザーが扱えるようにする必要があります。

webpackはJavaScriptのデファクト・モジュールバンドラーになったとの意見がある一方で、分かりにくく、学ぶのが難しいとの評価もあります。本記事では、webpackの代替ツールで、より高速でシンプルなFuseBoxを紹介します。

FuseBoxは開発に必要なものをすべて提供する、次世代型のエコシステムを備えたツールです。FuseBoxはあらゆるファイル形式をバンドルでき、モジュールローダー、トランスパイラー、タスクランナーとして動作します。ほかにも多くの機能があります。

FuseBoxを使ってJavaScriptアプリケーションの開発における一般的なタスクを一通り実施します。具体的には次のとおりです。

本記事を読んで、次のプロジェクトにFuseBoxを投入し、その速さ、シンプルさ、柔軟性を感じてください。

注記:本記事の著者は、FuseBoxプロジェクトのコアコントリビューターの1人です。

バンドル:基本的な例

プロジェクトはますます大規模になり、Webページに必要なファイルをすべてインクルードすると、ブロッキング通信によるHTTPリクエストをブラウザーから何度も発行されて動作が遅くなります。ファイルをバンドルしてリクエストするファイル数を減らせば問題が解決しますが、大変です。FuseBoxなら、その処理を簡単にできます。

バンドルを開始するために必要なものをFuseBoxに設定します。FuseBoxは大規模なプロジェクトのバンドルでも設定が少なく、ほとんどのプロジェクトで10行設定するだけです。サンプルを作りましょう。

フォルダーを作成し、コマンドラインでファイルに移動し、npm init -yを入力してプロジェクトを初期化します。npm install fuse-box -Dを入力してFuseBoxを開発用依存オブジェクトとしてインストールします。

フォルダー「src」を作成してすべてのコードを格納します。srcフォルダーにindex.jsファイルを作成し、以下を追加します。

console.log('Hello world');

プロジェクトのルートにfuse.jsファイルを作成し、FuseBoxの設定をすべて格納します。

現時点のフォルダー構造は次のようになっているはずです。

MyProject
├── node_modules
├── src
│    └── index.js
├── fuse.js
└── package.json

fuse.jsに以下のコードを追加します。

const { FuseBox } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js"
});

fuse.bundle("app")
  .instructions("> index.js");

fuse.run();

コードをセクションごとに分解して解説します。

FuseBoxをrequireします。initメソッドでFuseBoxの新たなインスタンスを初期化します。これをFuseBoxの用語でProducerと呼びます。Producerには全バンドル用のグローバル設定を定義します。

FuseBoxが実際のファイル構造を模擬した仮想ファイル構造を作成するため、homeDirオプションでファイルのホームディレクトリを指定します。outputオプションでバンドルを出力する場所を指定します。$name.jsはプレースホルダーなので、バンドルに与える名前で置き換えられます。

fuse.bundle("app")はバンドルをFuseBoxに伝える命令です。プロジェクトのdistフォルダーにバンドル「app.js」の作成を指示しています。出力ファイルはproject/dist/app.jsです。

instructions('>index.js')でバンドル対象を指定します。>記号を算術命令と呼びます。算術命令はバンドルするファイルを指定するFuseBoxの言語です。

fuse.run()でバンドル処理を開始します。

コマンドラインにnode fuse.jsを入力すれば完了です。FuseBoxがバンドルの魔法を使ってdist/app.jsにバンドルを作成します。

完成したサンプルはこちら

TypeScriptとES6のトランスパイル

FuseBoxの素晴らしい機能を紹介しましたが、モダンJavaScriptプロジェクトではあまり使われません。最近のアプリケーションは、ECMAScriptの6回目のメジャーリリース「ES6」で開発します。ES6はクラスアロー関数など新たな言語機能を持つ優れた仕様ですが、ES6を完全にサポートしていないブラウザーやNode.jsのバージョンもあります。JavaScriptのコードを、広くサポートされているバージョン「ES5」にトランスパイルする必要があります。

よく使われるトランスパイルのツールはTypescriptとBabelです。FuseBoxは両方サポートしています。FuseBoxはTypescriptで作られているため、本質的にTypescriptをサポートしています。

FuseBoxとTypescriptを使う手順です。

  • 新たなプロジェクトを作成する
  • コマンドラインでプロジェクトのルートに移動し、npm init -yを実行する
  • srcフォルダーを作成する
  • srcフォルダーにindex.tsを追加する
  • プロジェクトのルートにfuse.jsを作成する
  • npm install fuse-box typescript -Dを実行し、FuseBoxとTypeScriptを依存オブジェクトとしてインストールする

index.tsに以下を追加します。

const name: string = "FuseBox";
console.log(name);

:string meansはTypescriptの型システムの一例です。コンパイラーに対し、name変数がstring型だと伝えています。Typescriptについて詳しく学びたい場合は公式サイトを確認してください。

fuse.jsに以下を追加します。

const { FuseBox } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js"
});

fuse.bundle("app")
  .instructions("> index.ts");

fuse.run();

内容は前回と変わらず、唯一の違いは、instructions('>index.ts').jsファイルフォーマットの代わりに.tsファイルフォーマットを使っています。

準備ができたので、コマンドラインからnode fuse.jsを入力すると、FuseBoxがバンドルを開始します。

完成したサンプルはこちら

補足:ES6の構文では、FuseBoxはモジュールタイプを自動的に検出しコードをシームレスにトランスパイルします。Babelは不要です。FuseBoxは最高です!

モジュールローディング

console.logを使った単純な例を扱ってきましたが、ここからは一歩進んでモジュールローディングを解説します。独立した再利用可能なコードの非連続的なユニットです。JavaScriptにはモジュールを作成する方法がいくつかあります。

FuseBoxはコードをバンドルしてCommonJSモジュール形式にします。ブラウザーはCommonJSをサポートしていませんが、心配不要です。FuseBoxが提供する包括的なAPIで、ブラウザーでも簡単にモジュールを利用できます。

TypeScriptのサンプルをベースにモジュールを作成します。TypeScriptなのでES6のモジュールシステムを使います。

srcフォルダーのindex.tsの隣にhello.tsを作成し以下を追加します。

export function hello(name: string) {
  return `Hello ${name}`;
}

index.tsに以下を追加します。

import { hello } from "./hello";

const name: string = `Mr. Mike`;
console.log(hello(name));

コマンドラインでnode fuse.jsと入力し、続いてnode dist/app.jsを入力します。コンソールに以下のように出力されます。

 Hello Mr. Mike

FuseBox、ES6、Typescriptで最初のモジュールを作成し、読み込むことに成功しました。

ローカルモジュールを読み込む方法は分かりましたが、FuseBoxは外部のNode.jsパッケージも扱えます。サンプルを拡張しMoment.jsをモジュールとしてインクルードする方法を解説します。

コマンドラインにnpm install moment -Sを入力します。このコマンドはMoment.jsパッケージをプロジェクトの依存オブジェクトとしてインストールします。以下をindex.tsに追加します。

import {hello} from "./hello";
import * as moment from "moment"

const time = moment().format('MMMM Do YYYY, h:mm:ss a');
const name: string = `Mr. Mike`;
console.log(hello(name));
console.log(time);

node fuse.jsを入力し、node dist/index.jsと入力します。コンソールに以下が出力されます(日付は異なります)。

Hello Mr. Mike
June 13th 2017, 11:50:48 am

完成したサンプルはこちら

プラグインの使用

すべてのユーザーの要望に応えられる機能を持ったツールは存在しません。独創的な機能を幅広く備えているFuseBoxも例外ではなく、開発者が優れたプラグインを作成し、FuseBoxのエコシステムを豊かにしています。

JavaScriptとTypeScriptで作業してきましたが、ここからは重要な2つのFuesBoxプラグインCSSPluginSassPluginを使います。

以下を実施します。

  • 新たなプロジェクトを作成する
  • コマンドラインを使ってプロジェクトのルートに移動し、npm init -yを実行する
  • srcフォルダーを作成する
  • srcフォルダーにindex.tsを追加する
  • srcフォルダーにmain.cssを追加する
  • srcフォルダーにextra.scssを追加する
  • プロジェクトのルートにfuse.jsを作成する
  • コマンドラインでnpm install fuse-box typescript node-sass -Dを実行し、FuseBox、TypeScript、SASSコンパイラーを依存オブジェクトとしてインストールする

extra.scssファイルにSassを書きます。ブラウザーはSassをネイティブサポートしていないので、FuseBoxのSassPluginを使います。fuse.jsを以下のように変更します。

const { FuseBox, CSSPlugin, SassPlugin } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js",
  plugins: [
    [SassPlugin(), CSSPlugin()],
    CSSPlugin()
  ]
});
fuse.bundle("app")
  .instructions(`> index.ts`);

fuse.run();

CSSPluginを2回繰り返していますが、これはプラグインチェイン(plugin chaining)と呼ばれるFuseBoxのコンセプトです。プラグインチェインはあるプラグインの結果を次のプラグインに渡せるようになる、重要なコンセプトです。

スタイルシートに中身を追加します。

main.cssに以下を追加します。

body {
  margin: 0;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  background: #ececec;
}

extra.scssに以下を追加します。

$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}

スタイルシートファイルをプロセスにインポートしてバンドルします。index.tsに以下を追加します。

import "./main.css";
import "./extra.scss";

document.body.innerHTML = `
<div class="content">
  <h1>Welcome to FuseBox!</h1>
</div>`;

FuseBoxは、ほかのソリューションとは違い、JavaScript以外のファイルを追加作業なしでインポートできます。上記の設定でFuseBoxがSassPluginを実行して、SassをCSSにコンパイルしmain.cssとextra.scssをバンドルできます。さらに、結果をプレビューするために、FuseBoxに標準搭載されたもう1つの優秀なプラグイン、WebIndexPluginを使います。

WebIndexPluginは、FuseBoxが開発者の作業を楽にする1つの例です。HTMLファイルを自動的に生成して、プラグインに任意のHTMLファイルを渡し、テンプレートとして使えます。もっとも重要な機能は、バンドルを自動でインクルードすることです。追加するバンドルを自分で考える必要がないのです。WebIndexPluginの恩恵は、ハッシュで詳しく説明します。

fuse.jsを修正します。

const { FuseBox, CSSPlugin, SassPlugin, WebIndexPlugin } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js",
  plugins: [
    [SassPlugin(), CSSPlugin()],
    CSSPlugin(),
    WebIndexPlugin({path: "."})
  ]
});

fuse.bundle("app")
  .instructions(">index.ts");

fuse.run();

コマンドラインでnode fuse.jsを実行すると、distフォルダーにindex.htmlが生成されます。ファイルを開くとページにCSSが適用されていると確認できます。

main.cssbackground: #ecececの行をbackground: blueに変えてください。コマンドラインでnode fuse.jsを入力し、ページを再読み込みすると、背景が青色になります。

コードを変更して結果を確認するときは、毎回node fuse.jsを入力します。賢い方法ではありません。解決するために、FuseBoxにはwatchメソッドが用意されています。watchメソッドは、ファイルの変更時、自動で再バンドルします。

watchメソッドをバンドルに追加します。fuse.jsを修正します。

const { FuseBox, CSSPlugin, SassPlugin, WebIndexPlugin } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js",
  plugins: [
    [SassPlugin(), CSSPlugin()],
    CSSPlugin(),
    WebIndexPlugin({path: "."})
  ]
});

fuse.bundle("app")
  .watch()
  .instructions(">index.ts");

fuse.run();

コマンドラインでnode fuse.jsを入力し、ファイルを変更します。node fuse.jsを入力しなくても、FuseBoxが自動で再バンドルします。

完成したサンプルはこちら

ホットモジュールリローディング(HMR:Hot Module Reloading)

HMRを使うと、FuseBoxがファイルの変更を検出しメモリ内のモジュールを更新します。つまり、ブラウザーの表示も自動で更新されます。強力な機能です。エディターとブラウザーを切り替えながらF5を押して変更を確認する作業は過去になりました。FuseBox HMRはJavaScriptファイルをはじめ、すべてのファイルが扱えます。コードを変更して保存すると、FuseBoxはプロジェクトを自動的に更新し、更新されたアプリケーションがブラウザーに表示されるのです。

FuseBox HMRに合わせて、FuseBoxに標準搭載されている開発用サーバーも紹介します。Expressを使ったアプリケーションで、ルーティングの作成やミドルウェアの追加などが可能です。詳しくはドキュメントを確認してください。

前回のサンプルをベースに、fuse.jsファイルを更新します。

const { FuseBox, CSSPlugin, SassPlugin, WebIndexPlugin } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js",
  plugins: [
    [SassPlugin(), CSSPlugin()],
    CSSPlugin(),
    WebIndexPlugin({path: "."})
  ]
});

fuse.dev();

fuse.bundle("app")
  .instructions("> index.ts")
  .watch()
  .hmr();

fuse.run();

2つの命令fuse.dev().hmr()を追加しました。これでHMRが有効になります。コマンドラインでnode fuse.jsを入力すれば、コンソールにserver running http://localhost:4444と表示されます。

これがプロジェクトにアクセスするためのURLです。http://localhost:4444/にアクセスし、CSSファイルまたはJavaScriptファイルを変更してください。再読み込みをしなくても、変更がブラウザーに反映されます。

完成したサンプルはこちら

内蔵タスクランナー・Sparky

ファイルのバンドルを解説しましたが、ほとんどのプロジェクトではフォルダーのクリーンアップやファイルのコピー、アプリケーションのバージョンを上げる作業などの「追加のタスク」が必要です。

FuseBoxは開発のに必要なものをすべて提供する、と書いたことを覚えていますか? FuseBoxにはタスクランナーの「Sparky」が標準搭載されています(より詳しい情報はこちら)。Sparkyは上で挙げた一般的なタスクも扱えますが、プラグインを使うと機能を拡張して、独自のタスクも扱えます。

前のサンプルをベースに、以下のタスクを作成します。

  • バンドル処理の開始時にdistフォルダーをクリーンアップするタスク
  • 画像ファイルを追加、編集、削除したときにsrcフォルダーから画像ファイルをコピーするタスク

fuse.jsを変更します。

const { FuseBox, CSSPlugin, SassPlugin, WebIndexPlugin, Sparky } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js",
  plugins: [
    [SassPlugin(), CSSPlugin()],
    CSSPlugin(),
    WebIndexPlugin({path: "."})
  ]
});

fuse.dev();

fuse.bundle("app")
  .instructions("> index.ts")
  .watch()
  .hmr();

Sparky.task("clean", () => {
  return Sparky.src("dist").clean("dist");
});

Sparky.task("watch:images", () => {
  return Sparky.watch("**/*.+(svg|png|jpg|gif)", {base: "./src"})
    .dest("./dist");
});

Sparky.task("default", ["clean", "watch:images"], () => {
  fuse.run();
});

変更点を解説します。

Sparkyrequireし、タスクを3つ作成します。defaultタスクはSparkyが使う「おまじない」で、node fuse.jsを入力したら自動的に実行されます。defaultタスクを定義している箇所にある["clean","watch:images"]Sparky実行フロー(Execution-flow)の一例です。

Sparkyには2つのモード「waterfallモード」と「parallelモード」があります。waterfallモードはタスクは順次実行します。つまり、watch:imagesタスクはcleanタスクが完了するまで実行されません。fuse.rundefaultタスクに移動したのも、ほかのタスクが完了したあとにバンドルを開始する必要があるためで、重要な変更点です。

2つ目のcleanタスクは単純です。cleanメソッドでdistフォルダーを削除します。

3つ目のwatch:imagesタスクは画像をコピーします。Sparky.watchはFuseBoxに標準搭載されているファイル監視メソッドで、フォルダー内に変更があると起動します。"**/*.+(svg|png|jpg|gif)" srcフォルダーの監視対象の画像ファイルフォーマットの一覧です。.destメソッドは変更されたファイルをすべてdistフォルダーにコピーします。

srcフォルダーに画像を追加してnode fuse.jsを実行します。Sparkyがdistフォルダー内のファイルをすべて削除し、srcフォルダーにある画像をすべてdistフォルダーにコピーします。srcフォルダー内の画像ファイルを編集してください。Sparkyのファイル監視が起動し、distフォルダーにコピーします。

完成したサンプルはこちら

ユニットテスト

テストはソフトウェアの品質を向上させるための強力なツールです。テストでバグが減り、ドキュメントが正確になり、デザインを改善できます。

FuseBoxにはテストランナーが標準搭載されています。バンドルに使うエンジンと同じエンジンで作られているため、スピード、キャッシュ、プラグインなど、FuseBoxの特長をすべて有しています。Typescriptを使うので、追加の作業は不要です。

以下を実施します。

  • 新たなプロジェクトを作成する
  • コマンドラインを使ってプロジェクトのルートに移動し、npm init -yを実行する
  • srcフォルダーを作成する
  • srcフォルダーにindex.tsを追加する
  • srcフォルダーにindex.test.tsを追加する
  • プロジェクトのルートにfuse.jsを作成する
  • コマンドラインでnpm install fuse-box fuse-test-runner typescript -Dを実行し、FuseBoxとTypeScriptを依存オブジェクトとしてインストールする

fuse.jsを変更します。

const { FuseBox } = require("fuse-box");

const fuse = FuseBox.init({
  homeDir: "src",
  output: "dist/$name.js"
});

fuse.dev();

fuse.bundle("app")
  .instructions("> index.ts")
  .watch()
  .hmr();

fuse.run();
fuse.bundle("app").test("[**/**.test.ts]");

設定は、fuse.bundle("app").test("[**/**.test.ts]");の1行増えただけです。末尾が.test.ts.のテストファイルをすべて実行します。

index.tsに以下を追加します。

export const count = 1;

export function calculate(num) {
  return num + 1;
}

index.test.tsに以下を追加します。

import { should } from "fuse-test-runner";
import { count, calculate } from "./index";

export class BarTest {
  "Should be okay"() {
    should(count).beOkay();
  }

  "Should equal 2"() {
    should(calculate(count))
      .equal(2);
  }

  "Should not equal 2"() {
    should(calculate(5))
      .equal(2);
  }
}

処理の内容を説明します。

  • 内蔵のアサーションライブラリーを読み込む
  • 必要な関数をindex.tsから読み込む
  • クラスを作成しテストメソッドをラップする
  • コードをテストするテストメソッドを作成する

1つ目のテスト「Should be okay」はcount変数が空またはUndefinedではないか、should(count).beOkay();で検証しています。アサーションの開始にはshouldメソッドを使います。shouldメソッドは変数、関数、オブジェクト、数式を受け取り、内蔵のアサーションを1つ使います。上の例ではbeOkayを使っています。beOkaycount変数が空またはUndefinedではないことをアサートします。

2つ目のShould equal 2テストは、count変数をcalculate関数に渡して正しい結果が返されることをアサートします。

3つ目のShould not equal 2テストでは、5を渡してテストを意図的に失敗させています。値の結果は6なので期待値の2と一致しません。

node fuse.jsを実行すると、最初の2つのテストに成功したことと、3つ目のテストに失敗したとコンソールに表示されます。

Unit testing

完成したサンプルはこちら

開発環境 vs プロダクション環境

FuseBoxの主要なコンセプトを解説しましたが、開発環境とプロダクション環境で必要なものが異なります。たとえば、HMRを有効にした状態でコードをバンドルして公開することはありません。開発環境とプロダクション環境の両方の要件を満たせる、おすすめの設定を紹介します。

以下を実施します。

  • 新たなプロジェクトを作成する
  • コマンドラインを使ってプロジェクトのルートに移動し、npm init -yを実行する
  • srcフォルダーを作成する
  • srcフォルダーにindex.tsを追加する
  • srcフォルダーにcalc.tsを追加する
  • srcフォルダーにcalc.test.tsを追加する
  • srcフォルダーにmain.cssを追加する
  • srcフォルダーにextra.scssを追加する
  • プロジェクトのルートにfuse.jsを作成する
  • コマンドラインでnpm install fuse-box fuse-test-runner typescript node-sass uglify-js -Dを実行し、FuseBox、SASS、UglifyJS、TypeScriptを依存オブジェクトとしてインストールする

fuse.jsに以下を追加します。

const { FuseBox, CSSPlugin, SassPlugin, WebIndexPlugin, UglifyJSPlugin, Sparky } = require("fuse-box");

let fuse, app, vendor, isProduction = false;

Sparky.task("config", () => {
  fuse = FuseBox.init({
    homeDir: "src",
    output: "dist/$name.js",
    hash: isProduction,
    sourceMaps: !isProduction,
    plugins: [
      [SassPlugin(), CSSPlugin()],
      CSSPlugin(),
      WebIndexPlugin({path: "."}),
      isProduction && UglifyJSPlugin()
    ]
  });

  // vendor should come first
  vendor = fuse.bundle("vendor")
    .instructions("~ index.ts");

  // out main bundle
  app = fuse.bundle("app")
    .instructions(`!> [index.ts]`);

  if (!isProduction) {
    fuse.dev();
  }
});

// development task "node fuse""
Sparky.task("default", ["config"], () => {
  vendor.hmr().watch();
  app.watch();
  return fuse.run();
});

// Dist task "node fuse dist"
Sparky.task("dist", ["set-production", "config"], () => {
  return fuse.run();
});

Sparky.task("set-production", () => {
  isProduction = true;
  return Sparky.src("dist/").clean("dist/");
});

Sparky.task("test", ["config"], () => {
  return app.test();
});

理解すべきことが多くありそうですが、心配しないでください。個別に見れば、とてもシンプルで強力なコードだと分かります。

考え方は前回と同じですが、新たな変数「isProduction」が追加されています。isProduction変数でFuseBoxに開発用のバンドルか、プロダクション用のバンドルどちらを作成するのか指示します。

FuseBox.init()に渡すオブジェクトの中にhashプロパティがあります。このプロパティにisProductionの値をセットします。FuseBoxのハッシュ機能で、リリース管理に重要な役割があります。ハッシュを利用することで、新たなバージョンのアプリケーションを提供する際にブラウザーのキャッシュを無効化します。ユーザーが最新バージョンのアプリを確実に入手できるようになるのです。キャッシュを有効にすると、FuseBoxはバンドル開始時に各バンドル用にファイルのハッシュ名を生成します。

d72d7ad8-app.js
b841f28-vendor.js

プロダクションではコードをできるかぎり小さく、高性能にします。UglifyJSPluginでバンドルを圧縮します。

pluginsプロパティのisProduction &&UglifyJSPlugin()ですが、JavaScriptの式でisProduction変数がtrueの場合にUglifyJSPluginを適用します。

vendorバンドルを作成します。vendorバンドルはローカルコードを外部パッケージや依存オブジェクトから分離し、モジュール方式を実現します。バンドル内の重複コードを減らすのです。.instructions("~ index.ts")~記号はFuseBoxの算術記号で、FuseBoxに外部の依存オブジェクトをすべて抽出し、実際のプロジェクトファイルを無視するよう指示します。つまり、ローカルコード以外の外部の依存オブジェクト(npmパッケージ)がすべてバンドルされます。

メインバンドルを作成します。.instructions("!> [index.ts]")!>記号も算術記号です。!記号でバンドルからローダーAPIを取り除きます。!記号を使う理由は、ローダーAPIがvendorバンドルにインクルード済みだからです。>記号はロード時にファイルを自動で実行します。

タスク

タスクについて説明します。設定(config)をconfigタスクにカプセル化しています。繰り返しやコードの汚染なしに設定を別のタスクで使えるのです。

defaultタスクが開発環境をターゲットにしているため、defaultタスク内でvendor.hmr().watch()を使ってHMRを有効にします。ここではisProductionfalseにします。

isProduction変数はset-productionタスクでtrueにします。

一方、distタスクはプロダクション環境をターゲットにするため、set-productionタスクとconfigタスクに依存します。distタスクはset-productionタスクが完了するまで実行されず、set-productionタスクはconfigタスクが完了するまで実行されません。

testタスクは単にプロジェクト内で定義したテストを実行します。

すべての動作を確認します。コマンドラインでnode fuse.jsを入力すると、FuseBoxが以下の項目を実行します。

  • バンドル処理を開始する
  • 開発用サーバーを起動する
  • HMRを開始する
  • コードに変更を加えるたびにHMRとバンドル処理が起動する

プロダクションはどうなるのか

プロダクションについても心配いりません。node fuse.js distを実行(distパラメーターに注意)すると、FuseBoxが以下を実施します。

  • バンドル処理を開始する

プロダクションモードのため、HMRも開発用サーバーも実行されません。distフォルダーを開くとFuseBoxがランダムな名前でバンドルを生成したことが分かります。バンドルを開くと、FuseBoxがUglifyJSPluginを使ってコードを圧縮したため、コードが無茶苦茶になっています。バンドルのサイズを開発モードとプロダクションモードで比べると違いが分かります。

テストはコマンドラインからnode fuse.js testを実行します。

完成したサンプルはこちら

軽量なwebpack代替ツール

FuseBoxさえあれば最新の開発ワークフロー(開発からプロダクションに至るまで)に必要なものがすべて揃います。ライブラリーはより高度なオプションやコンセプトが用意されています。この記事がFuseBoxを正しく理解し、FuseBoxを楽しく使ってもらうための手助けになれば幸いです。

Gitterにあるコミュニティです。コミュニティのメンバーはとても親切で協力的です。プロジェクトが気に入ったらGitHubにスターをつけてTwitterをフォローしてください。

本記事はDominic Myersが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。

(原文:Introduction to FuseBox — a Faster, Simpler Webpack Alternative

[翻訳:薮田佳佑/編集:Livit

Web Professionalトップへ

WebProfessional 新着記事