kurodakazumichi / issues

0 stars 0 forks source link

【Babel】導入と使い方 #26

Open kurodakazumichi opened 6 years ago

kurodakazumichi commented 6 years ago

BabelはブラウザにまだサポートされていないようなJavaScriptの次世代の標準機能を、現在のブラウザでも使えるようにするNode.js製のトランスパイラです。

メモ

Babelの手ほどき 前編 Babelとは ES6の新機能

kurodakazumichi commented 6 years ago

BabelとAltJS(AlternativeJavascript)

AltJSとは何か?

Alternative(代替) Javascriptという事で、JavaScriptの代わりに使えるJavaScript もう少し具体的にいうとこんな感じ

  1. AltJSでコードを書く
  2. コンパイルする
  3. JavaScript(本物)が出来上がる

AltJSにはCoffeeScriptTypeScriptといったものがある。(それぞれ文法も違う)

CoffeeScriptで学ぶJSの設計 TypeScriptことはじめ

ではBabelとは何か

Babelでは純粋なJavaScriptを書く。代替言語ではないということ。 ECMAScript6という正当なJavaScriptでコードを記述するが ES6はまだ完全に対応されたわけでもない。

というわけで、ES6で書いたコードをES5に変換するというのがBabelだ。 未来に備えてES7にも対応されていくようだ。

kurodakazumichi commented 6 years ago

Babelのインストール

 npm install --save-dev babel-cli

パッケージはbabelではなくbabel-cli。 昔はbabelだったが、現在はbabel-cliが推奨されているようだ。 またbabelはグローバルに入れるのもイケてないっぽいのでプロジェクトにインストール。

グローバルにいれるのがイケてない理由

同じマシーン内であってもプロジェクトにより異なったバージョンのBabelに依存していることもあり、別々にアップデートできるようにするため。 自分の作業環境だけでなく、簡単に別の環境でもセットアップできるようにするため。

kurodakazumichi commented 6 years ago

babel入れたのにコマンドがないって怒られるぞ

babel --version

babel : 用語 'babel' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してください。

https://stackoverflow.com/questions/34421513/babel-command-not-found ここで似たような症状で悩める人を発見。

理由はわからないが、ローカルには確かにインストールされている./node_modules/.bin/babel ここにパスが通っていないようだ(Windowsだから?)

試しに相対パスで直接指定したらうまくいった

.\node_modules\.bin\babel --version

6.26.0 (babel-core 6.26.0)

解決策 その1

環境パスを一時的に追加する。

この方法だとcmd起動するたびに毎回設定しないといけないのでやや面倒。

解決策 その2

package.jsonのスクリプトを使う。

package.json

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "babel": "babel"
  },
npm run babel -- --version

package.jsonscriptsに書いたコマンドはnpm run babelのようにして呼び出せる。 またscriptsに書かれたコマンドを呼ぶ場合は./node_modules/.bin.にパスが通るらしい。 npm run-scriptに引数を渡す

この方法で実行すれば自由に引数を指定してbabelを実行できる。

kurodakazumichi commented 6 years ago

コンパイルは出来るけどES5に変換されないぞ

大前提:Windows標準のコマンドプロンプトでコマンド実行すること なぜかAtom上のTerminalだとうまくいかないから。

sample.js

class App {
  constructor() {
    console.log('class syntax');
  }
}

const func = () => {
  console.log('arrow function');
};
npm run babel -- sample.js

これをコンパイルしても全く同じjsファイルが出力されるだけ。

どうやらbabelだけでは何もしてくれないらしい

ES5に変換するには上記の2ステップ必要なようだ。 参考にしたサイト

babel-preset-es2015を入れる

npm install --save-dev babel-preset-es2015

.babelrcを作成する

.babelrc

{
  "presets":["es2015"]
}

これでnpm run babel -- sample.jsすることで無事ES5にコンパイルできました。

