Giter Club home page Giter Club logo

my-module-bundler's Introduction

My module bundler

It it a module bundler with the following transform plugins.
The module bundler is based on minipack.

plugins

  • @yukihirop/plugin-transform-arrow-functions
  • @yukihirop/plugin-transform-destructuring (coverage 60%)
  • @yukihirop/plugin-transform-modules-commonjs
  • @yukihirop/plugin-transform-typeof-symbol

presets

  • @yukihirop/preset-my
    • @yukihirop/plugin-transform-arrow-functions
    • @yukihirop/plugin-transform-destructuring (coverage 60%)
    • @yukihirop/plugin-transform-modules-commonjs
    • @yukihirop/plugin-transform-typeof-symbol

Since only destructuring is complicated to implement, the coverage (type that can be converted) is low.

Development

yarn
lerna bootstrap

Tips for operating the library for each package

#1

Example

yarn bundler:dev ./example/destructuring/call-expression-array-basic/entry.js ./dist/destructuring/call-expression-array-basic.js

Test

yarn test
$ yarn test
yarn run v1.19.0
$ yarn build && jest --verbose
$ yarn clean && tsc -b packages/bundler packages/plugin-transform-arrow-functions packages/plugin-transform-modules-commonjs packages/plugin-transform-typeof-symbol packages/plugin-transform-destructuring packages/preset-my
$ rimraf packages/**/lib
 PASS  packages/plugin-transform-arrow-functions/__tests__/plugin-transform-arrow-functions.test.ts
  arrow-functions
    ✓ basic (91 ms)
    ✓ default-parameters (18 ms)
    ✓ expression (10 ms)
    ✓ nested (14 ms)
    ✓ paran-insertion (9 ms)
    ✓ spec-naming (9 ms)

 PASS  packages/plugin-transform-typeof-symbol/__tests__/plugin-transform-typeof-symbol.test.ts
  typeof-symbol
    ✓ basic (97 ms)
    ✓ builtin-global (204 ms)
    ✓ builtin-global-string (74 ms)
    ✓ typeof-typeof (15 ms)
    ✓ non-typeof (7 ms)
    ✓ typeof-function-declaration (16 ms)
    ✓ typeof-function-expression-var (17 ms)
    ✓ typeof-function-expression-func (16 ms)

 PASS  packages/plugin-transform-destructuring/__tests__/plugin-transform-destructuring.test.ts
  destructuring
    ✓ array-basic (66 ms)
    ✓ array-rest-basic (19 ms)
    ✓ array-rest-nested (19 ms)
    ✓ array-overflow (17 ms)
    ✓ array-self-reference (13 ms)
    ✓ array-assignment-function-block (12 ms)
    ✓ object-basic (23 ms)
    ✓ object-rest-basic (67 ms)
    ✓ object-rest-nested (58 ms)
    ✓ object-overflow (26 ms)
    ✓ object-assignment-function-block (10 ms)
    ✓ call-expression-array-basic (53 ms)
    ✓ call-expression-array-helper-rename (40 ms)
    ✓ call-expression-array-self-reference (27 ms)
  destructuring(err)
    ✓ call-expression-array-init-mix (31 ms)

 PASS  packages/plugin-transform-modules-commonjs/__tests__/plugin-transform-modules-commonjs.test.ts
  modules-commonjs
    interop
      ✓ export-default-literal (71 ms)
      ✓ export-default-oe (18 ms)
      ✓ export-default-ae (23 ms)
      ✓ export-default-fd (13 ms)
      ✓ export-default-fd-id-name (13 ms)
      ✓ export-default-ce (16 ms)
      ✓ export-default-ne (16 ms)
      ✓ export-from-all (24 ms)
      ✓ export-from-named (18 ms)
      ✓ export-from-named-multi (15 ms)
      ✓ export-from-as (11 ms)
      ✓ export-from-as-default (15 ms)
      ✓ export-from-as-mix (27 ms)
      ✓ export-from-default-as (35 ms)
      ✓ export-named (11 ms)
      ✓ export-named-multi (11 ms)
      ✓ export-named-as (12 ms)
      ✓ export-named-as-default (11 ms)
      ✓ export-named-as-mix (15 ms)
      ✓ export-named-remap (10 ms)
      ✓ export-variables (49 ms)
      ✓ import-default-literal (20 ms)
      ✓ import-default-as (17 ms)
      ✓ import-wildcard-as (53 ms)
      ✓ import-as-mix (27 ms)
      ✓ import-named (12 ms)
      ✓ import-named-multi (13 ms)
      ✓ import-named-as-mix (9 ms)
      ✓ import-basic (9 ms)
      ✓ import-hoist (17 ms)
      ✓ import-global-variable-unbind (12 ms)
      ✓ import-wildcard-as-hoist (27 ms)
      ✓ export-hoist-function-success (13 ms)
      ✓ export-rename-hoist (21 ms)
      ✓ export-rename-not-hoist (19 ms)
      ✓ export-illegal (4 ms)
      ✓ export-hoist-function-failure (16 ms)
    misc(throw error)
      ✓ import-global-variable-throw-bs (20 ms)
      ✓ import-global-variable-throw-ae (9 ms)
      ✓ import-global-variable-throw-id (11 ms)
      ✓ import-global-variable-throw-bs-ls (15 ms)
      ✓ undefined-this-computed-class-method (7 ms)
      ✓ undefined-this-root-call (5 ms)
    misc
      ✓ this-computed-class-method-wrap-func (7 ms)
      ✓ undefined-this-root-declaration (5 ms)
      ✓ undefined-this-root-reference (5 ms)
    noInterop
      ✓ import-default (8 ms)
      ✓ import-wildcard (9 ms)
      ✓ export-named-from (12 ms)
    loose
      ✓ export-default (11 ms)
    strictMode
      ✓ false (6 ms)

