JavaScript
webpack
babel
prettier
parcel

JavaScript おじさんが教える本当の Modern JavaScript 入門 1

JavaScript おじさんが教える本当の Modern JavaScript 入門 1

by superyusuke
1 / 19

本発表における Modern JavaScript とは何か

Phase 1 として以下の環境での開発ができれば Modern JavaScript に入門できたものとする。

  1. Webpack, Parcel 等の module bunder による "module system" の活用。
  2. ES2015+ や TypeScript といった "Alt JS" の使用。それに伴う Babel によるトランスコンパイルツールの使用。
  3. ESlint, Prettier といった集団開発における、ソース品質安定のためのツール の使用。

ここまでのツールは、生産性が大きく上がるので、全フロントエンド開発者が使用すべきだと考える。


そもそもなぜ伝統的な JavaScript で書かないのか?

入門書で解説されている書き方と、実際の開発で使われている書き方は現在大きく異なる。なぜなのか?

// 入門書で学習する関数の宣言
function func1(val) {
  console.log(val);
}

func1("func1 test");

// 実際の開発で散見されるアロー関数(ラムダ式)による宣言
const func2 = val => console.log(val);

func2("func2 test");

JavaScript 特有の、扱いが難しい挙動をなるべく取り除き、一般的なプログラミング言語は持っているが "JavaScript にはない" 諸機能を与えるため。

今回の開発ツールを使用しない生の JavaScript で書くことはほぼないと思っていただいていい。むしろ生の JavaScript の方が「圧倒的に難しい」(体感的には三倍難しい)


1. Webpack, Parcel 等の module bunder による "module system" の活用


他のプログラミング言語には当然あるが、"JS にはない" module system を使用するためにバンドルツールを使用する。

// module ( = 別ファイルに切り出した JS ファイル) を読み込む
import module1 from './module1.js'
import module2 from './Module2.js'

module1();
const Object1 = new Module2()

これがないと、こうなる。依存関係を解決するために「特定の順番で」ファイルを読み込まなくてはいけない。ファイル数が膨大になると人間が管理することは不可能になり、アプリケーションは破壊される。

<html>
  <head></head>
  <body>
    <script src="js1.js"></script>
    <script src="js2.js"></script>
    <script src="js3.js"></script>
    <script src="js4.js"></script>
    <script src="js5.js"></script>
  </body>
</html>

Module Bundler の比較

有名なものは以下。

  • Webpack: 大規模開発案件ではほぼこれ。
  • Browserify: Webpack が主流になる前に主流だった。
  • Parcel: バンドルツールの複雑な設定を廃し、簡易的に使える。
  • Rollup: ライブラリ開発者がよく使っている。サイズが小さいらしい。

最終的には Webpack を使うようにする。しかし、まずは Parcel でモダン開発環境を導入する。


2. Alt JS の使用と Babel によるトランスコンパイル


Alt JS とは

(正確ではないかもしれないが) Alt JS とは ブラウザでは動かない、もしくは動かない可能性のある Syntax で書かれた言語で、最終的には JavaScript にトランスコンパイルされるもの。

  • ES2015+: JS のスタンダードな仕様だがブラウザがまだ追いついていない、おいおい採用される、検討中だが使いたいので追加された、といった syntax の総称。ほぼ JavaScript の見た目。
  • TypeScript: 静的型を JavaScript に組み込むための言語。ほぼ見た目は C? ですか? わかりません。
  • Elm, ReasonML とかもあります。がユーザー数からいうと上記二つがほとんど。 

そもそもなぜコンパイルする必要があるのか

フロントエンドの主戦場である「ブラウザ」が実行できるのは JavaScript のみ(WebAssembly 等は一旦脇に退ける)

そのため最終的には JavaScript にするしかない。

かといって生の JavaScript にはない機能がありすぎる。

そのため、何らかの言語で書いて、最終的に JavaScript にコンパイルするしかない。


Babel でトランスコンパイルする

試しに CLI ツールでコンパイルする

npm install --save-dev babel-cli # CLI をいれる
npx babel src -d lib 
# src の中身をガッとコンパイルして lib に吐き出す

Babel の設定は .babelrc というファイルに書く(ディレクトリ直下に置くのが簡易的な開発では一般的)

例えば Babel の挙動を変更するプラグインをインストールして、それを使う設定

npm install babel-preset-env --save-dev
.babelrc
{
  "presets": ["env"]
}

