変換処理

適当でもなんとなくの理解はできるけど、ちゃんと抑えておくといろいろスムーズになりそう

コンパイル

🤔 さすがにわかる

  • プログラミング言語で書かれたプログラムを、機械語に変換すること
  • 変換を行うソフトウェアをコンパイラという

image

😗 この単語めちゃ見るけど、やってるのは JavaScript を直接実行するところだけなのでは...??

トランスコンパイル

🤔 察しはつく

  • ある言語で書かれたプログラムを、別の言語の同等のプログラムに変換すること
    • e.g. TypeScript → JavaScript
    • e.g. ES11 → ES9
  • 変換を行うソフトウェアをトランス ( コン ) パイラという
  • 最新機能を用いて実装し、配布前に変換することで古いブラウザで動かす、ということが可能
JavaScript ( ES11 )
height ?? 100

↓ ES11 を ES9 にトランスパイル

JavaScript ( ES9 )
(height !== undefined && height !== null) ? height : 100

image

😗 変換後も直接実行できる機械語ではなく高級言語なところがコンパイルと違うはず

モジュールバンドル

🤔 あまり耳馴染みがない

  • 複数のモジュールを 1 つにまとめること
    • e.g. .js + .js + .js.js
    • e.g. .html + .css.html
  • 変換を行うソフトウェアをモジュールバンドラという

image

😗 あまり気にしたことなかったけど、これの理解は大事っぽい

Minify

🤔 圧縮のことだろう

  • JavaScript や CSS を圧縮すること
    • e.g. .js.js
  • 主にサイズを小さくして通信負荷を下げるために行われる
  • 変換後のコードもそのまま実行でき、同じ結果が得られる
before
function printMessage(name) {
    console.log("hey" + name);
}
printMessage("hoge-san");
after
function a(b){console.log("hey"+b);}a("hoge-san");

😗 認識通り

難読化

🤔 字の通りだろう

  • JavaScript や CSS を読みづらくすること
    • e.g. .js.js
  • 主にユーザにコードを理解されるのを避けるために行われる
  • 変換後のコードもそのまま実行でき、同じ結果が得られる
before
function printMessage(name) {
    console.log("hey" + name);
}
printMessage("hoge-san");
after
function _0x1ac4(){var _0x394085=['1090440PQdWgm','10490733gaJQgP','log','243921AcDNII','20784aUhiXj','463129uQMLXK','614454YHaQww','hey','1884534zFuqKU','4SAggHz','413ojXDeO'];_0x1ac4=function(){return _0x394085;};return _0x1ac4();}function _0x4f80(_0x1b8cc6,_0x506517){var _0x1ac43e=_0x1ac4();return _0x4f80=function(_0x4f804d,_0x1cbbed){_0x4f804d=_0x4f804d-0x9f;var _0x1160c8=_0x1ac43e[_0x4f804d];return _0x1160c8;},_0x4f80(_0x1b8cc6,_0x506517);}(function(_0x339430,_0x59df82){var _0x525670=_0x4f80,_0x2ccac9=_0x339430();while(!![]){try{var _0x92e38b=-parseInt(_0x525670(0xa5))/0x1+-parseInt(_0x525670(0xa6))/0x2+-parseInt(_0x525670(0xa3))/0x3*(-parseInt(_0x525670(0xa9))/0x4)+parseInt(_0x525670(0xa0))/0x5+-parseInt(_0x525670(0xa8))/0x6+-parseInt(_0x525670(0x9f))/0x7*(-parseInt(_0x525670(0xa4))/0x8)+parseInt(_0x525670(0xa1))/0x9;if(_0x92e38b===_0x59df82)break;else _0x2ccac9['push'](_0x2ccac9['shift']());}catch(_0x16c4d7){_0x2ccac9['push'](_0x2ccac9['shift']());}}}(_0x1ac4,0x8256d));function printMessage(_0x25710f){var _0x22ab6a=_0x4f80;console[_0x22ab6a(0xa2)](_0x22ab6a(0xa7)+_0x25710f);}printMessage('hoge-san');

