へっぽこびんぼう野郎のnewbie日記

けろけーろ(´・ω・`)! #vZkt8fc6J

JavaScript界隈の基本的な用語を歴史とともにさらにまとめてみた

https://qiita.com/sinsengumi/items/e20342d13cbdd7ac2304 を読んで、すこしだけもやもや感がぬぐえなかったので、適当に自分が思ってる「今のJavaScriptはこんなかんじ」というのを書いた。

EcmaScript

だいじなこと

EcmaScriptとは、プログラミング言語ではない。

EcmaScriptとは、Ecmaインターナショナルが決めているJavaScript言語仕様のこと。

Ecmaとは、European Computer Manufacturers Association の略で、要は世界のコンピュータ関連の仕様を決めてる闇の組織みたいなところ。 (→History of Ecma

なんでEcmaScriptとかいうものがあるのか?

大昔、JavaScriptという言語はHTMLやCSSの「おまけ」扱いだった。

当時のブラウザベンダ(NetScapeIE)が自分たちの好きなようにJavaScriptを作っていたので、Webサイト開発者がサイトを開発するとき、彼らは各ブラウザの独自仕様を理解して同じような動きをするサイトを作らなければいけなかった。

そこで、JavaScriptの仕様を統一しようということで、EcmaScriptという言語仕様が登場した。

これの登場によって、各ブラウザベンダ間での実装がまぁまぁ同じになって、昔より格段と作りやすくなった。(マシになったというだけで、今も辛いのは変わっていない)

今でも他の言語とは違ってJavaScriptでは、仕様と実装が乖離していることが多い。そのためEcmaScriptのことを意識しないと使いにくい。

たとえばPythonでは、PEPが言語仕様で、CPythonやPyPyが言語実装であり、あんまり実装や仕様のことを考えなくてもCPythonがかなり支配的なので「Pythonとはこういうもの」という理解だけでも、そんなに混乱することはない。*1 *2

一方JavaScriptでは、IESafariChromeFirefoxJavaScriptの動きが異なっており、日本ではそのすべてに対応しないといけないことが多いので、EcmaScriptを意識しないと「JavaScriptとはなんやねん」って感じになってしまう。

つまりEcmaScriptという言語仕様があるという概念を理解するのは、ものすごくだいじ。

EcmaScriptの現在

現在でも各JavaScriptエンジン開発者は、このEcmaScriptという言語仕様をもとにおのおののエンジンを開発している。

EcmaScriptは、現在バージョン8まで仕様が決められており、これはES8とかES2017と呼ばれている。現在はES2019が策定中。

ES2019については→GitHub - tc39/ecma262: Status, process, and documents for ECMA262

ES2018についてはこっちのブランチを参照→GitHub - tc39/ecma262 at es2018

(ES8(ES2017)の実際の言語仕様についてはStandard ECMA-262を参照)

2018年3月現在の主要ブラウザでは、

ブラウザ バージョン 備考
Chrome だいたいES8(ES2017)まで
Firefox だいたいES7(ES2016)まで
Safari だいたいES7(ES2016)まで
Edge だいたいES6(ES2015)まで
IE 11 ほとんどES5まで IE11は2025年10月までサポートされる💢

のようになっている。*3

※ここから引用したよ

ECMAScript 2016+ compatibility table

JavaScriptエンジンの現在

各ブラウザベンダは、それぞれ別々のJavaScriptエンジンを使って、開発者にJavaScriptの実行環境を提供している。

ブラウザ エンジン リファレンス
Chrome V8 JavaScript Engine GitHub - v8/v8: The official mirror of the V8 Git repository
Firefox SpiderMonkey SpiderMonkey - Mozilla | MDN
Safari JavaScriptCore https://github.com/WebKit/webkit

こんな感じでまあ色々ある。

なので、前述した通りそれぞれJavaScriptの実装状況が全く違う。

つまりこうした状況で、自分たちが各々の実装を見極めて使える使えないを判定しなければいけない。

これが大変なので、polyfill(様々なブラウザに対応するためのプラグインという概念)や、後述するBabelというトランスパイラが出現することになる。

Nodeの登場によるJavaScriptの変革

話は過去に戻る。

あるとき、Node(のーど)というJavaScriptの実装が登場した。

それまでJavaScriptというのは、ブラウザベンダが実装するものであって、ぼくたちがターミナルでJavaScriptを触るという機会はほとんどなかった。*4

それがNodeというJavaScript実装が登場したことによりターミナル上で

$ node foo.js
Hello World!

のようにしてJavaScriptを実行できるようになった。

これがJavaScriptのひとつの転換期で、Node全盛の時代が始まる。そして現在もNode全盛の時代である。

npmというのは、Node Package Managerのことで、Nodeで動かすことを目的として作られたJavaScriptのライブラリを管理するためのツールである。

npmはNodeに同梱されている。

ちなみにNodeで使われているJavaScriptエンジンは、前述のV8 JavaScript Engineである。(追記: 2018/05/02 Node v10からはV8に依存しなくなったので、好きにエンジンを切り替えられるらしいです)

JavaScriptビルド時代

nodeやnpmを使用してJavaScriptの開発をするようにまで人類が成長した近代。

人類は他の言語でも使われているビルドという概念を、JavaScriptに導入したのであった。

それがGruntGulpである。タスクランナーと呼ばれている。

書いたコードを、製品として出すときに、インデントなどを削ったりしてコードのサイズを小さくしたりするために使われたり、JavaScriptでテストを実行するときにも使われた。

現在ではnpmのpackage.jsonファイルに若干存在を食われており、あまり新規で使うことはないが、まだ使われてはいる。

↓こういうかんじでつかわれてた

var gulp = require('gulp');
var browserify = require('gulp-browserify');
 
// Basic usage 
gulp.task('scripts', function() {
    // Single entry point to browserify 
    gulp.src('src/js/app.js')
        .pipe(browserify({
          insertGlobals : true,
          debug : !gulp.env.production
        }))
        .pipe(gulp.dest('./build/js'))
});

トランスパイルして古いバージョンはどんどん殺していく現代

あらゆるソフトウェアで、バージョン違い、つまり後方互換性とはものすごくめんどくさい問題だった。

サービスが広まれば広まるほど、古いバージョンを使っている人の数が増えるので、これまでは「古いバージョンをどうサポートするか」ということに主眼が置かれていた。

現在ではアップデートは自動で行われるようになり、それでもアップデートしないやつはもう知らん、という方針を人類が選択したことで、開発者が新機能を使って開発することができるようになった。

特にOS周りでその動きが顕著である。

一方JavaScriptでは、IEのサポート終了期間が長すぎるので、気軽に自動でJavaScriptをアップデートとかできなかった。

そこで誰かが「古い言語仕様にしか対応してないブラウザに対応せざるを得ないなら、新しい言語仕様で書かれたコードを、古い言語仕様のコードに変換すればよくね?」という天才の発想を思いつき、それをトランスパイルという。

このトランスパイルするやつの1つがBabel

BabelはおもにES6(ES2015)のJavaScriptをES5仕様のJavaScriptに変換する。

もっと新しい言語仕様の実装を使いたい場合はpresetというのを含めると良い。ちなみにenvというpresetをつけると最新になる(ES2017 preset · Babel)

他にもbabel-polyfill(Polyfill · Babel)などで、クロスブラウザ問題(ブラウザ間のJavaScriptの実装の違いの問題)を解決する。

そんなかんじでした。

その他

npmと bower について

NodeはもともとサーバーサイドでもJavaScript使おうぜという発想で作られたものだった。

なのでnpmは、サーバーサイドで使うJavaScriptライブラリを格納するためのものだった。いわゆるパッケージマネージャ。

bowerは、npmがサーバーサイドのものなんだから、こっちはクライアントサイドのものを入れようぜという思想のもと作られたパッケージマネージャであった。

でも、

( ^o^)<クライアントに関するライブラリはbowerで管理するぞ〜!bowerはnpm使ってインストールするぞ〜

( ˘⊖˘) 。o(待てよ、なんで敢えて分けて管理する必要があるんだ??npmで全部管理すればよくね?)

|npm|┗(☋` )┓三

