1.1.0 • Published 7 months ago

@hcfy/js-to-mjs v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

js-to-mjs

tsc -m ESNext 输出的虽然是 es module 文件,但是:

  • 文件后缀仍然是 .js
  • 文件内的模块导入没有加上完整的文件后缀,比如应该用 import './utils.mjs' 而不是 import './utils'

而 js-to-mjs 的作用就是:将 .js 文件重命名为 .mjs 文件,并给文件内的相对路径的模块加入完整的文件扩展名。

使用示例

首先安装 @hcfy/js-to-mjs:

npm i -D @hcfy/js-to-mjs

然后参考下方的 package.json:

{
  "type": "commonjs",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    }
  },
  "scripts": {
    "build:mjs": "tsc --outDir dist -m ESNext --moduleResolution bundler -d && js-to-mjs dist",
    "build:cjs": "tsc --outDir dist -m NodeNext --moduleResolution NodeNext",
    "build": "npm run build:mjs && npm run build:cjs",
    "dev": "nodemon --watch src -e ts,tsx,js --exec \"npm run build\""
  }
}

如果你使用的是 TypeScript 5.2.0 以下的版本,那么 build:mjsbuild:cjs 可以用下面这种写法,但是这个写法在 5.2.0 以后会报错,见 TypeScript 5.2.0 的说明

{
  "scripts": {
    "build:mjs": "tsc --outDir dist -m ESNext --moduleResolution NodeNext -d && js-to-mjs dist",
    "build:cjs": "tsc --outDir dist -m CommonJS --moduleResolution NodeNext"
  }
}

以上示例中:

  • build:mjs 用来输出 ESM 和 *.d.ts 文件,其中使用了 js-to-mjs 对 tsc 输出的 .js 文件做了处理。
  • build:cjs 用来输出 CommonJS 文件,注意其中没有 -d 参数,这是因为在 build:mjs 中已经输出了 *.d.ts。
  • build 用来组合上面两个命令。注意顺序,build:mjs 要先执行。
  • dev 用来在文件变更之后自动 build。由于 tsc --watch 不提供执行命令的钩子,所以改为用 nodemon 来监听文件变化并执行 build 命令。

注意事项

js-to-mjs 只会处理相对路径的模块,即以 '.' 开头的模块导入路径:

import '../utils'
// 会变成
import '../utils.mjs'

但 node_modules 里的 submodule 是不会处理的,比如:

// 下面的导入语句不会改变
import isEqual from 'lodash/isEqual'

这种情况,你需要自行在 .ts 文件里加上后缀,即 import isEqual from 'lodash/isEqual.js'

全部的转换规则

// 非相对路径的模块:不会改变
import React from 'react'

// 以 / 结尾的模块:
// 如果 utils/index.js 文件存在,则会变成 './utils/index.mjs',否则不会改变
import utils from './utils/'

// 不是以 / 结尾的模块:
// 如果 ../runSth.js 文件存在,则变为 '../runSth.mjs';
// 如果 ../runSth/index.js 存在,则变成 '../runSth/index.mjs';
// 如果都不存在则不会改变
import '../runSth'