【问题标题】:Babel transform imports to destructure defaultBabel 将导入转换为解构默认值
【发布时间】:2018-09-06 02:58:14
【问题描述】:

我正在尝试创建一个不将文件捆绑在一起的构建管道,而是使用<script type="module">。这样我就可以在文件更改时重新编译文件,而无需重新打包,大大缩短了开发过程中的构建时间。

我们的项目使用 ES6,所以这通常很容易。

但是有一个障碍:只有 CommonJS 构建的第三方模块(例如 react)。

有几种方法可以解决这个问题。目前,我有一个将导入名称从react 更改为/node_modules/react 的转换,并且我的服务器足够智能,可以从node_modules 找到适当的dist 文件并提供它。这一切都很好。

问题是当我尝试执行以下操作时会感到困惑:

import { Component } from 'react';

这不会像现在这样工作(因为它会因为没有默认值而感到困惑)。但是,这将起作用:

import * as React from 'react';
const { Component } = React;

我可以为所有文件和包手动执行此操作,但是 a) 这会使其变得不必要地丑陋(对于 Redux 和其他东西,我们必须这样做的许多文件中有六个不同的包,并且 b ) 有很多文件,我不想手动更改它们。

有没有可以自动进行这种转换的 Babel transform 插件? 看来这不是一个完全新颖的方法,所以我希望有一个插件可以做到对我来说,我的 Google-fu 没能找到。

【问题讨论】:

  • 谁或什么东西弄糊涂了?你真的应该解决这个问题,不要到处使用丑陋的风格。
  • “它”在这种情况下是 Chrome。使用type="module" 时,它会尝试使用 ESM 导入,但对于 CJS 模块,它们没有检测到的“默认”导出,因此会引发错误“模块‘blahblah’没有默认导出”。不能直接解决这个问题。
  • 我认为 Chrome 根本不支持 CJS 模块,它也应该抛出一个关于没有命名导出“Component”的错误。我认为您实际上应该这样做import 'react'; const { Component } = React;
  • 是的,我自己将其包装成一些东西,然后将它们收集起来export default他们。不得不做一些魔术......希望它会奏效。 =p

标签: javascript ecmascript-6 babeljs commonjs


【解决方案1】:

我设法让这个工作。我最终不得不编写自己的 Babel 插件来进行我正在寻找的更改。基本上,对于 import 语句的不同版本,它会改变它以便更好地与 UMD 和 CJS 模块一起工作。

例如,像这样的:

import A, { a, b, c } from 'a';

变成了这样的东西:

import * from __babel_A from 'a';
const A = __babel_A.default && (__babel_A.default.default || __babel_A.default) || __babel_A;
const { a, b, c } = __babel_A.default || __babel_A;

这种格式是根据大多数东西的导出方式产生的。许多(如 React)会将所有内容放入一个对象中,其名称为 module.exports(如果我提供了一个假的)或 thiswindow。其他人最终没有将事物组合在一起(例如 ReactRTE)并且有自己的“默认值”,这就是 default.default 位的来源。

除了这个转换之外,当我的服务器提供第三方文件的 dist 版本时,它会以某种方式将它们包装起来,然后让我执行export default。看起来像这样:

const module = {}; 
const keys = Object.keys(this || window);
const toExport = (function __auto_wrapper() {  
  ${fileCode}

  return module.exports || Object.keys(this).reduce((r, k) => keys.includes(k) ? r : Object.assign(r, { [k]: this[k].default || this[k] }), {});
}).call(this || window);

export default Object.keys(toExport).length === 1 ? Object.entries(toExport)[0][1] : toExport;

同样,不同的方式取决于不同项目的输出。有些人会在给定它时使用module.exports,其他人不会认为module.exports是真实的,因为我(故意)没有将export初始化为对象(如果我这样做了,它会尝试使用require()这是我不想要的)。就我而言,ReactRTE 只有一个 CJS 模块而不是 UMD,所以我还必须对其代码进行替换,以将 require('react')require('react-dom') 替换为对 window 上的对象的引用。

这一切都如我所愿(在浏览器中加载完全未捆绑的代码)。唯一轻微的副作用是React 和朋友都可以在window 上使用(如果捆绑得当,它们通常不会出现),但这很小。

【讨论】:

    猜你喜欢
    • 2020-11-19
    • 2018-04-29
    • 2017-08-31
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 2018-10-04
    • 2018-08-20
    • 2017-06-09
    相关资源
    最近更新 更多