( ◠‿◠ )☛ そこに気付いたか。bowerには死んでもらおう

▂▅▇█▓▒░('ω')░▒▓█▇▅▂うわあああああああああああ

ということになった。現在ではbowerは技術的負債として各々のプロジェクトに眠っている存在である。

npmとYarn

Yarnはnpmの上位互換。

npmでのnode_modules下にある、重複したライブラリを1つにしたり、新しくJavaScriptライブラリをinstallする際にキャッシュがあればそこからインストールするというように使われる。

基本yarnを使った方がいいけどまだ主流はnpmで、yarn自体もnpmでインストールする上Facebookが牛耳っているし、みんなよくわかってないので、あまり魅力を感じられていない。

[追記]コメントで指摘がありましたが、npmからじゃなくてMacだとHomebrew、WindowsだとChocolateyでやるっぽいです。昔からこうだったっけ……? → インストール | Yarn

 

全然広まらないので、そのうちyarnの機能がnpmに取り込まれるのでは説がぼくの中で結構ある。

よくわからなかったらとりあえずnpm使っとけばいい。ぼくはyarn使ってる。

webpackとは

GruntGulpなどのタスクランナーの役割に似ているが、こちらはブラウザ用にビルドするために特化したもの。

JavaScript以外にも、CSS、Sass、HTML、jpgなど、ほぼすべてのものをモジュール化して一つのJavaScriptファイルを生成するもの。これをバンドルファイルっていう。

設定をwebpack.config.jsに書くだけでよく、今は基本これ使っとけばいい。

webpack-dev-serverと組み合わせて使うとホットリロードとかされて開発しやすい。

ぼくが思ってること

JavaScriptは他の主要な言語と違ってつらみが多い。

たとえば以前、leftpadというライブラリがnpmから消されたことによって、JavaScript界隈が大混乱に陥ったことがある。

qz.com

postd.cc

いままでJavaScriptはつらすぎたので、それをなくす動きがようやく始まったよという感じがしてる。

IE対応は早めに切り捨てないとそのうち辛くなるので、早めに「IEの場合は機能限定をする」とか考えないといけないなとも思った。

でもV8 JavaScript Engineを作ってる人がWebAssemblyすごくいいよ!とか言ってるので、そのうちJavaScriptが死ぬ世界が来ても全然おかしくないと思う。

この適当な解説が、誰かの何かの役にたてば幸いです🐹 間違いとかあれば指摘ほしいです。

*1:ただしPEPのすべてが言語仕様というわけではない

*2:だからPythonはいい、JSはダメという話ではないです

*3:IE使用者が4人に1人を占めている日本ではIE対応をしないといけないことが多く、かなりつらいことがわかる。

*4:らしい。ぼくがJSに触れたときには既にNodeがあった