将现有AMD模块导入ES6模块

Import existing AMD module into ES6 module

本文关键字:模块 导入 ES6 AMD      更新时间:2023-09-26

我有一个现有的应用程序,我有使用RequireJS定义的AMD模块。我在我的项目中广泛使用"文本"answers"i18n"插件。我最近一直在尝试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,只要你保持导入的模块名称一致,你就会很好。例如:

下面是gulpfile:

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,起初我认为在ES6模块中找到AMD插件加载器的替代品将是一件非常棘手的事情,我切换到其他本地化工具,如i18next。但事实证明,这样做是可以的:

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

因为它会被gulp任务编译成STH,像

define(['d3', 'i18n!nls/lang'], function (_d, _lang) {
// ....
这样,我们就不用担心require.js加载器了。

简而言之,在ES6模块中,如果你想使用现有的AMD插件/模块,你只需要确保编译的文件与现有的设置一致。此外,您还可以尝试使用ES6模块捆绑器Rollup来捆绑所有新的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"));