JSコンパイル系の続きで今回はBabelです。前回はAltJSのTypeScriptをGulpでコンパイルしました。今回のBabelはESの新しい書式を従来の書式(ES5)に変換します。AltJSではなく正規なJSでちょっと書き方が新しいだけだし、Babel自体にコンパイル機能があるためGulpも使いません。それでは行きましょう!(ESメソッドを適用させるポリフィルについても追記しました!)
【目次】
- Babelとは何か
- ESとは何か
- Babelのコンパイル環境を準備する
- コンパイルするjsファイルを準備
- Babelコンパイル前のファイル
- Babelコンパイル実行!
- IE未対応メソッドにはポリフィル必要!(追記)
- 最後に
前回記事
※参考:【JS】TypeScriptをGulpでコンパイルしてみる - クモのようにコツコツと
Web開発環境まとめ
qiita.com
Babelとは何か
こちらの解説がわかりやすい。
※参考:Babelの手ほどき | 前編 Babelとは | CodeGrid
Babel(バベル)*は、次世代のJavaScriptの標準機能を、ブラウザのサポートを待たずに使えるようにするNode.js製のツールです。次世代の標準機能を使って書かれたコードを、それらの機能をサポートしていないブラウザでも動くコードに変換(トランスパイル)します。
そしてBabelはなんと、厳密に言うとAltJSではなかった。
BabelとAltJS
Babelはコードを変換するという点では、CoffeeScriptやTypeScript*といった、JavaScriptのコードを生成するAltJSの仲間と言えるかもしれません。
しかしながら…
Babelを使う際に書くのは、AltJSではなく純粋なJavaScriptです*。新しい機能や構文を使って書いたJavaScriptを、現状のブラウザでも動くJavaScriptへと変換します。
CodePenの「JavaScript Preprocessor」にBabelもあったのでAltJSの一種かと思っていた。
ちなみにプリプロセッサとは…
プリプロセッサとは、ソフトウェアの役割による分類の一つで、ある中心的な処理を行うプログラムに対して、その前処理(preprocess)を行うプログラムのこと。プログラミング言語のコンパイラの前処理を行うものが非常に有名。
※参考:プリプロセッサ(プリコンパイラ)とは - IT用語辞典 e-Words
TyepeScriptはJSのメタ言語(代替言語)のため拡張子が.ts
。BabelはJSの標準仕様のため拡張子は.js
のままだった。
ESとは何か
ESはEcmaScriptの略
JSの標準仕様なのになぜコンパイルが必要なのか。それはJSの新しい仕様にまだ対応していないブラウザがあるため。
以前の記事でも触れた様にJSの標準仕様は「ES」という。
※参考:周回遅れでもWebGLを事始める!canvas大地に立つ!! - クモのようにコツコツと
ESは「ECMAScript」の略称
ECMAScript(エクマスクリプト)は、JavaScriptの標準であり、Ecma Internationalのもとで標準化手続きなどが行われている。
ESを策定している「Ecma International」とは何か
Ecmaインターナショナル(エクマ・インターナショナル、英: Ecma International)は情報通信システムの分野における国際的な標準化団体。
脚注によると「ECMA」は「European Computer Manufacturers Association」の略で「欧州電子計算機工業会」という意味。今は略語ではなくなったため、大文字では書かず「Ecma」が正式名称になったそうな。
ESのバージョン
このESのバージョンが今は毎年改定されていてブラウザの対応がなかなか追いつかない。
6th editionから、「ECMAScript 2015」仕様の名称に発行年が付加されることになった。以降、ECMAScriptは毎年改訂されることになり、以降特定の版を指す場合は、edition名ではなく年号つきの仕様書名で呼ばれることが推奨されている[2]。
「ES6(ES2015)」の前の「ES5」は2009年、「ES5.1」は2011年に改定されたため、今ではほとんどのブラウザが対応している。
ES6からは便利な機能がかなり追加された。
- letとconst
- カーリーブラケット{}によるブロックスコープ
- アロー関数
- Class構文
- 関数のデフォルト引数
- 分割代入
- テンプレート文字列
- スプレッド演算子...
- for...of
- Promise
なので、みんな使いたい。そのため開発時はES6〜の仕様でJSを書いて、公開時にはBabelでES5にコンパイルをするわけだ。
ES6(ES2015)のブラウザ対応状況
なお、ES6のブラウザ対応状況はこちら。
※参考:ECMAScript 6 compatibility table
以前はChromeとFireFox以外はあまり対応してくれていなかった様だが、さすがに5年も経っているのでSafariやEdgeなども対応してくれている様だ。ただ、IEはもうホントどーしようもない。早く市場から消え去って欲しい。
IEが標準ブラウザなOS「Windows7」のサポート終了は2020年1月14日。いよいよカウントダウンが始まっている!時が来た!!!!
※参考:Windows 7 のサポート終了情報 - Microsoft
Babelのコンパイル環境を準備する
ということで早速バベりたい。
CDNリンク
Babelのコンパイルについて調べるとGulpやWebPackと連携する方法が多いが、まずはBabel単体に標準で付いているコンパイル機能がどんなものか体験する。こちらの記事がわかりやすく、参考にさせていただきました!
※参考:Babelの使い方入門編|ES6をコンパイル(JavaScript)
ちなみに、先に書いた様にBabelは.jsファイルの中身を変換するのみのため、なんとCDNのリンクでブラウザ(クライアントサイド)のみでも変換が可能らしい!head
タグの中に下記をリンクする。
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
Babelインストール前の準備
node.jsとnpmは入っている前提(下記のコマンドでバージョン番号が出る)
node -v npm -v
Babelをインストールするフォルダを作る。今回はbabel_test
という名前にした。
ターミナルを開いてcd
コマンドでフォルダに移動する。
cd /(フォルダ)/babel_test
package.jsonを作成する。
npm init -y
ここまではTypeScriptの時と同じですな。
※参考:【JS】TypeScriptをGulpでコンパイルしてみる - クモのようにコツコツと
babel-cliをインストール
この次、今回はGulpは入れない。
babel-cli
というツールをローカルでインストールする。
npm install -D babel-cli
成功するとpackage.json
のdevDependencies
にbabel-cli`が記載される。
"devDependencies": { "babel-cli": "^6.26.0" }
babel-preset-envをインストール
Babelの設定ファイルである.babelrc
を作成する。
なお、ドット付きのファイルは「非表示ファイル」のため、ファインダーで表示されない場合は「command + shift + . 」で表示する。
※参考:Macのショートカットキー - 不可視ファイルの表示/非表示を切り替える - PC設定のカルマ
次にbabel-preset-env
というプリセットをローカルでインストールする。
npm install babel-preset-env -D
参考記事ではbabel-preset-es2015
かbabel-preset-env
のいずれかを入れる、とあった。
babel-preset-es2015
は「ES2016」を「ES2015(ES6)」にコンパイルしてくれるプリセットだが、公式サイトを見るとそれに変わる機能としてbabel-preset-env
を推奨している様だ。
※参考:babel-preset-es2015 -> babel-preset-env · Babel
毎年改定されるES20xx
の内容をこのプリセットが判断してくれるっぽい。
※参考:babel-preset-envを簡単にさわってみた。 - Qiita
成功するとまたpackage.json
に追記される。
"devDependencies": { "babel-cli": "^6.26.0", "babel-preset-env": "^1.7.0" }
.babelrc
に設定を書き込む。これだけでも大丈夫っぽいが…
{ "presets": ["env"] }
念のため、参考記事にある様にブラウザの詳細設定も追記する。
{ "presets": [ ["env", { "targets": { "browsers": ["last 2 versions", "safari >= 7"] } }] ] }
presets
の第二引数として連想配列targets
キーを入れるtargets
キーの中にさらに連想配列browsers
キーを入れる。browsers
の値は配列で一つ目の値に相対的なバージョン、二つ目の値にSafariのバージョン
データはJSON形式のようだ。
コンパイルするjsファイルを準備
以前のAltJS記事のおさらい
コンパイルしたいjsファイルを作る。以前、AltJS記事で作ったBabelのCodePenを使う。
See the Pen Babel practice 1 by イイダリョウ (@i_ryo) on CodePen.
※参考:【CoffeeScript, LiveScript, TypeScript, Babel】AltJS 事始め - クモのようにコツコツと
HTMLファイル、css、jsフォルダ作成
プロジェクトフォルダ直下にindex.html
を作る。
HTMLコード
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>Babel事始め</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <section id="coffee"> <h1>Babel事始め</h1> <p>CodePen Settingの旅、JS編第4回。JS編の最後を飾るBabelはブラウザがまだ対応していない最新のESに準拠した記述ができるAltJSとのこと。 </p> <section id="hello"> <h2>特徴</h2> <ul> <li>最新のESに準拠</li> <li>変数にletやconstなどが使える</li> <li>アロー関数式「=>」が使える</li> <li>クラス定義ができる</li> </ul> <p>Babelも素のJSがそのまま行けるようなのでJSからの書き換えもしやすそう。</p> <p><small>※letは再宣言が出来ない。<br> ※constは再宣言も再代入もできない。<br> →いずれもvarより厳密だが、全てvarに置き換えても問題はない。 </small></p> </section> <div><button id="btn">ここ押せワンワン</button> </section> <script src="js/script.js"></script> </body> </html>
body
の閉じタグの直前でscript.js
というファイルをリンクしている。これはBabelでコンパイル後のファイルの前提。
<script src="js/script.js"></script>
また、css
フォルダ、js
フォルダも作る。また、css
フォルダの中にcommon.css
ファイルを作っている(コードはCodePen参照)
ブラウザで開いてみると「ここ押せワンワン」というボタンがある。
しかし、まだscript.js
が存在していないため、ボタンを押しても何も起こらない。
Babelコンパイル前のファイル
js
フォルダの中にBabelコンパイル前のファイルを作る。babel_test.js
という名前にする。
こんなファイル構成。
コンパイル前(babel_test.js
)
JSコード
/*関数 function hellow(){ window.alert('hellow TypeScript'); window.alert('こんにちは、型スクリプト'); window.alert('おしまい'); }*/ /*アロー関数*/ var hellow = () => { window.alert('hellow Babel'); window.alert('こんにちは、バベル'); window.alert(title + 'は第' + num + '回です。'); window.alert('おしまい'); } /*変数 var btn = document.getElementById('btn');*/ /*最新の変数*/ const btn = document.getElementById('btn'); let title = 'JS編'; var num = 4; /*イベント*/ btn.addEventListener('click', hellow, false);
Babelコンパイル実行!
それでは、いよいよコンパイルを実行する!
./node_modules/.bin/babel js/babel_test.js -o js/common.js
./node_modules/.bin/babel
を実行js/babel_test.js
をjs/common.js
にコンパイルする
別ファイルにコンパイルしたい場合は-o
で別名を指定する。付けない場合は上書きされる。
やた!common.js
が作られた!
コンパイル後(common.js
)
JSファイル
'use strict'; /*関数 function hellow(){ window.alert('hellow TypeScript'); window.alert('こんにちは、型スクリプト'); window.alert('おしまい'); }*/ /*アロー関数*/ var hellow = function hellow() { window.alert('hellow Babel'); window.alert('こんにちは、バベル'); window.alert(title + 'は第' + num + '回です。'); window.alert('おしまい'); }; /*変数 var btn = document.getElementById('btn');*/ /*最新の変数*/ var btn = document.getElementById('btn'); var title = 'JS編'; var num = 4; /*イベント*/ btn.addEventListener('click', hellow, false);
- アロー関数(
=>
)が従来のfunction
の関数になっている。 - 変数の
const
、let
も全てvar
になっている。
ブラウザをふたたび開く。
common.js
がリンクになっているので…
ボタンを押すとアラートが表示された!
IE未対応メソッドにはポリフィル必要!(追記)
(※2021/05/01追記)
Babelを使えばIE気にせずモダンなJS書ける〜♪と思ってたのだが…どうやらBabelがコンパイルしてくれるのはJSの文法的な部分(アロー関数、const
変数など)だけのようだ。。
JSリファレンスのポリフィル
例えば文字列(String)が要素に含まれるかを探すincludes()
メソッド。ES2015から追加されたメソッドでIEは未対応。
※参考:String.prototype.includes() - JavaScript | MDN
このメソッドはBabelコンパイル後もそのままのため、IE上ではコンソールエラーになる。。
これを防ぐにはポリフィルを追記する必要がある。JSリファレスを調べるとポリフィルが載っていたりする。
if (!String.prototype.includes) { String.prototype.includes = function(search, start) { 'use strict'; if (search instanceof RegExp) { throw TypeError('first argument must not be a RegExp'); } if (start === undefined) { start = 0; } return this.indexOf(search, start) !== -1; }; }
これは「もしString.prototype
にincludes
がなければ変わりに別の処理を行う」という内容で、includes
対応ブラウザ(=IE以外のブラウザ)では動かない。
※参考:String.prototype.includes() - JavaScript | MDN
しかし!リファレンスにポリフィルが必ず書かれてるとは限らないようだ。例えば配列(Array)用のincludes()
メソッドにはポリフィルが掲載されていなかった。
※参考:Array.prototype.includes() - JavaScript | MDN
調べると個人の方がポリフィルを書いてくれていたりする!
※参考:【JavaScript】Arrayにincludesをポリフィルしよう | レコチョクのエンジニアブログ
とてもありがたいことだが、リファレンスで全部のポリフィルを用意してくれればいいのにと思ふ。
また、そもそもincludes()
メソッドを使うたびにポリフィルをコードに追加するのもなかなか手間な作業ではある。。
polyfill-io
ポリフィル対策は他にもいくつかある。
「polyfill-io」上で該当するメソッドのポフィリスのURLを取得してリンクする方法。
※参考:【Polyfill.io】を使用してJavascriptのブラウザ互換を解決する|日々、アップデート
※参考:Polyfill.io
先ほどの配列用includes()
のリンクを取得して
ページ上にリンクを追加する
<script src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.includes"></script>
npmライブラリのポリフィル
JSコードの中にポロフィルを含みたい場合はnpmで探すとライブラリが見つかるのでインストールするといい。
先ほどの配列用includes()
を調べると下記が出てくる。
※参考:polyfill-array-includes - npm
ライブラリをインストールして
$ npm install polyfill-array-includes
モジュールでインポートするとIEでもincludes()
メソッドが動く。
$ import 'polyfill-array-includes';
コンパイルするとこのコードも含まれて1ファイルになる。モジュール開発している場合は「polyfill-io」のリンクよりこの方法の方が望ましい。
まあ個人的にはIEは対象外にするのが一番望ましくはあるw(2021/05/01現在、PCブラウザでのIEのシェアは6.91%)
※参考:Desktop Browser Market Share Japan | StatCounter Global Stats
最後に
ということで、Babelを使ってES6のコードをES5にコンパイルしました!Babelは自動コンパイル設定をしたり、GulpやWebPackと連携してコンパイルすることもできる様です。おいおいトライしていこうと思います。
なお、以前にも触れた通りGulp、Babel、Webpackの3つがフロント開発3銃士と呼ばれている様です。
※参考:gulpとbabelとwebpackというフロント開発3銃士 - Qiita
そのうち2つに触れたことになりますが、最後のWebPackがまだ未体験のため、次回トライしてみたく思います。それではまた!
Web開発環境まとめ
qiita.com