Parcel を使っておけば Babel によるトランスコンパイル, Module Bundle はやってくれるのでまずは後半の演習でこれを使う。


ESlint, Prettier といった集団開発における、ソース品質安定のためのツールの使用


定番ツール

  • ESLint: 不備があったり、バグに繋がりやすい syntax で書かれているものを見つけてエラーを吐くツール。そのルールもカスタマイズできる。
  • Prettier: 主に JavaScript のコードを成形してくれるツール。誰が書いても、このツールを実行すればかならず同じ形にしてくれるので、楽。

Prettier を使う

npm install --save-dev --save-exact prettier # インストール

WebStorm を使っている人なら command + option + shift + p で勝手に Prettier が発動する。Atom, VSCode 等々各種エディターにプラグインがあるのでこれを使うのが良い。

設定ファイルに細々書く。

  • シングルクオートを使う
  • セミコロンは使わない
  • 追コンマは常に使用する
.prettierrc
{
  "singleQuote": true,
  "semi": false,
  "trailingComma": "all"
}

するとこうなる。

const obj1 = {
  name: 'name1',
  age: '30', // 追いコンマ
}

演習1: Parcel で Modern JavaScript 開発環境を作る

https://github.com/superyusuke/minumum-modern-front-end-setting

  • parcel-bundler が本体
  • node-sass は sass を使う際に必要
  • babel-plugin... は babel に色々なシンタックスを使用できるようにするために必要
package.json
{
  "dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1"
  },
  "devDependencies": {
    "babel-plugin-syntax-object-rest-spread": "^6.13.0",
    "node-sass": "^4.9.3",
    "parcel-bundler": "^1.9.7",
    "prettier": "^1.14.2"
  }
}

npm script で parcel を実行する。

同じくpackage.json
"scripts": {
    "start": "npm run parcel:dev",
    "parcel:dev": "npx parcel src/index.html",
    "parcel:build": "npx parcel build src/index.html --out-dir build"
}

src/index.html で src/js/index.js を読み込んでいる。この js ファイル内で import されているファイルは全部うまいことバンドルしてくれる。Babel でトランスコンパイルもしてくれる。

Screen Shot 2018-08-22 at 5.18.15 PM.png


すると次のようにモダンな JS を書く環境ができる。

import '../scss/index.scss' // sass を読み込む
import 'babel-polyfill' // async 系で必要っぽい

// import module
import module1 from './module1'
console.log(module1, 'module 1')

import React from 'react'
import ReactDOM from 'react-dom'

// react component
class HelloMessage extends React.Component {
  render() {
    return <div>Hello {this.props.name}</div>
  }
}

// render react component
const mountNode = document.getElementById('app')
ReactDOM.render(<HelloMessage name="Jane" />, mountNode)

// async / await
const url = 'http://api.myjson.com/bins/159wqn'
const asyncFunc = async url => {
  console.log(await fetch(url), 'fetch result')
}

asyncFunc(url).then(() => console.log('fetch done (in then)'))

// object rest spread
const obj1 = { value: 1 }
const obj2 = { value: 2 }
const obj3 = { test: 'hey' }
const combinedObject = { ...obj1, ...obj2, ...obj3 }
console.log(combinedObject, 'combined object')

const func1 = ({ test }) => console.log(test)
func1(combinedObject)

Phase 1 のまとめ

  • Parcel で module system が使えるようになった。
  • Parcel で Babel の処理をしてくれるので、ES2015+ syntax で JS を書くことができるようなった。
  • Parcel が勝手に JSX も処理してくれるので React コンポーネントを JSX で書けるようになった。
  • Prettier でコードが成形できるようになった。

Phase 2 の展望

モダンなパラダイムで JavaScript を書く

  • var, let を書かないで、ほぼ全部 const にする。
  • そのためには functional programming に則っていく必要あり。
  • map, reduce 等をうまく使う。
  • immutable

Phase 3 の展望

非同期処理をモダンに書く

  • Callback の根絶
  • Promise の理解
  • async / await を使う
  • redux/vuex 関係でも async/await を使う
const url = 'http://api.myjson.com/bins/159wqn'

const asyncFetch = async url => {
  const res = await fetch(url)
  const { data } = res
  console.log(data)
}

asyncFetch(url).then(() => console.log('done'))

Phase 4 の展望

Virtual DOM を用いた View ライブラリの活用

  • ReactJS
  • VueJS
  • Redux/Vuex