vivliostyle / vfm

⬇️ Open and extendable Markdown syntax and toolchain.
https://vivliostyle.github.io/vfm/#/vfm
Other
69 stars 12 forks source link

Use native ESM #101

Open akabekobeko opened 3 years ago

akabekobeko commented 3 years ago

Given that Node.js 12 has become a MAINTENANCE LTS, some npm that VFM depends on is also native ESM. VFM will eventually have to support these.

akabekobeko commented 3 years ago

試しに ESM 化された doctype 3.0.0 だけ更新して npm test してみたらエラーになった。

 FAIL  tests/attr.test.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    .../vfm/node_modules/doctype/index.js:3
    export var doctypes = {
    ^^^^^^

    SyntaxError: Unexpected token 'export'

       7 |  */
       8 |
    >  9 | import doctype from 'doctype';
         | ^
      10 | import { Properties } from 'hast';
      11 | import h from 'hastscript';
      12 | import { Node } from 'unist';

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1479:14)
      at Object.<anonymous> (src/plugins/document.ts:9:1)

Test Suites: 14 failed, 14 total
Tests:       0 total
Snapshots:   0 total
Time:        8.27 s
Ran all test suites.
akabekobeko commented 3 years ago

ts-jest が未対応なので以下の設定を試すもエラーは直らず。

tsconfig.json

allowJs を追加。

{
  "exclude": ["tests", "lib"],
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "declaration": true,
    "outDir": "./lib",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "allowJs": true
  }
}

jest.config.js

globals を追加、preset を変更。

module.exports = {
  globals: {
    'ts-jest': {
      useESM: true,
    },
  },
  preset: 'ts-jest/presets/js-with-ts-esm',
  testEnvironment: 'node',
  testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
  testPathIgnorePatterns: ['lib'],
};
akabekobeko commented 3 years ago

簡単な設定変更で対応可能なら 1.0、難しければ 2.0 へ見送る。現時点では 2.0 としておく。

akabekobeko commented 3 years ago

現状のわかりやすいまとめ。簡単な設定変更では対応できなさそうだ。

akabekobeko commented 2 years ago

remark v13 以降へ対応するための micromark 調査用に作成したプロジェクトで ts-jest による Native ESM を試してみた。

Jest v27 系なら以下の設定でゆける。

  1. npm-scripts のテスト コマンドにおける Jest 実行環境の Node.js を ESM 対応モードにする
  2. Jest 設定で ESM の有効化と JS の EMS 変換用 preset を追加

1 は package.json にて npm-scripts の jest コマンド前にオプションを設定すればよい。

{
  "scripts": {
    "test": "NODE_OPTIONS=--experimental-vm-modules jest",
  }
}

2 は Jest 設定が jest.config.js に定義されているなら以下のように書く。

module.exports = {
  transform: {
    '^.+\\.ts$': 'ts-jest'
  },
  preset: 'ts-jest/presets/js-with-ts-esm',
  globals: {
    'ts-jest': {
      useESM: true
    }
  }
}

この方法では TypeScript から ESM な JS を import する際、拡張子 .js は省略したままでも実行に成功。tsc や webpack ではなく Jest (ts-jest) を通すだけならこれでゆけた。