なぜJavascriptにビルドが必要?フロントエンド開発の知識をアップデートしよう
はじめに
Javascriptなんて、基礎は簡単です。HTMLのscriptタグにコードを書けばそれだけで動きますし、別ファイルにしたい場合はjsファイルにコードを書いて、リンクを張れば良いだけです。
...にもかかわらず、最近のフロントエンド開発の現場では、「Node.jsで開発環境を構築する」だの、「ソースコードをビルドする」だの、何だか難しいことを言っており、久しくフロントエンド開発に触れていない方にとっては、玉手箱を開けたような気分になるかもしれません。
そのような方に向け、この記事では、なぜJavascriptにビルドが必要なのかという疑問に対して、最小限の前提知識で理解いただけるよう、説明をしたいと思います。
主たるビルド処理とその目的
現在のメジャーなフロントエンド開発環境では、プログラマが書いたJavascriptをそのまま公開するのではなく、実行用のJavascriptに変換してから公開するのが主流になっており、この変換処理を「ビルド」と呼んでいます。
ビルドと一言で言っても様々な種類があり、それぞれ目的も異なるので、開発環境によって必要なものを組み合わせて使うことになります。
ここでは、よく使われる3種類のビルド工程である、bundle、transpile、minifyについて紹介します。
bundle - 複数ファイルのソースを1ファイルにまとめる
大きな規模のプログラムの場合、ソースコードが機能ごとに適切に分けられて別々のファイルになっているほうが、開発時には保守性の面で良いですよね?
しかし、ユーザが実行する時のことを考えると、たくさんのjsファイルがあるとダウンロードに時間がかかりパフォーマンスが落ちてしまうので、できるだけソースは1つのファイルにまとめられていたほうが良いです。
そこで、bundle処理は、ファイルごとに分割して書かれたコードを、1ファイルにまとめてくれます。
下例のように、export
宣言のあるJavascript(子モジュール)をimport
宣言のあるJavascript(親モジュール)から呼び出すように書き、これらをbundleすると、まとめられて1つのファイルになります。
変換前
//module1.js
export const hoge = 1;
//module2.js
export const fuga = 2;
//main.js
import hoge from "module1.js"
import fuga from "module2.js"
console.log(hoge + fuga); // 3
変換後
//bundled.js
const hoge = 1;
const fuga = 2;
console.log(hoge + fuga); // 3
自分の書いたコードだけでなく、インストールした外部のパッケージのコードもimport
で取り込むことができますので、パッケージ管理の面でもbundleは重要な役割を担っていると言えます。
transpile - 新しい規格を古い規格に変換
Javascriptは、より効率的に開発ができるように日々新しい規格(ES5、ES6、などと呼ばれます)が考案され、新しい文法が追加されています。しかし、古いブラウザは新しい規格に対応していないため、新しい規格の文法を使うと対応ブラウザが限られてしまうことになります。
そこで、transpileを行うことで、新しい規格に沿って書かれたコードを古い規格に変換することができ、この問題を解決することができます。
一例をあげます。かつて、Javascriptでは変数宣言の時にvar
を使用していましたが、新しい規格では、再代入ができない定数にconst
を、再代入できる変数にはlet
を、と使い分けるようになりました。これにより、誤って定数に代入しようとしたときにエラーが出るようになり、バグが混入しにくくなったのです。
しかし、const/let
は古いブラウザでは使用できないため、transpileではこれらを全てvar
に置き換えます。
変換前
const hoge = 1;
let fuga = 1;
fuga = 2;
変換後
var hoge = 1;
var fuga = 1;
fuga = 2;
「いや、それじゃconst/let
を使い分ける意味ないでしょ!」とお思いかもしれませんが、linter(文法チェッカー)を使えば、transpileするより前に最新の規格に沿ってチェックを行ってくれるので、const
への代入があればちゃんとエラーを教えてくれます。
const/let
のほかにも、アロー関数、class構文、async/await
など新しい規格の文法がありますが、これらも古いブラウザで使用できる文法に変換してくれます。
minify - インデントやコメントなどを取り除く
プログラミングにおいて、適切なインデントやコメント、そして分かりやすい命名はソースコードの可読性を向上させるために必要なものです。しかし、これらはプログラムの動作とは無関係なので、実行時には無くても一切問題ありません。
minify処理では、ソースコードから実行上意味のないスペースや改行を取り払い、命名された名前を短いものに置換します。
minifyの目的としては、ファイルのサイズを小さくしてWebのパフォーマンスを上げることのほか、悪意のある攻撃者がソースコードを読んでアプリケーションの脆弱性を見つけることを難しくしたり、知的財産であるソースコードの盗用を防ぐといったことも挙げられます。
ビルドするためのツール
以上で紹介したビルド処理をするためには、webpack、babelというツールを使うのが主流です。
- webpack
- bundleおよびminify処理をしてくれる
- babel
- transpile処理をしてくれる
これらのツールは、Node.jsのパッケージとして提供されています。だから、フロントエンドの開発環境をNode.jsで構築することが多いのです。これらのパッケージをインストールして、設定ファイルに必要事項を記載しておくことで、コマンド1つで、一連のビルド処理を行ってくれます。
その他の変換処理
ここで紹介した以外にも、フロントエンド開発におけるビルド処理には様々なパターンがあります。ここまではJavascriptのみについて言及してきましたが、HTMLやCSSを変換するケースもありますのでいくつか紹介します。
- Typescript
- 変数の型を指定できるようにしたJavascript
- ビルドにより純粋なJavascript(型のないもの)が生成される
- Pug
- タグの表記を簡略化できるようにしたHTML記法
- ビルドにより純粋なHTMLが生成される
- Sass
- セレクタの入れ子構造などをできるようにしたCSS記法
- ビルドにより純粋なCSSが生成される
ここでは紹介だけにとどめますが、興味のあるものがあれば、ぜひ、調べてみてください。
さいごに
イメージは掴めましたでしょうか?より理解を深めるためには、実際にNode.jsをインストールして最小限の開発環境を作ってみるとよいと思います。