※AtomにいれていたTerminal系のプラグインだとうまくいかずエラーがでまくります。 原因は不明だが、Atomのターミナルは普通のコマンドプロンプトと違うので パス周りがなんかおかしい気がしている。

kurodakazumichi commented 6 years ago

コードをさくっと実行するbabel-node

babel-nodeコマンドを使うと、ソースコードのコンパイルと実行を同時にやってくれる。

sample.js

class App {
  constructor() {
    console.log('class syntax');
  }
}

const func = () => {
  console.log('arrow function1');
};

const func2 = () => {
  console.log('arrow function2');
};

new App();
func();
func2();

コマンド

babel-node sample.js

class syntax arrow function1 arrow function2

kurodakazumichi commented 6 years ago

外部ファイルを読み込んで使う

普通のプログラムなら当然のように出来るが、javascriptにはそういった機能がなかった。 Babelを使う事で、機能単位などでファイルを分割し、使いたいところで読み込んで使う事ができる。

greeting.js

export function hello() {
  console.log("Hello");
};

export function bye() {
  console.log("good bye");
};

外部に公開するものにはexportを付ける

関数だけじゃなく、変数などもexportで公開できるようになる。

main.js

import * as greeting from "./greeting.js";

greeting.hello();
greeting.bye();

読み込みたい場合はimportを使う

import 使いたいもの as 別名 from 読み込むファイル
kurodakazumichi commented 6 years ago

外部ファイル読み込みはブラウザではエラーになる問題

build.js:上記のmain.jsをbabelでコンパイルしたjsファイル

"use strict";

var _greeting = require("./greeting.js");

var greeting = _interopRequireWildcard(_greeting);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

greeting.hello();
greeting.bye();

index.html:build.jsを読み込んだindex.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>test</title>
  </head>
  <body>
      babelで作ったjavascriptを読み込むテスト。
      consoleでエラーでてたら想定通り。
  </body>
  <script src="./build.js"></script>
</html>

想定通りだがエラーになる

var _greeting = require("./greeting.js");

Uncaught ReferenceError: require is not defined at build.js:3

requireなんてないよと、そもそもブラウザでサポートされてるものじゃない。 でもブラウザでrequire使いたいよという希望をかなえてくれてるものがあるらしい

その名は「requireJS」、require.jsというjsを読み込むことで ブラウザ上でもrequireを使えるようにするライブラリ。

<script data-main="js/main.js" src="bower_components/requirejs/require.js"></script>

書き方がちょっと特殊

kurodakazumichi commented 6 years ago

requireをブラウザで使うための方法

このため Webpack か Browserify を利用して解決するというのが、現在の一般的なアプローチ。 ということらしい。

kurodakazumichi commented 6 years ago

Browserifyを使ってみる

npm install --save-dev browserify babelify

browserifybabelifyを入れる必要があるらしい。 インストールが終わったら

browserify main.js -t babelify -o output.js

output.jsは必要なスクリプトが全部1ファイルにまとまったファイルとしてでてくる。

output.jsを先ほどのindex.htmlに読み込ませてみたところ

Hello good bye

外部ファイルに定義した処理をちゃんと呼び出せてる。

kurodakazumichi commented 6 years ago

BrowserifyとBabelify?

Browserifyとは

Browserifyはrequire構文をブラウザでも利用できるようにするためのパッケージです。

Babelifyとは

babelifyはBrowserifyのtransformでBrowserifyの処理の中にbabelの処理を組み込めるモジュールです。

ふむ。

どうやらこういう関係性らしい

  1. babelはimport/exportをrequire()形式に変換してくれる
  2. ブラウザがrequireに対応してないから動かない
  3. Browserifyはrequireをブラウザで使えるようにしてくれる奴
  4. BabelifyはBrowserifyの処理の中にbabelの処理を組み込める。

うーん、やってることはわかったけど仕組みがなぞい。 そして色んなライブラリがわんさか登場するつらみ。