😗 認識通り

ビルド

🤔 改めて、でも超軽く

  • 実行可能なファイルを作成する一連の工程のこと
    • コンパイルなどを含むプログラムの変換処理
    • 外部ファイルとのリンク
    • 起動用コードの追加

😗 コンパイルやモジュールバンドルを含む一連の変換のことを指すと思えば良さそう

変換ツール

やたらあるので全部は覚えず、変換処理とちゃんと対応づけて代表的なのだけ抑える

Babel

🤔 バベルの塔...??

  • JavaScript のトランスコンパイラ
  • 主に ES6+ を古い JavaScript に変換するために使われる
    • e.g. アロー関数を function に戻す
  • JSX なども変換できる
  • Polyfill も提供することで、変換後に存在しない関数を代替実装して動かすことができる
    • e.g. ES5 には存在しないが構文エラーではない Promise.then は Polyfill で解決する

image

😗 Webpack のトランスパイルもこれとかを使っているのだろう、これ以上は必要になったら...

webpack

🤔 やたらみんな使ってるみたいけど聞いたこともないぞい、なんか超多機能そう

  • JavaScript のモジュールバンドラの 1 つ
  • 依存関係のあるモジュールを受け取りアセットを生成する
    • e.g. .js + .js + .js.js
  • 主に JavaScript 用だが、設定と loader 次第でトランスパイルなどを実行させることも可能
    • e.g. .html + .jsx + .ts + .js + .scss.html + .js + .css
  • いくつものモジュール形式に対応している
    • e.g. ESM の import
    • e.g. CJS の require
  • 開発時はファイルを分割したいがデプロイではまとめたい、などが実現できる

image

😗 これ自体はモジュールバンドラであり、トランスパイル機能を持っているわけではない

gulp

🤔 6 年くらい前に違う部署の同僚が叩いてたなぁ

  • JavaScript のタスク自動化ツールで、Node.js と npm に基づいている
  • Sass や画像の圧縮などやテストなどを行うために使われる
  • Babel を使うと ES6 から ES5 への変換などが行える

image

😗 これ以上は必要になったら... 多分 webpack の方を使えばいい気がする

Grunt

🤔 牛のやつだっけ

  • JavaScript のタスク自動化ツールで、Node.js と npm に基づいている
  • Gulp より先に生まれた

image

😗 これ以上は必要になったら... 多分 webpack の方を使えばいい気がする

tsc

🤔 javacrustc と同じ感じだろう

  • TypeScript のトランスパイラ
  • .ts.js にする
  • tsconfig.json を使って変換先の ES Edition などを設定する
  • 変換対象はあくまで JavaScript の構文のみであり、Babel と違い Polyfill は提供しない
    • e.g. Promise.then は ES5 では使えないが文法としては問題ないので対処されない

image

🤔 tsconfig.json は tsc のためのトランスパイル設定だったのね

代替コード

カテゴライズに迷ったのでここに

Polyfill

🤔 聞いたことないわい

  • 古いブラウザでは使えない処理を、同等の機能で補う代替コードのこと
  • 実装を差し替えることであり、トランスパイルを行っているわけではない
  • Polyfill を行うライブラリがいくつかある
    • e.g. core-js
    • e.g. Polyfill.io
  • これを読み込むタイミングで足りない関数がプロトタイプ汚染などで埋められるという理解
    • なので ?? 演算子などは置き換えられないはず
// Math.trunc が実装されていない ( 極めて ) 古いエンジンの場合
if (!Math.trunc) {
  // 代替実装を提供することで Math.trunc を使えるようにする
  Math.trunc = function(number) {
    return number < 0 ? Math.ceil(number) : Math.floor(number);
  };
}

😗 トランスパイルとはできることが違うけど意識するのは大変そう、全部 Babel に頼もう

まとめ

本当に何も知らない状態に比べると格段に会話が成立するようになった

何から何に変換するものか、それは誰が行っているのか、何を目的としているのか
を整理できるとツール選定や設定の把握がしやすいと感じた

あとは実践あるのみ