Test Suites: 4 passed, 4 total
Tests:       80 passed, 80 total
Snapshots:   79 passed, 79 total
Time:        3.046 s
Ran all test suites.
✨  Done in 14.97s.

.mmbrc

Same as .babelrc.
Write with nodejs.

const path = require('path');

module.exports = {
  presets: [path.resolve(__dirname, 'packages/preset-my')],
};

or

const path = require('path');

module.exports = {
  "plugins: [
    path.resolve(__dirname, "packages/plugin-transform-arrow-functions"),
    path.resolve(__dirname, "packages/plugin-transform-destructuring"),
    path.resolve(__dirname, "packages/plugin-transform-modules-commonjs"),
    path.resolve(__dirname, "packages/plugin-transform-typeof-symbol")
  ]
}

my-module-bundler's People

Contributors

yukihirop avatar

Stargazers

 avatar

Watchers

 avatar  avatar

my-module-bundler's Issues

babelのヘルパーに関してのメモ

処理の流れ

this.addHelper("_slicedToArray")

helper.ensure("_slicedToArray", File)

helper.loadHelper("_slicedToArray")

helper.getHelperMetadata({ast: helpers["_slicedToArray"].ast() })

ASTになったヘルパー関数に対してトラバース。dependenciesとかを洗い出す

before

import _arrayWithHoles from '_arrayWithHoles';
  import _iterableToArrayLimit from '_iterableToArrayLimit';
  import _unsupportedIterableToArray from '_unsupportedIterableToArray';
  import _nonIterableRest from '_nonIterableRest';

  export default function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

after

 function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

dependencies

function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
}

