简体   繁体   English

Babel.js使用导入和导出无法正常工作

[英]Babel.js using Import and Export not working

I'm trying to use import and export to create modules and it's not working. 我正在尝试使用导入和导出来创建模块,但它无法正常工作。

I added https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js to the index.html header and tried to import a js file and get an error message saying SyntaxError: import declarations may only appear at top level of a module. 我将https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js添加到index.html标头并尝试导入js文件并收到一条错误消息,指出SyntaxError:导入声明只能出现在模块的顶层。 What can I possibly be doing wrong? 我可能做错了什么?

I know I can use require.js but rather use import and export. 我知道我可以使用require.js,而是使用import和export。

HTML HTML

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

JS File JS档案

  import Mymodule from './modules/mymodule';

Babel cannot perform client-side transpiling of modules, or rather it is not universally supported by browsers. Babel不能执行模块的客户端转换,或者说它不是浏览器普遍支持的。 In fact, unless you use a plugin, Babel will transform import into require() . 实际上,除非你使用插件,否则Babel会将import转换为require()

If I run the following code: 如果我运行以下代码:

<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>

I get the following error: 我收到以下错误:

Uncaught ReferenceError: require is not defined 未捕获的ReferenceError:未定义require

From Babel Docs : 来自Babel Docs

Compiling in the browser has a fairly limited use case, so if you are working on a production site you should be precompiling your scripts server-side. 在浏览器中进行编译具有相当有限的用例,因此如果您在生产站点上工作,则应该在服务器端预编译脚本。 See setup build systems for more information. 有关更多信息,请参阅setup build systems。

Most people choose a pre-compiled module bundler like Webpack or Rollup . 大多数人选择预编译的模块捆绑器,如WebpackRollup

If you really want to perform this client-side, use RequireJS with Babel run via a plugin , though you may need to use AMD syntax. 如果你真的想要执行这个客户端,可以使用RequireJS和Babel通过插件运行,尽管你可能需要使用AMD语法。

Native browser support for ES6 modules is still in early stages . 对ES6模块的本机浏览器支持仍处于早期阶段 But to my knowledge there isn't a preset/plugin available yet for Babel to tell it not to transform import/export statements. 但据我所知,还没有一个预设/插件可供Babel告诉它不要转换import/export语句。

The scripts that babel-standalone translates execute by default in global scope, so any symbols defined by them are automatically available to every other module. babel-standalone转换的脚本默认在全局范围内执行,因此由它们定义的任何符号都可自动用于其他每个模块。 From that perspective, you don't need import/export statements in your modules. 从这个角度来看,您的模块中不需要导入/导出语句。

However, you might be trying to maintain source files that can be used both by babel-standalone (eg for quick test environments, feature demonstrations, etc) and via bundlers such as webpack. 但是,您可能正在尝试维护可以由babel-standalone(例如,用于快速测试环境,功能演示等)以及通过诸如webpack之类的捆绑器使用的源文件。 In that case, you need to keep the import and export statements there for compatibility. 在这种情况下,您需要保留导入和导出语句以实现兼容性。

One way to make it work is to add extra symbols into the global scope that cause the import and export code that babel generates to have no effect (rather than causing an error as usually occurs). 使其工作的一种方法是在全局范围中添加额外的符号,这会导致babel生成的导入和导出代码无效(而不是像通常那样导致错误)。 For example, export statements are compiled into code that looks like this: 例如,export语句被编译成如下所示的代码:

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

This fails if there is no existing object called "exports". 如果没有名为“exports”的现有对象,则会失败。 So give it one: I just give it a copy of the window object so anything interesting that gets defined is still accessible: 所以给它一个:我只是给它一个window对象的副本,所以任何有趣的东西仍然可以访问:

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

import statements are translated to calls to require() . import语句被转换为对require()调用。 The result (or properties extracted from it) is assigned to the variable used as the identifier in the import statement. 结果(或从中提取的属性)将分配给用作import语句中的标识符的变量。 There's a little bit of complication around default imports, which are different depending on whether or not the result of require() contains the property __esModule . 默认导入有一些复杂性,这取决于require()的结果是否包含属性__esModule If it doesn't, things are easier (but then you can't support having both default and named exports in the same module ... if you need to do this, look at the code babel produces and figure out how to make it work). 如果没有,事情会变得更容易(但是你不能支持在同一个模块中同时使用默认导出和命名导出...如果你需要这样做,请查看babel生成的代码并弄清楚如何制作它工作)。

So, we need a working version of require() . 因此,我们需要一个工作版本的require() We can provide one by giving a static translation of module name to exported symbol/symbols. 我们可以通过给出导符号/符号提供模块名称的静态转换来提供一个。 For example, in a demo page for a React component, I have the following implementation: 例如,在React组件的演示页面中,我有以下实现:

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

For a module returning multiple symbols, you'd just return an object containing the symbols as properties. 对于返回多个符号的模块,您只需返回包含符号作为属性的对象。

This way, a statement like 这样,一个声明就好

`import React from "react";`

translates to code that is effectively: 转换为有效的代码:

`React = React;`

which is roughly what we want. 这大致是我们想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM