2017-05-09 64 views
2

我试图使用导入和导出来创建模块,它不工作。Babel.js使用导入和导出不工作

我将https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.24.0/babel.min.js添加到index.html标题中,并试图导入js文件并获取一条显示SyntaxError的错误消息:import declarations可能只出现在模块的顶层。我可能会做错什么?

我知道我可以使用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'; 
+0

错误的意思是“导入”应该出现在不在类或函数中的文件的顶层。 –

+0

我有一个没有其他代码的js文件中的导入语句。只需从'./modules/mymodule'导入MyModule; – icode

回答

3

巴别不能执行模块的客户端transpiling,或相反,它是不普遍由浏览器支持。事实上,除非你使用插件,否则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

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.

大多数人选择预编译的模块捆绑如WebpackRollup

如果你真的想要执行这个客户端,使用RequireJS与Babel运行通过plugin,虽然你可能需要使用AMD语法。

本机浏览器对ES6模块的支持仍然在early stages。但据我所知,还没有一个预设/插件可供Babel告诉它不要变换import/export声明。

0

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

但是,您可能会尝试维护可由babel独立使用的源文件(例如,用于快速测试环境,功能演示等)以及通过捆绑软件(如webpack)使用的源文件。在这种情况下,为了兼容性,您需要保留导入和导出语句。

让它工作的一种方法是在全局范围中添加额外的符号,使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()。我们可以通过给导出的符号/符号提供模块名称的静态转换来提供一个。例如,在一个阵营组件演示页,我有以下实现:

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

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

这样一来,像

`import React from "react";` 

声明翻译成代码,实际上是:

`React = React;` 

这大概是我们想要的。