【问题标题】:Babel.js using Import and Export not working使用导入和导出的 Babel.js 不起作用
【发布时间】:2017-10-07 03:21:26
【问题描述】:

我正在尝试使用导入和导出来创建模块,但它不起作用。

我在 index.html 标头中添加了https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js 并尝试导入 js 文件并收到错误消息说 SyntaxError:导入声明可能只出现在模块的顶层。我可能做错了什么?

我知道我可以使用 require.js,但可以使用导入和导出。

HTML

 script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js"></script

JS 文件

  import Mymodule from './modules/mymodule';

【问题讨论】:

  • 错误意味着“导入”应该出现在文件的顶层,而不是在类或函数中。
  • 我的导入语句在一个 js 文件中,没有其他代码。就是这个 import Mymodule from './modules/mymodule';

标签: javascript import export babeljs


【解决方案1】:

Babel 不能执行模块的客户端转译,或者说它没有被浏览器普遍支持。事实上,除非你使用插件,否则 Babel 会将import 转换为require()

如果我运行以下代码:

<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.js"></script>
    <script defer type="text/babel" data-presets="es2015">
        import Mymod from './modules/module';
        Mymod();
    </script>
</head>

我收到以下错误:

Uncaught ReferenceError: require is not defined

来自Babel Docs

在浏览器中编译的用例相当有限,因此如果您在生产站点上工作,您应该在服务器端预编译脚本。有关详细信息,请参阅设置构建系统。

大多数人选择像WebpackRollup 这样的预编译模块捆绑器。

如果您真的想执行此客户端,请使用RequireJS 和通过plugin 运行的 Babel,尽管您可能需要使用 AMD 语法。

对 ES6 模块的原生浏览器支持仍在 early stages 中。但据我所知,目前还没有可供 Babel 使用的预设/插件来告诉它不要转换 import/export 语句。

【讨论】:

    【解决方案2】:

    babel-standalone 翻译的脚本默认在全局范围内执行,因此它们定义的任何符号都自动可用于所有其他模块。从这个角度来看,您的模块中不需要导入/导出语句。

    但是,您可能会尝试维护可以由 babel-standalone(例如,用于快速测试环境、功能演示等)和通过 webpack 等捆绑器使用的源文件。在这种情况下,您需要保留 import 和 export 语句以保持兼容性。

    使其工作的一种方法是在全局范围内添加额外的符号,导致 babel 生成的导入和导出代码无效(而不是像通常发生的那样导致错误)。例如,导出语句被编译成如下代码:

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

    如果没有名为“exports”的现有对象,这将失败。所以给它一个:我只是给它一个 window 对象的副本,所以任何被定义的有趣的东西仍然可以访问:

     <script>
         // this must run before any babel-compiled modules, so should probably
         // be the first script in your page
         window.exports = window;
    

    import 语句被转换为对require() 的调用。结果(或从中提取的属性)分配给在导入语句中用作标识符的变量。默认导入有一些复杂性,这取决于require() 的结果是否包含属性__esModule。如果没有,事情会更容易(但是你不能支持在同一个模块中同时拥有默认和命名导出......如果你需要这样做,请查看 babel 生成的代码并弄清楚如何制作它工作)。

    所以,我们需要require() 的工作版本。我们可以通过将模块名称静态转换为导出的符号/符号来提供一个。例如,在一个 React 组件的演示页面中,我有以下实现:

    function require (module) {
        if (module === "react")  return React;
        if (module === "react-dom")  return ReactDOM;
    }
    

    对于返回多个符号的模块,您只需返回一个包含符号作为属性的对象。

    这样,语句就像

    `import React from "react";`
    

    翻译成有效的代码:

    `React = React;`
    

    这大致就是我们想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-11
      • 1970-01-01
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 2017-10-02
      • 1970-01-01
      相关资源
      最近更新 更多