こちらの記事は、2017年10月に公開された
『Modern JavaScript Explained For Dinosaurs』の和訳になります。
本投稿は転載であり、本記事はこちらになります。
はじめに
あなたがJavaScriptの進化と共に歩んでこなかったのであれば、今のJavaScriptを学ぶことは難しく感じるでしょう。エコシステムは急速に成長し変化しているため、さまざまなツールが解決しようとしている問題を理解することは困難です。私は1998年からプログラミングを始めて、2014年になって初めてJavaScriptを真剣に学び始めました。当時私はBrowserifyに出会い 、そのキャッチフレーズを見たことを覚えています。
「Browserifyは、あなたの依存関係のすべてをまとめることによって、ブラウザでrequire(‘modules’) を使えるようにします。」
私はこの文章中の単語をほとんど理解しておらず、開発者にとってどのように役立つかのかわかりませんでした。
この記事の目的は、JavaScriptに関連するツールがどのように進化して2017年時点の形になったかという歴史的背景を説明することです。最初から始めて、サンプルのウェブサイトを作成します。恐竜のようにツールは使用せずに、HTMLとJavaScriptだけを使います。その後に私達は一つずつ、問題を解決するためにツールを適用していきます。JavaScriptの進化の歴史をトレースすることで、変化し続けるJavaScriptの状況を学び、順応することができます。それでは、始めましょう!
JavaScriptを「昔ながらの」方法で使う
HTMLとJavaScriptを使用して、手動でファイルをダウンロードしてリンクする「昔ながらの」Webサイトから始めましょう。これは、JavaScriptファイルをリンクする単純なindex.htmlファイルです。
<! DOCTYPE HTML>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>JavaScript Example</title>
<script src="index.js"></script>
</head>
<body>
<h1>Hello from HTML!</h1>
</body>
</html>
console.log("Hello from JavaScript!");
これがウェブサイトを作るために必要なすべてです!このウェブサイトに、あなたがmoment.jsのような他の人が書いたライブラリ(人間が読める形式で日付をフォーマットするのを助けることができるライブラリ)を追加するケースを考えましょう。
たとえば、次のようにJavaScriptでmomentが提供する関数を使用できます。
moment().startOf('day').fromNow(); // 20時間前
しかし、これはあなたのウェブサイトにmoment.jsを含んでいることを前提としています!
moment.jsのホームページには、次のような内容があります。
画面右側の「インストール」セクションにはたくさんのインストール方法が書かれてていますが、今は無視してください。
HTMLファイルと同じディレクトリにmoment.min.jsファイルをダウンロードし、moment.jsをindex.htmlファイルから参照することでウェブサイトに追加します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
<link rel="stylesheet" href="index.css">
<script src="moment.min.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>Hello from HTML!</h1>
</body>
</html>
moment.min.jsをindex.jsより前にリンクしていることに注意してください。index.jsより前にロードすることで、momentが提供する関数を使用できます。
console.log("Hello from JavaScript!");
console.log(moment().startOf('day').fromNow());
このように、他の人が書いたJavaScriptライブラリを使ったウェブサイトを作ることができます!昔ながらの方法のメリットは、理解するのが簡単だということです。デメリットは、ライブラリが更新されるたびに新しいバージョンのライブラリを見つけてダウンロードするという面倒な作業が発生することです。
JavaScriptパッケージマネージャを使用する(npm)
2010年頃から、いくつかの競合するJavaScriptパッケージマネージャが登場し、中央リポジトリからライブラリをダウンロード(アップグレード)するプロセスを自動化できるようになりました。2013年にはBowerが間違いなく最も人気がありましたが、2015年頃にはnpmに追い越されました。( yarnはnpmの代わりとして2016年末ごろから多くの注目を集めていますが、内部ではnpmのパッケージを使用しています。)
npmはもともとnode.js というサーバー上で動作するように設計されたJavaScriptランタイムのために作られたパッケージマネージャでした。そのため、ブラウザで動くJavaScriptのパッケージマネージャとして選択するのは奇妙に感じるでしょう。
注意:パッケージマネージャを使うためには、一般的にコマンドラインを使う必要があります。フロントエンド開発者はこれまでコマンドラインを使う必要がほとんどありませんでした。コマンドラインを一度も使用したことがない場合は、 このチュートリアルを読んで概要を把握してから始めることができます。良くも悪くも、コマンドラインの使い方を知ることは現代のJavaScriptでは重要な要素になります(そしてそれは他の開発分野にも扉を開きます)。
それでは、手動でライブラリをダウンロードするのではなく、npmを使用してmoment.jsパッケージを自動的にインストールする方法を見てみましょう。node.jsがインストールされている場合は、すでにnpmもインストールされています。コマンドプロンプトなどのターミナルを開き、index.htmlファイルがあるフォルダに移動してから次のコマンドを実行します。
$ npm init
いくつかの質問が表示され(デフォルトは大丈夫です。質問ごとに「Enter」を押すとデフォルトが選択されます)、package.jsonという名前の新しいファイルが生成されます。これは、npmがすべてのプロジェクト情報を保存するために使用する設定ファイルです。デフォルトでは、package.jsonの内容は次のようになります。
{
"name": "your-project-name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
次のコマンドを実行して、moment.js パッケージをインストールすることができます。
$ npm install moment --save
このコマンドは2つのことを行います 。
最初に、moment.jsパッケージのすべてのコードをnode_modulesというフォルダーにダウンロードします。
次に、package.jsonファイルを自動的に変更して、プロジェクトの依存関係としてmoment.jsを保持します。
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.22.2"
}
}
これは後で他の人とプロジェクトを共有するときに便利です。node_modulesフォルダ(非常に大きくなることがある)を共有する代わりに、package.jsonファイルを共有するだけでよく、他の開発者はコマンドnpm installで必要なパッケージを自動的にインストールできます。
npmを使うことで、Webサイトからmoment.jsを手動でダウンロードする必要はなくなりました。npmを使用すれば自動的にダウンロードして更新できます。
node_modulesフォルダーの中を見ると、node_modules/moment/minディレクトリにmoment.min.jsファイルがあります。そのため、次のようにしてindex.htmlファイルからnpmダウンロード版のmoment.min.jsを参照できます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript Example</title>
<script src="node_modules/moment/min/moment.min.js"></script>
<script src="index.js"></script>
</head>
<body>
<h1>Hello from HTML!</h1>
</body>
</html>
メリットは、コマンドラインからnpmを使ってパッケージをダウンロードして更新できるようになったことです。
デメリットは、node_modulesフォルダーを調べて各パッケージの場所を見つけ、それを手動でHTMLに記載しなければいけないことです。あまりにも不便なので、次にそのプロセスを自動化する方法を見てみましょう。
JavaScriptモジュールバンドラー(webpack)を使う
ほとんどのプログラミング言語は、あるファイルから別のファイルにコードをインポートする方法を提供します。しかし、JavaScriptはこの機能を使用できるように設計されていませんでした。JavaScriptはブラウザ上で実行されるように設計されていて、セキュリティ上の理由からクライアントのコンピュータのファイルシステムにアクセスできないからです。そのため、長い間JavaScriptコードを複数のファイルにまとめるには、各ファイルをグローバルに共有する変数に読み込む必要がありました。
これは実際にmoment.jsの例で行っていることです - moment.min.jsファイル全体がグローバル変数momentに格納され、HTMLにロードされます。moment変数はmoment.min.jsの後にロードされたどのファイルでも利用可能です。(アクセスする必要がないファイルでも参照できてしまいます)
2009年には、ブラウザの外部で動作するJavaScriptのエコシステムの仕様を決めることを目的として、CommonJSというプロジェクトが開始されました。CommonJSの大部分はモジュールの仕様でした。CommonJSにより、JavaScriptはほとんどのプログラミング言語と同じように、グローバル変数を使用せずに直接コードをインポートおよびエクスポートすることができるようになりました。CommonJSモジュールの実装で最もよく知られているのはnode.jsです。
前述したように、node.jsはサーバー上で動作するように設計されたJavaScriptランタイムです。下記のコードは、moment.jsをnode.jsで使う場合のサンプルになります。HTMLスクリプトタグでmoment.min.jsをインポートする代わりに、次のようにJavaScriptファイルから直接読み込むことができます。
var moment = require('moment');
console.log("Hello from JavaScript!");
console.log(moment().startOf('day').fromNow());
繰り返しになりますが、これがnode.jsでモジュールをロードする仕組みです。node.jsはコンピュータのファイルシステムにアクセスできるサーバーサイドの言語なので、とてもうまくいきます。node.jsはnpmモジュールの位置も知っているので、require( 'node_modules/moment/min')と書く必要はなく、単にrequire(' moment ')と書くことができます。
node.jsを動かす場合にはとても良い仕組みなのですが、ブラウザで上記のコードを使用しようとすると、requireが定義されていないというエラーが表示されます。ブラウザはファイルシステムにアクセスすることができないため、この方法でモジュールをロードするためには複雑な方法をとる必要があるということです。 - ファイルのロードは動的に、同期的(実行速度を落とす)または非同期(タイミングの問題がある)に行う必要があります。
そこで、モジュールバンドラーを導入します。JavaScriptモジュールバンドラーは、ビルドステップ(ファイルシステムへのアクセス権を持つタイミング)で問題を回避するツールです。ファイルシステムへのアクセスする必要がない、ブラウザ互換性のあるファイルを作成します。このケースでは、すべてのrequireステートメント(ブラウザのJavaScriptでは無効な構文)を見つけて、リンクする先の内容に置換するモジュールハンドラが必要になります。最終的な出力は単一のバンドルされたJavaScriptファイルとなります(requireステートメントは含まれていません)。
2011年にリリースされ、フロントエンドでのnode.jsスタイルのrequireステートメントの使用法の先駆けとして、最も人気のあるモジュールバンドラーはBrowserifyでした(これが本質的にnpmをフロントエンドパッケージマネージャーとして使用することを可能にしました)。2015年頃には、webpackがより広く使用されるモジュールバンドラーとなりました(webpackのさまざまな機能をフルに活用したReactフロントエンドフレームワークの普及により促進されました)。
ブラウザで前述したのrequire('moment')の例を動かすためにwebpackを使う方法を見てみましょう。最初にwebpackをプロジェクトにインストールする必要があります。webpack自体はnpmパッケージなので、コマンドラインからインストールできます。
$ npm install webpack webpack-cli --save-dev
webpackとwebpack-cliの2つのパッケージをインストールしていることに注意してください(これでコマンドラインからwebpackを使用できます)。--save-devを引数とすることで開発時の依存関係として保存されます。つまり、本番サーバーではなく開発環境で必要なパッケージとなります。package.jsonファイルに反映されて、自動的に更新されてます。
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.19.1"
},
"devDependencies": {
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0"
}
}
これでwebpackとwebpack-cliがパッケージとしてnode_modulesフォルダにインストールされました。次のようにコマンドラインからwebpack-cliを使用できます。
$ ./node_modules/.bin/webpack index.js --mode=development
このコマンドは、node_modulesフォルダーにインストールされたwebpackツールを実行し、index.jsファイルから始めて、requireステートメントを見つけ、それらを適切なコードに置換して単一の出力ファイル(デフォルトではdist/main.js)を作成します。
--mode = development引数を使用することで出力されたJavaScriptは開発者にとって読みやすい形式となります。(引数--mode = productionを使用した場合、出力されるJavaScriptは圧縮されます)
webpackにより出力されたdist/main.jsはrequireステートメントを含まないため、ブラウザでindex.jsの代わりに参照することができます。次のようにindex.htmlファイルに反映します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript Example</title>
<script src="dist/main.js"></script>
</head>
<body>
<h1>Hello from HTML!</h1>
</body>
</html>
ブラウザを更新すると、すべてが以前と同じように機能していることがわかります。
index.jsを変更するたびにwebpackコマンドを実行する必要があることに注意してください。これは面倒で、webpackのより高度な機能を使用するにつれてさらに面倒になるでしょう(変換されたコードから元のコードをデバッグするのを助けるためにソースマップを生成するなど)。
webpackはwebpack.config.jsというプロジェクトのルートディレクトリにある設定ファイルからオプションを読み取ることができます。
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'main.js',
publicPath: 'dist'
}
};
index.jsを変更するたびに、次のコマンドでwebpackを実行できます。
$ ./node_modules/.bin/webpack
webpackはwebpack.config.jsファイルからこれらのオプションを読み込んでいるので、index.jsと--mode = developmentオプションを指定する必要はもうありません。
これは優れていますが、コードを変更するたびにこのコマンドを入力するのは面倒です - 後でこのプロセスを少しスムーズにします。
全体的に見ると大したことではないかもしれませんが、このワークフローにはいくつかの大きな利点があります。グローバル変数を介して外部スクリプトをロードすることはもうありません。
HTMLに新しく<script>タグを追加するのではなく、JavaScriptのrequireステートメントを使用して新しいJavaScriptライブラリを追加します。単一のJavaScriptバンドルファイルを使用することになるので、多くの場合パフォーマンスが向上します。
そして、ビルドステップを追加したため、他にも開発ワークフローに追加できる強力な機能がいくつかあります。
新しい言語機能のためのコード変換(babel)
コード変換とは、ある言語のコードを別の言語の同等なコードに変換することです。これはフロントエンド開発では重要なポイントとなります - ブラウザは新しい機能を追加するのが遅いので、新しい言語はブラウザの互換言語にTranspileする実験的な試みとして作成されました。
CSSには、 Sass 、Less 、Stylusがあります。JavaScriptでは、しばらくの間最も人気のあるtranspilerはCoffeeScript (2010年頃にリリース)でしたが、今日ではほとんどの人がbabelかTypeScriptを使っています。CoffeeScriptは、言語を大幅に変更(オプションの括弧、重要な空白など)することによってJavaScriptを改善することに焦点を当てた言語です 。
Babelは新しい言語ではなく、すべてのブラウザでは利用できない機能(ES2015以降の機能)を備えた次世代のJavaScriptを古い互換性のあるJavaScript(ES5)に変換するTranspilerです。TypeScriptは、次世代のJavaScriptと本質的に同一の言語ですが、オプションの静的型付けも追加します。多くの人が標準仕様に近いbabelを選択しています。
既存のwebpackのビルド手順でbabelを使用する方法の例を見てみましょう。まず、コマンドラインからプロジェクトにbabel(これはnpmパッケージです)をインストールします。
$ npm install @babel/core @babel/preset-env babel-loader --save-dev
開発時の依存関係として3つの別々のパッケージをインストールしていることに注意してください - @babel/coreはbabelの主要部分です、 @babel/preset-envはどの新しいJavaScript機能をTranspileするか定義するプリセットです、そしてbabel-loaderはwebpackでbabelを使えるようにするためのパッケージです。次のようにwebpack.config.jsファイルを編集することで、babel-loaderを使用するようにwebpackを設定できます。
module.exports = {
mode: 'development',
entry: './index.js',
output: {
filename: 'main.js',
publicPath: 'dist'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};
構文はわかりにくいですが、幸いなことに編集ことがほとんどありません。webpackに.jsファイル(node_modulesフォルダ内のものを除く)を探して、babel-loader
と@babel/preset-env
プリセットを使用してbabelの変換を適用するように指示しています。あなたはここで webpack設定構文についてもっと読むことができます。
これですべての設定が完了したので、JavaScriptでES2015機能を使用すことができます。これは、index.jsファイル内のES2015テンプレート文字列の例です。
var moment = require('moment');
console.log("Hello from JavaScript!");
console.log(moment().startOf('day').fromNow());
var name = "Bob", time = "today";
console.log(`Hello ${name}, how are you ${time}?`);
モジュールをロードするためにrequireの代わりにES2015 importステートメントを使うこともできます。これは今日多くのコードベースで見られるでしょう:
import moment from 'moment';
console.log("Hello from JavaScript!");
console.log(moment().startOf('day').fromNow());
var name = "Bob", time = "today";
console.log(`Hello ${name}, how are you ${time}?`);
この例では、import構文はrequire構文とそれほど違いはありませんが、importはより高度な場合にはさらなる柔軟性を持ちます。index.jsを変更したので、コマンドラインで再度webpackを実行する必要があります。
$ ./node_modules/.bin/webpack
ブラウザでindex.htmlを更新してみましょう。これを書いている時点で、最近のほとんどのブラウザはES2015のすべての機能をサポートしているので、babelが動いたことを見分けるのは難しいかもしれません。IE9のような古いブラウザでテストするか、bundle.jsを検索して変換されたコードの行を見つけることができます。
// ...
console.log('Hello ' + name + ', how are you ' + time + '?');
// ...
ここでは、ブラウザの互換性を維持するために、babelがES2015テンプレート文字列を通常のJavaScript文字列連結に変換したことがわかります。この例はそれほど面白くないかもしれませんが、コードを変換する機能は非常に強力です。より良いコードを書くために、async/awaitのようなJavaScriptの刺激的な新機能を今日から使い始めることができます。コード変換は時に退屈で苦痛に思えるかもしれませんが、多くの人々が新機能を試すことで、過去数年間で言語の劇的な改善をもたらしました。
ほとんどの説明をしましたが、ワークフローにはいくつか未完成の部分があります。パフォーマンスが心配な場合は、バンドルファイルを圧縮する必要があります。既にビルドステップを組み込んでいるので、簡単に実行できます。また、JavaScriptを変更するたびにwebpackコマンドを再実行する必要があります。次はこれらの問題を解決するための便利なツールについて紹介します。
タスクランナーを使用する(npmスクリプト)
JavaScriptモジュールが動くためのビルドステップができたので、ビルドプロセスのさまざまな部分を自動化するツールであるタスクランナーを使用すると効果的です。フロントエンド開発の場合、タスクにはコードの圧縮、画像の最適化、テストの実行などがあります。
2013年、Gruntは最も人気のあるフロントエンドのタスクランナーでした。Gulpはそのすぐ後に続きました。どちらも他のコマンドラインツールをラップするプラグインに依存しています。今日最も人気のある選択は、npmパッケージマネージャ自身に組み込まれているスクリプト機能を使用することです。これはプラグインを使用せず、代わりに他のコマンドラインツールで直接動作します。
webpackを使いやすくするためのnpmスクリプトを書いてみましょう。これは簡単で、package.jsonファイルを次のように変更するだけです。
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --progress --mode=production",
"watch": "webpack --progress --watch"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.22.2"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.2",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0"
}
}
ここで、buildとwatchという2つの新しいスクリプトを追加しました。ビルドスクリプトを実行するには、コマンドラインに次のように入力します。
$ npm run build
コマンドを実行すると、(前に作成したwebpack.config.jsの設定を使用して)webpackを進捗率を示す--progressオプションと、本番用のコードを最小化する--mode = productionオプションを付けて実行します。watchスクリプトを実行するには次のコマンドを実行します。
$ npm run watch
webpackの--watchオプションの代わりに、JavaScriptファイルを検知して自動的にリビルドするために使います。開発時に最適なコマンドです。
node.jsは各npmモジュールパスの場所を知っているので、package.jsonのスクリプトはフルパス./node_modules/.bin/webpackを指定しなくてもwebpackを実行できます。とても便利です1webpack-dev-serverをインストールすることで、さらに便利になります。これは、シンプルなWebサーバーとリロードによる自動反映機能を提供する別のツールです。開発時のみに使う設定でインストールするには、次のコマンドを入力します。
$ npm install webpack-dev-server --save-dev
次に、package.jsonにnpmスクリプトを追加します。
{
"name": "modern-javascript-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --progress -p",
"watch": "webpack --progress --watch",
"server": "webpack-dev-server --open"
},
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.19.1"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.2",
"webpack": "^3.7.1",
"webpack-dev-server": "^3.1.6"
}
}
次のコマンドを実行して開発サーバーを起動できます。
$ npm run server
実行すると、localhost:8080のindex.htmlをブラウザで自動的に開きます(デフォルト設定)。JavaScriptを変更するたびに、webpack-dev-serverはそれ自身のバンドルされたJavaScriptを再構築し、ブラウザを自動的に更新します。新しい変更を確認するためにコードとブラウザの間でコンテキストを絶えず切り替える必要がなく、コードに集中することができるので、これは驚くほど便利で時間の節約になります。
ここでは、簡単な機能を紹介しただけで、webpackとwebpack-dev-serverの両方にたくさんのオプションがあります(詳細はここで読むことができます )。もちろん、SassからCSSへの変換、画像の圧縮、テストの実行など、他のタスクを実行するためのnpmスクリプトを作成することもできます。コマンドラインツールを備えたものは、公平に適用することができます。npmスクリプト自体に関する優れた高度なオプションやテクニックもいくつかあります。Kate Hudsonによる講演は、入門には最適です。
結論
一言で言えばこれがモダンなJavaScriptです。HTMLとJSから、サードパーティのパッケージを自動的にダウンロードするためのパッケージマネージャ、単一のスクリプトファイルを作成するためのモジュールバンドル、将来のJavaScript機能を使用するためのTranspiler、そしてビルドプロセスのさまざまな部分を自動化するためのタスクランナーを使いました。特に初心者には参考になるでしょう。Web開発は、プログラミングに慣れていない人にとっては、起動と実行が非常に簡単だったために、非常に優れた入口でした。しかし今日では、さまざまなツールが急速に変わる傾向があるため、初心者がついていくのは非常に困難です。
それでも、それほど悪くはありません。フロントエンドでも実行可能な方法としてnodeエコシステムを採用することで、状況は落ち着いてきました。パッケージマネージャとしてnpm、モジュールのためのnode requireまたはimportステートメント、そしてタスクを実行するためのnpmスクリプトを使うことにより、多くのメリットがあり、一貫した方法を提供します。これは1〜2年前と比較しても非常に単純化されたワークフローです。
ほとんどのフレームワークにはプロセスを開始しやすくするために、初心者も熟練開発者も使えるツールが付属しています。例えばEmberにはember-cliがあります 。これはAngularのangular-cli 、Reactのcreate-react-app 、Vueのvue-cliなどに大きな影響を与えました。これらのツールはすべて、すぐにコードを書き始められるようにプロジェクトをセットアップします。しかし、これらのツールは魔法のようなものではなく、単にすべてを一貫した作業方法で設定するだけです。そのため、この記事で説明したようにwebpack、babelなどを使用するための特別な設定を行う必要があります。
JavaScriptは急速に変化し進化し続けているので、イライラすることもあるでしょう。時には車輪を再発明しているように思えるかもしれませんが、JavaScriptの急速な進化は、ホットリロード、リアルタイムな構文チェック、およびタイムトラベルデバッグなどの革新を推進するのに役立ちました。今は、開発者になるのは刺激的なタイミングです。この記事があなたの旅をお手伝いするロードマップとして役立つことを願っています!
最後に、2003年以来最高の不条理なユーモア(恐竜がウェブを支配したとき)を提供してきたryanqnorthのDinosaur Comicsに特別な感謝を述べます。
翻訳協力
Author:Peter Jang(https://medium.com/@peterxjang)
Thank you for letting us share your knowledge!
記事選定: @takitakis
翻訳/技術監査: @aoharu / @azumana
Markdown化: @aoharu