31
25

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 5 years have passed since last update.

babel6にmodule.exportsを追加するだけのプラグインを作った

Last updated at Posted at 2015-11-11

babel6はCommonJSに対応しないので、コンパイル済みのコードにmodule.exports(requireのエントリポイント)が含まれません。これは、transform-es2015-modules-commonjsプラグインを使っても改善しませんでした。issueもしょっちゅう立ってはLockされてます。

add-module-exportsプラグインというものを作成しました。これはコード末尾にmodule.exports文を加えます。

npm install babel-cli --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-plugin-add-module-exports --save-dev

0.1.*

babel@5の動作に準拠するバージョン0.1.0を公開しました。
このバージョンでは、export default文のみを使用した場合にだけ、module.exports文を追加します。

index.js
export default 'foo'

上記はmodule.exports文を追加します

babel index.js --presets es2015 --plugins add-module-exports 
# 'use strict';
#
# Object.defineProperty(exports, "__esModule", {
#   value: true
# });
# exports.default = 'foo';
# module.exports = exports['default'];

下記は追加しません

index.js
let foo= 'bar'
export default 'baz'
export {foo}
babel index.js --presets es2015 --plugins add-module-exports 
# 'use strict';
#
# Object.defineProperty(exports, "__esModule", {
#   value: true
# });
# var foo = 'bar';
# exports.default = 'baz';
# exports.foo = foo;

0.0.*

常にmodule.exports文を発行します。Object.assignでマージするため、動作は破壊的です

index.js
let foo= 'bar'
export default 'baz'
export {foo}

下記のように変換されるでしょう。

babel index.js --presets es2015 --plugins add-module-exports 
# 'use strict';
#
# Object.defineProperty(exports, "__esModule", {
#   value: true
# });
# var foo = 'bar';
# exports.default = 'baz';
# exports.foo = foo;
# module.exports = Object.assign(exports.default || {}, exports);

Object.assignを使用したくない場合は、polyfillに置換できるプラグインが用意されているので、これを利用して下さい。

参考

よもやま話

babel@6からプラグインの作成方法も変わったらしく、ハローワールド的な記事を探しても、5系のものがほとんどでした。その中、頼りになるのは公式の似た目的を持つプラグインの実装日本語の5系の解説記事でした。

例えば拙作のプラグインでは、babel-templateというsebmck製モジュールに依存していますが、これは文字列からASTの生成関数を返すファクトリ関数です。

var babelTemplate= require('babel-template')
babelTemplate('var hoge="fuga"')()
// { type: 'VariableDeclaration',
//   start: undefined,
//   end: undefined,
//   loc: undefined,
//   declarations: 
//    [ { type: 'VariableDeclarator',
//        start: undefined,
//        end: undefined,
//        loc: undefined,
//        id: [Object],
//        init: [Object],
//        _fromTemplate: true } ],
//   kind: 'var',
//   _fromTemplate: true }

プラグインのエントリポイントは以下のようなオブジェクトを返すのが決まりですが、visitor内のトランスフォーム関数の第一引数pathがAST改変用のメソッド群を持つので、これの.pushContainer('body')にASTの配列を渡すと、オレオレコードを追加することができました。

babel-plugin-add-module-exports/lib/index.js
// Dependencies
var babelTemplate= require('babel-template')

// Public
module.exports= function(){
  return {
    visitor: {
      Program: {
        exit: function(path){
          var topNodes= []

          var code= 'module.exports=Object.assign(exports.default||{},exports);'
          var node= babelTemplate(code)()
          topNodes.push(node)

          path.pushContainer('body',topNodes)// プログラム末尾に`module.exports = Object.assign(exports.default || {}, exports);`を追加する
        },
      },
    },
  }
}
31
25
2

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
31
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?