17
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

babel-plugin-macrosは何がすごいのか

Last updated at Posted at 2020-02-27

どうも、こんにちは。

一人で babel-plugin-macros タグを占有している者です。

そんな、babel-plugin-macrosは何がすごいのでしょうか?

babel-plugin-macros (babelの作者によるリポジトリ)

Allows you to build simple compile-time libraries

(訳)シンプルな compile-time ライブラリを作れるようにします

compile-timeライブラリとは、

コンパイル時に実行されるライブラリを指しています。

まずは要領を得てもらうために、

penv.macro をご紹介しましょう。

これはNODE_ENVにより「環境ごとの値」に値を分けるコードです。

import env from 'penv.macro'

const BASE_URL = env({
  development: 'https://development.example.com',
  staging: 'https://staging.example.com',
  production: 'https://production.example.com',
})

ええ、普通にパッと見ただけだと、「こんなの誰だって作れるやい!」って思うでしょう。

でも、これは下のようなコードにコンパイルされるんですよ。

const BASE_URL = 'https://production.example.com'

つまり「実行時のオーバーヘッドはない」のです。

しかも、いつも通りimportするだけで使えるんです。

import env from 'penv.macro'

Webpackで必要になるような細かい設定は必要ないんです。

(もちろん、拡張用の設定手段は提供されているのですが)

もう少し具体的に説明していきます。

なぜbabel-plugin-macrosは生まれたのか

経緯は、こちらの記事にまとめられています。

Zero-config code transformation with babel-plugin-macros

タイトルからもわかるように、

  • ゼロコンフィグによるコード変換を行うこと

をミッションにbabel-plugin-macrosは生まれました。

babel は本来、ECMAScriptの基準に達していないブラウザでコードが動作することを目的に作られましたが、

今、それ以上のものなろうとしています。

それは構文拡張ではなく「コード変換」によりもたらされるもので、

  • コンパイル時の最適化のために、「コード変換」をカスタマイズするためのライブラリを作る手段を提供しよう!

というのが、babel-plugin-macrosのもたらすものなのです。

もちろん今までも、babel-plugin-xxによって提供されてきました。

しかし、それには「いくつかの問題」がありました。

  1. コードを見たときに、そこで「コード変換」が行われていることが明示的でないため、混乱が生じることがあった。
  2. グローバルな設定が必要で、しかもそれらは.babelrcwebpackのようなコードの外で行わなければいけない。
  3. 複数のプラグインが、1度のAST解析の中で同時に行われる。そのせいで衝突が発生したりする。

皆さんは、プラグインの衝突・それらの管理・訳のわからないエラーに悩まされてきたことはないですか?

Gatsby とか Create React App 使ってるから無い?

でも、Gatsby とか Create React App を作っている人たちは悩まされてきたのかもしれません。

だから、彼らもbabel-plugin-macrosを使っているんです。

その証拠に、Gatsby / Create React App 内では、xx.macro系のライブラリがデフォルトで利用できます。

インストール

でも、それ以外の人たちも、インストールして.babelrcを設定してあげれば、すぐに使えるようになります。

npm install --save-dev babel-plugin-macros
.babelrc
{
  "plugins": ["macros"]
}

簡単ですね。

これだけで、Awesom babel macrosに載っている素晴らしいライブラリが使えるようになるんです。

では、さらにいくつかのユースケースを紹介していきましょう。

コンパイル時にコードを評価する

preval.macro

babel-plugin-prevalに対応するマクロです。

babelの作者がサクッと作ったようです。

import preval from 'preval.macro'

const one = preval`module.exports = 1 + 2 - 1 - 1`

お分かりの通り、1 + 2 - 1 - 1がコンパイル時に評価され、インラインでコードに埋め込まれます。

別モジュールを評価することもできます。

import preval from 'preval.macro'

const hoge = preval.require('./hoge')

JSON.parse(hoge)

hogeモジュール内では、hoge.jsonを読み込んでいます。

hoge.js
const fs = require('fs')
const path = require('path')

const filePath = path.join(__dirname, 'hoge.json')

module.exports = fs.readFileSync(filePath, 'utf8')

ここで「ん???」と思った方もいるでしょう。

最終的に、フロントエンドで実行されるのに、ファイルが読み込めるの?と。

ええ、なぜなら「コンパイル時に実行される」からです。

つまりhoge.jsこそが「マクロ」としてコンパイル時に実行されるコードなんです。

評価結果は、JSON文字列なので、JSON.parseできます。

開発中だけ、詳細なコンソールログを出す

scope.macro

これは便利系ですね。ブラウザでもNode.jsでも動きます。

まずは見た方が早そうなので、、、

イイ感じの詳細なログが出ていて、開発が捗りそうです。

こんな「イイ感じの詳細なログ」を出すために、どれだけの苦労をしなければいけないのでしょうか?

import scope from 'babel-plugin-console/scope.macro'

function add100(a) {
  const oneHundred = 100

  // ココ
  scope('Add 100 to another number')

  return add(a, oneHundred)
}

function add(a, b) {
  return a + b;
}

え?これだけ?って思いませんか?

それがマクロのすごいところなんです。

もちろん、プロダクションコードの実行時にオーバーヘッドなんてありませんよ。

おわり

もっと紹介したいのですが、時間がないので興味がある方は

Awesom babel macros

を見てください。

個人的には、Vue.jsのテンプレートをコンパイルするマクロや、

Jestのマクロでインラインテストコードが書けるようになることを密かに期待しています。

(というか、prevalとかpenv使えば、できちゃいそうですよね。できたら記事にしますね。)

そんなこんなで、babel-plugin-macrosの紹介でした。

読んでいただき、ありがとうございました。

17
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?