function _nonIterableRest() { 
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

lernaで作ったパッケージを別のパッケージから参照する

状況

lernaのパッケージが二つあるとして

packages
├── bundler(パッケージの名前は、@yukihirop/bundler)
└── plugin-transform-arrow-functions (パッケージの名前は、@yukihirop/plugin-transform-arrow-functions)

が二つあるとして、 bundlerのdependenciesにplugin-transform-arrow-functionsを入れたい場合

やり方

  1. typescirptのコンパイル (lid/index.js・lib/index.d.tsの作成)
  2. lerna add

typescirptのコンパイル

plugin-transform-arrow-functions をコンパイルする必要がある。

lerna.jsonがあるディレクトリから以下のようにコンパイルできる

tsc -b plugin-transform-arrow-functions

これで packages/plugin-transform-arrow-functions/lib/index.js(index.d.ts) などが作成されたかを確認する。

コンパイル結果は commonjs になってないと、ts-node で動かなくなるので注意が必要

tsconfig.jsoncompilerOptions.modulecommonjs になっているか確認が必要

lerna add

  1. typescriptのコンパイルが終わったら、lerna addできる。

packages/bundlerのパッケージもtypescriptで作成されているので、devDependencies でいい。

lerna add @yukihirop/plugin-transform-arrow-functions --scope @yukihirop/bundler --dev

lerna remove

lerna removeはないので間違ってdependenciesを入れてしまった場合、以下のようなコマンドで取り消す

lerna exec --scope @yukihirop/bundler -- yarn remove @yukihirop/plugin-transform-arrow-functions || lerna bootstrap

テストを各プラグインに分割する

Summary

  • bundlerからplugin-transform-**を除去する
  • plugin-transform-**でbundlerを参照するようにする
  • 各プラグインでのテストは各プラグインで行うようにする

babel-udf-helpersというnpmを作る

Summray

記憶が新しいうちに作る。

#17 の実装中に思いついて実装したやつを切り出して、npmにする。

https://github.com/yukihirop/my-module-bundler/tree/implement_plugin-transform-destructing/packages/plugin-transform-destructuring/src/helperImpl

babel公式ではhelpersの定義をカスタムでできないが、できるようにするライブラリーである。

https://babeljs.io/docs/en/babel-helpers#defining-helpers

注:このパッケージは、このリポジトリに含まれているパッケージでのみ使用されることを意図しています。現在、サードパーティのプラグインがヘルパーを定義する方法はありません。

udf = user define functions

の略

Variable and Function Hoisting (変数と関数宣言、関数式の巻き上げ)に関して

Summary

  • varは巻き上げられる
  • constとletは巻き上げられない
  • 関数宣言は巻き上げられる
  • 関数式は巻き上げられない

exportの巻き上げ(Babel REPLの例)

image

import { isEven } from "./evens";

export function nextOdd(n) {
  return isEven(n) ? n + 1 : n + 2;
}

export var isOdd = function isOdd(isEven) {
  return function (n) {
    return !isEven(n);
  };
};

とトランスパイルすると、nextOdd は巻き上げられるが、 isOdd は巻き上げられない

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

// nextOddは巻き上げられている。つまり、この時点でexports.nextOdd(n)が実行できる。
exports.nextOdd = nextOdd;
// isOddは巻き上げられてない。つまり、この時点でexports.isOdd(n)が実行できない。
exports.isOdd = void 0;

var _evens = require("./evens");

function nextOdd(n) {
  return (0, _evens.isEven)(n) ? n + 1 : n + 2;
}

var isOdd = function isOdd(isEven) {
  return function (n) {
    return !isEven(n);
  };
};

// ここで設定されているのは巻き上げようとしても巻き上げれなかった結果なのである。
exports.isOdd = isOdd;

importの巻き上げ(Babel REPLの例)

巻き上げのママではなく、順番が正されているね。

image

_interopRequireDefault は関数宣言で巻き上げられるので実行できるんだね。

var _interopRequireDefault = function(){..} って書いてしまったら巻き上げられずにエラーになるわけか。

参考

もろわかりやすかった。

https://scotch.io/tutorials/understanding-hoisting-in-javascript

arrow-functionsのテストが落ちる

Summary

parserをbaylon(archived)から@babel/parserに変更して正しくエラーがキャッチされるようになった事に夜影響だと思う

   arrow-functions  basic

    SyntaxError: Identifier 'a' has already been declared (18:9)

      30 |   private createAsset(filename: string): AssetType {
      31 |     const content = fs.readFileSync(filename, 'utf-8');
    > 32 |     const ast: any = parser.parse(content, {
         |                             ^
      33 |       sourceType: 'module',
      34 |     });

ts-nodeでもnode debuggerを使う方法

やり方

lerna.json があるディレクトリのpackage.jsonのscriptsタグにこんな感じでかく

{
  "private": true,
  "scripts": {
    "test": "yarn build && jest",
    "test:debug": "yarn build && node --inspect -r ts-node/register ./node_modules/.bin/jest --runInBand"
  },
  "devDependencies": {
    "jest": "^26.0.1"
  },
  "workspaces": [
    "packages/*"
  ]
}

すると、node debuggerをchromeで開いた状態で

yan test:debug

とすると、debugger の位置でとまるようになる。

参考

https://github.com/TypeStrong/ts-node/issues/537#issuecomment-368305072

Babelへのコントリビュート(テストの追加)

Summary

@babel/plugin-transform-typeof-symbolへ以下のケースのテストを追加する。

_typeof2に変換されるのは結構重要な性質だと思う

typeof-function-declaration

image

typeof-function-expression-func

image

typeof-function-expression-var

image

babelでバグの報告だけで終わってるリスト一覧まとめ

  • https://github.com/babel/babel/issues/11596
  • https://github.com/babel/babel/issues/11569
  • https://github.com/babel/babel/issues/11605
  • https://github.com/babel/babel/issues/11610
  • https://github.com/babel/babel/issues/10932
  • https://github.com/babel/babel/issues/10841
  • https://github.com/babel/babel/issues/10629

@babel/preset-envを使わないようにする

概要

勉強のために、@babel/preset-env が行なっているトラバース処理を自分で実装する。
つまり、複数のplugin-transformの作成とpreset自体の作成を行う。

やる事

  • transformプラグインでESMをCommonJSに変換して、module bundleで ブラウザで動くようにする

やらないこと

  • babel-coreの実装。babel-coreをそのまま使う。故にhelperを使う時に使用すうaddHelperとかもbabel-coreが定義しているやつを使う。
  • UMD・AMD・SystemJSに変換はしない。

@babel/preset-envで使われているプラグイン一覧

https://github.com/babel/babel/blob/master/packages/babel-preset-env/src/available-plugins.js

ファイルに書いてあるプラグインで対応するものにcheckを入れる

ここから、babel/preset-modulesの非公開??プラグイン(公式ドキュメントなし)

計画

preset-my (pluginの名前はbabelを限りなく参考にする)

並び順は実装していく順番

  • @babel/plugin-transform-arrow-functions(arrow functionの変換)
  • @babel/plugin-transform-modules-commonjs(ESMをCommonJSに変換するプラグイン)
    • [メモ]requireをinteropRequire**にwrapするヘルパーを内部で使用する
  • @babel/plugin-transform-typeof-symbol(typeofのES6で導入されたSymbol対応)
  • @babel/plugin-transform-destructuring(展開代入)
  • @babel/plugin-transform-spread(スプレッドの変換)
  • @babel/plugin-transform-shorthand-properties(ショートハンドプロパティー, {a,b} => {a: a, b: b}と書き直すやつ)
  • @babel/plugin-transform-template-literals(テンプレートリテラル)
  • @babel/plugin-proposal-nullish-coalescing-operator(ヌリッシュ合体演算子)
  • @babel/plugin-transform-object-super(メソッドをキー: functionに書き直すプラグイン)
  • @babel/plugin-proposal-optional-chaining(オプショナルチェイン)
  • @babel/plugin-transform-async-to-generator(async・awaitの変換)

=== こっから下はチャレンジ

  • @babel/plugin-transform-computed-properties
  • @babel/plugin-transform-for-of(for-of)
  • @babel/plugin-proposal-class-properties

helpers (helpresは色々ある。今のところ、module-transformだけ認識している)

 - helpers.typeof (typeofのES6で追加されたSymbol対応)
 - helpers.interopRequireWildCard (helpers-module-transfromでwrapする??)

作成の途中必要性を感じたプラグインは適宜追加していく。

preset-myの使い方

import presetMy from '@yukihirop/preset-my'

  const { code } = transformFromAstSync(ast, null, {
-    presets: [env],
+    presets: [presetMy]
  });

参考

かなりシンプルなpreset、babel-presetを理解する上で参考になるかもしれない。
template.tsで用意しているやつはbebelではbable-helpers扱いなんだね。

https://github.com/babel/babel/blob/master/packages/babel-preset-typescript/src/index.js
https://github.com/babel/babel/blob/master/packages/babel-preset-flow/src/index.js
https://github.com/babel/babel/blob/master/packages/babel-helpers/src/helpers.js#L623-L626

これが一番わかりやすいかもしれない。

https://github.com/babel/preset-modules/blob/master/src/index.js

JavaScriptのモジュール化の歴史がわかっていいかも

https://neos21.hatenablog.com/entry/2018/08/03/080000

気になった事

@babel/babel-preset-env の正体は @babel/preset-modules だがこいつはmonorepoで管理されてない。将来的にはマージされる予定?

便利ツール

Babel Repl

https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&spec=false&loose=false&code_lz=IYZwngdgxgBAZgV2gFwJYHsLwBQEoYDeAUDPOgE4zADuwqyM2ANgKYMAeM6cMY-xpUgHNs7XAG4SMAL5FpQA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Ces2015%2Cenv&prettier=false&targets=&version=7.10.2&externalPlugins=

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.