javascript - Babel `import` 的 Codemod 到 commonjs `require`
问题描述
我正在寻找一种将完整节点项目的 Babel import
s 转换为 CommonJS-style 的方法require()
。目标是摆脱 Babel。
考虑到 node.js 现在内置了 async/await 之类的东西,运行 Babel 感觉是多余的。Babel 目前唯一剩下的就是将 ES6 样式import
的 s 转换为require()
.
我一直在寻找,但找不到任何优雅的解决方案来半自动完成。编译 Babel 时的输出不够干净,无法在没有大量手动工作的情况下直接复制。
如果我有这样的输入文件:
import express from 'express'
import bodyParser from 'body-parser'
import authMiddleware from './middlewares/auth'
import { get } from 'lodash'
export const myVar = 1
export default function doSomething() {
// ...
}
..我想要一个类似的输出
const express = require('express')
const bodyParser = require('body-parser')
const authMiddleware = require('./middlewares/auth').default
const { get } = require('lodash')
export.myVar = 1
export.default = function doSomething() {
// ...
}
或者,它将文件转换为相关文件的.mjs
-syntax 并用于require()
外部内容。
这不是我第一次有一个运行 Babel 的旧节点项目,随着时间的推移,它变得越来越冗余,所以我确信以前有人已经对此做了很好的解决方案。
解决方案
我挖了源代码babel-plugin-transform-modules-commonjs
。看起来不可能配置 babel 来输出你想要的结果。
背后的原因是 helpers like 的必要性_interopRequireDefault
仍然很强,因为 ES 模块不向后兼容 commonjs,尤其是export default
事情。
举个例子:
// input
import bodyParser from 'body-parser'
import authMiddleware from './middlewares/auth'
// your desired output
const bodyParser = require('body-parser') // <-- no default
const authMiddleware = require('./middlewares/auth').default // <-- default
// actual babel output
var _bodyParser = _interopRequireDefault(require("body-parser"));
var _auth = _interopRequireDefault(require("./middlewares/auth"));
您无法判断何时添加.default
,何时不添加。处理此问题的唯一正确方法是包装require()
并_interopRequireDefault
进行运行时检查。
如果编译器确实跟踪了所需的模块并检查它是 ES 模块还是 commonjs 模块,那么它可以判断是否.default
需要。然而,babel 是围绕一次单个文件的模型设计的,所以它不可能为你做到这一点。
我想如果你能找出一个可靠的规则来告诉你什么时候添加 a.default
什么时候不添加,那么一个简单的 regex-replace 可能会解决你的问题。
边注。我确实有一些想法可以使用定制的 babel 插件来破解它。
您可以分叉babel-plugin-transform-modules-commonjs
源,删除_interopRequireDefault
包装逻辑,然后使用解析器执行上述 check-if-requiree-is-esmodule 工作,然后查看.default
输出中是否需要。
但说起来容易做起来难,这需要一些认真的努力。
推荐阅读
- angular-material - 设置角度分量默认值
- ruby-on-rails - 带有反应导轨和设备 JWT 的基本身份验证:401
- java - 如何使用spring将数据从mysql检索到jsp
- hbase - Hbase按插入顺序扫描多个版本
- firebase - 在 Firebase 数据库上为各种指标创建仪表板
- python - python:ModuleNotFoundError:没有名为“加密”的模块
- ruby - 使用 Stripe 找不到没有 ID 的产品
- ionic-framework - 在 iOS 中使用 ionic 3 打开 facebook 页面和应用商店
- sql - 在选择中显示临时表中的字段
- c# - 如何从 C# 中的 SQLDataReader 以更快的方式获取记录