将现有的 AMD 模块导入 ES6 模块

Import existing AMD module into ES6 module

我有一个现有的应用程序,其中我使用 RequireJS 定义了 AMD 模块。我在我的项目中广泛使用 "text" 和 "i18n" 的 requirejs 插件。 我最近一直在试验 ES6 模块,并希望在我的应用程序中创建新模块时使用它们。但是,我想重用现有的 AMD 模块并在定义我的 ES6 模块时导入它们。

这可能吗?我知道 Traceur 和 Babel 可以从 ES6 模块创建 AMD 模块,但这只适用于不依赖于现有 AMD 模块的新模块,但我找不到重用现有 AMD 模块的示例。

如有任何帮助,我们将不胜感激。这是我现在开始使用所有 ES6 好东西的障碍。

谢谢

是的,可以做到。创建具有以下结构的新应用程序:

gulpfile.js
index.html
js/foo.js
js/main.es6
node_modules

安装 gulpgulp-babel。 (我更喜欢在本地安装 gulp,但您可能需要全局安装:这取决于您。)

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Something</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.js"></script>
    <script>
    require.config({
        baseUrl: "js",
        deps: ["main"]
    });
    </script>
</head>
<body>
</body>
</html>

gulpfile.js:

"use strict";

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task("copy", function () {
    return gulp.src(["./js/**/*.js", "./index.html"], { base: '.' })
        .pipe(gulp.dest("build"));
});

gulp.task("compile-es6", function () {
    return gulp.src("js/**/*.es6")
        .pipe(babel({"modules": "amd"}))
        .pipe(gulp.dest("build/js"));
});

gulp.task("default", ["copy", "compile-es6"]);

js/foo.js:

define(function () {
    return {
        "foo": "the value of the foo field on module foo."
    };
});

js/main.es6:

import foo from "foo";

console.log("in main: ", foo.foo);

在您 运行 gulp 构建应用程序之后,在浏览器中打开文件 build/index.html。您会在控制台上看到:

in main:  the value of the foo field on module foo.

ES6 模块 main 能够加载 AMD 模块 foo 并使用导出的值。也可以让原生 AMD 模块加载已转换为 AMD 的 ES6 模块。一旦 Babel 完成它的工作,就 AMD 加载器而言,它们都是 AMD 模块。

除了@Louis 的回答之外,假设您已经在 require.js 配置中指定了一堆第三方库,在您的新 ES6 模块中,无论何时导入模块,无论是 amd 还是 es6,只要保持导入的模块名称一致,就可以了。例如:

这是 gulp 文件:

gulp.task("es6", function () {
  return gulp.src("modules/newFolder//es6/*.js")
  .pipe(babel({
    "presets": ["es2015"],
    "plugins": ["transform-es2015-modules-amd"] 
     // don't forget to install this plugin
  }))
  .pipe(gulp.dest("modules/newFolder/build"));
});

这是 es6 文件:

import d3 from 'd3';
import myFunc from 'modules/newFolder/es6module'
// ...

这将被编译成这样:

define(['d3', 'modules/newFolder/es6module'], function (_d, _myFunc) {
  'use strict';
   // ...
});

只要编译文件 define(['d3', 'modules/newFolder/es6module'], ... 中的模块在原始 AMD 文件中没有问题,它应该可以在现有 require.js 设置下工作,例如压缩文件等

关于@coderC 关于 require.js 加载器的问题,我在 AMD 模块中使用 i18n!nls/lang,起初我认为找到 AMD 插件加载器的替代品是一件非常棘手的事情在 ES6 模块中,我切换到其他本地化工具,例如 i18next。但事实证明这样做是可以的:

import lang from 'i18n!nls/lang';
// import other modules..

因为它会被gulp任务编译成这样的:

define(['d3', 'i18n!nls/lang'], function (_d, _lang) {
// ....

这样,我们就不用担心 require.js 加载器了。

简而言之,在ES6模块中,如果你想使用现有的AMD plugin/modules,你只需要确保编译后的文件符合现有的设置即可。此外,您还可以尝试使用 ES6 模块捆绑器 Rollup 来捆绑所有新的 ES6 文件。

希望这对那些试图在项目中集成 ES6 语法的人有所帮助。

最新版 babel 的一些变化:

首先,babel({"modules": "amd"}) 不适用于最新版本的 babel。相反,使用 babel({"plugins": ["@babel/plugin-transform-modules-amd"]})。 (你需要将该插件作为一个单独的模块安装在 npm 中,即 npm install --save-dev @babel/plugin-transform-modules-amd。)

其次,gulp.task 的语法不再接受数组作为其第二个参数。相反,使用 gulp.parallelgulp.series 创建复合任务。

您的 gulpfile 最终将如下所示:

"use strict";

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task("copy", function () {
    return gulp.src(["./js/**/*.js", "./index.html"], { base: '.' })
        .pipe(gulp.dest("build"));
});

gulp.task("compile-es6", function () {
    return gulp.src("js/**/*.es6")
        .pipe(babel({"plugins": ["@babel/plugin-transform-modules-amd"]}))
        .pipe(gulp.dest("build/js"));
});

gulp.task("default", gulp.parallel("copy", "compile-es6"));