5分でわかるbabelプラグインのつくりかた

# このスライドは「JavaScript メタプログラミング勉強会@さくらインターネット metapro.es」のLT資料です。

- - -

# はじめに

- - - 

# メタプログラミングすごそう

- - -

# 実行時注入ならRubyとかPHP, JSで結構簡単にできる

- - -

# インジェクションなら楽にできる

- - - 

# けど黒魔術になりがちだし実際のプロダクト開発でやりだすとどうしても扱いづらい

- - -

# 他人の書いたメタプロ生成コードをみたとき

- - -

# 🤔🤔🤔🤔🤔

- - -

# 🙄

- - - 

# 静的解析すごそう

- - - 

# けどわかんねーよ！

- - - 

# という人のためのはじめの一歩

- - - 

# 自己紹介

- [potato4d](https://twitter.com/potato4d)
- [metapro.js](https://connpass.com/event/77100/)発起人
- フロントエンドエンジニア

- - -

# メタプログラミングわかりません

- - - 

# 自分がわかるようになるために分かる人を呼んで勉強会を開いた

- - - 

# なんで話すか

- - -

# 「**自分のQoLを高める程度なら意外と誰でもプラグイン書けるんやで**」って言いたいから

- - - 

# つくったもの

- - - 

# `process.env.NODE_ENV` が `production` 以外の時に設定した文字を置き換えてくれるプラグイン

- - -

# https://github.com/potato4d/babel-plugin-replace-only-development

- - - 

# 動作:.babelrc

```json
{
  "plugins": [
    [
      "babel-plugin-replace-only-development",
      {
        "rules": {
          "https://api.example.com": "http://localhost:3000"
        },
      }
    ]
  ]
}

```

- - - 

# 動作: Before

```js
import axios from 'axios'

axios.get('https://api.example.com')
```

- - - 

# 動作: After

```js
import axios from 'axios'

axios.get('http://localhost:3000')
```

- - - 

# 使いみち

- - - 

# どうでもいいものを作ったけどローカルとデプロイ時でAPI ROOTを変えたい**けど**設定を管理するのがだるい時

- - - 

# まれによくある

- - - 

# replaceしかしてない簡単構成

- - -

# 作りかた

- - - 

# 作りたいものを決める

- 例えばconsole.logリムーバーとか
- console.logをxhrに置き換えてロギングしたくない？とか
- そういうやつ

- - - 

# おもむろにbabelプラグインの初期設定をする

- babelプラグインなら構文パーサーとかがデフォでついてくるからしんどくない
- CLIインターフェースとかオプションとかをbabelのシステムに依存できるので楽
- 今回のサンプルプラグインはyarn initからはじめてて本当に最小限なので使ってみてくれ！

- - -

# 構文として何に属するかを調べる

- [ASTエクスプローラー](https://astexplorer.net/)におもむろにコードを投げつける
- 出てきたtypeをコピペ

- - - 

# ASTエクスプローラー

![Screen Shot 2018-02-20 at 3.18.23.png](https://qiita-image-store.s3.amazonaws.com/0/75633/27294eb1-f90a-eea4-d381-72cc32124e9b.png)

- - - 

# プラグインのテンプレを流用

```js
const { transform } = require('@babel/core')
const plugin = ({types: t}, options) => {
  return {
    visitor: {
      Literal (path, file) {
        // Literalなのでここに書く
      }
    }
  }
}

module.exports = plugin
```

- - - 

# Babel Plugin Handbookをみて欲しいのを調べる

- https://github.com/jamiebuilds/babel-handbook/blob/master/translations/ja/plugin-handbook.md

- - - 

# 書く

```js
// ...
      Literal (path, file) {
        Object.entries(options.rules).forEach(([before, after]) => {
          if (path.get('literal').container.value == before) {
            path.replaceWith(t.stringLiteral(after))
          }
        })
      }
// ...
```

- - - 

# 完成

- - - 

![Screen Shot 2018-02-20 at 2.56.08.png](https://qiita-image-store.s3.amazonaws.com/0/75633/d925c9f6-1587-8d34-5dbf-cc5c00ab23d1.png)
- - - 

![Screen Shot 2018-02-20 at 2.56.08.png](https://qiita-image-store.s3.amazonaws.com/0/75633/48f80b90-6722-56d5-38cc-bf3454f5467f.png)

- - -

![Screen Shot 2018-02-20 at 2.56.08 3.png](https://qiita-image-store.s3.amazonaws.com/0/75633/5bcdc82c-1a28-412a-a872-9d99b0891599.png)

- - -

# やってみたい人へ

- - - 

# 4つのTips

- - - 

# 1. babelプラグインにするとJSのパーサーを用意しないでいいので楽

- - - 

# 2. ASTエクスプローラーとHandbookがあれば2秒でできそうと思うことは20分あればできる

- - - 

# 3. とりあえずASTって構文の木があるんだ〜ぐらいの気持ちで雑にはじめる

- - - 

# 4. 置き換える系はTypeを調べてreplaceWithだけで倒せるから楽

- - - 

# 参考になった資料

- - - 

# 参考になった資料

- [ASTエクスプローラー](https://astexplorer.net/)
  - 使わないと非人道的なAST脳内パースがはじまる
- [Babel Plugin Handbook](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/ja/plugin-handbook.md)
  - これがあればなんとかなる
- [babel@6プラグインの単純な作成方法について](https://qiita.com/59naga/items/7cee889f677cd80d59be)
  - 簡単なものの作り方はほぼ書いてる

- - - 

# まとめ

- - -

# まとめ

- babelプラグインにするとJSのパーサーを用意しないでいいので楽
- 資料は無茶苦茶あるので誰でもはじめの一歩は作れる
- ASTエクスプローラーがないと人権がないので頑張る
- Qiitaとかにも意外と記事はあるので有効活用すべし
  - ちなみにwebpack pluginをやろうと思ったらそっちはなさすぎたのでブルーオーシャン
- Typeさえわかればあとは割りと泥臭い作業っぽい

- - - 

# やってみよう