#javascript #typescript #amd #systemjs #es6-module-loader
#javascript #typescript #amd #systemjs #es6-module-loader
Вопрос:
У меня есть модуль AMD, который я хочу загрузить с помощью SystemJS. Я могу это сделать, но, к сожалению, мне приходится называть это следующим образом:
var Logdown = module.default;
var instance = new Logdown('Test');
Я хотел бы пропустить вызов .default
, но я не знаю, как избавиться от этого свойства. Я думаю, что это default
каким-то образом назначается загрузчиком SystemJS.
Это мой модуль:
logdown.js
define('Logdown', function() {
function Logdown(name) {
this.name = name;
}
Logdown.prototype.log = function() {
console.log(this.name);
};
return Logdown;
});
И вот моя конфигурация SystemJS:
SystemJS.config({
baseURL: '/dist',
map: {
'logdown': 'lib/dynamic/logdown/logdown.js'
}
});
Комментарии:
1. Что у вас есть в logdown.js называется «named module» в спецификации AMD , на которую вы ссылаетесь, и в этом документе говорится: «Вам следует избегать присвоения имен модулям самостоятельно и размещать только один модуль в файле во время разработки. Однако для обеспечения инструментария и производительности модульному решению необходим способ идентификации модулей во встроенных ресурсах.» Для SystemJS присвоение имени module в
logdown.js
превращает этот файл в пакет, а не в модуль. И на ваш вопрос невозможно ответить, не увидев полный исходный код, который импортирует этот модуль.2. Спасибо за разъяснение, Артем. ☺
3.
default
создается не загрузчиком модуля, а скорее объявлением экспорта.
Ответ №1:
TL; DR
Используйте import ... from "...";
синтаксис вместо import ... = require("...");
при использовании именованных модулей AMD в коде TypeScript.
Объяснение
Мое основное приложение (использующее Logdown
модуль) написано на TypeScript и скомпилировано в код ES5. При этой настройке я заметил, что в выходных данных есть разница в зависимости от используемого синтаксиса импорта TypeScript.
Вот различия:
import Logdown from "logdown";
export default class Main {
constructor(message: string) {
let logger: Logdown = new Logdown('Test');
logger.log();
}
}
Компилируется в:
System.register(["logdown"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 amp;amp; context_1.id;
var logdown_1;
var Main;
return {
setters: [
function(logdown_1_1) {
logdown_1 = logdown_1_1;
}],
execute: function() {
Main = (function() {
function Main(message) {
var logger = new logdown_1.default('Test');
logger.log();
}
return Main;
}());
exports_1("default", Main);
}
}
});
И:
import Logdown = require("logdown");
export default class Main {
constructor(message: string) {
let logger: Logdown = new Logdown('Test');
logger.log();
}
}
Компилируется в:
System.register(["logdown"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 amp;amp; context_1.id;
var Logdown;
var Main;
return {
setters:[
function (Logdown_1) {
Logdown = Logdown_1;
}],
execute: function() {
Main = (function () {
function Main(message) {
var logger = new Logdown('Test');
logger.log();
}
return Main;
}());
exports_1("default", Main);
}
}
});
Важной частью является то, что при использовании import Logdown from "logdown";
скомпилированный код TypeScript создаст новые экземпляры, подобные этому var logger = new logdown_1.default('Test');
.
Но при использовании import Logdown = require("logdown");
скомпилированный код TypeScript не добавляет default
свойство, а вместо этого создает экземпляры, подобные этому: var logger = new Logdown('Test');
.
Итак, с тем типом модуля, который у меня есть (названный модуль AMD), мне нужно использовать import ... from "...";
synatx.
Ответ №2:
При предыдущей комплектации с webpack вы могли просто добавить esModule
свойство со значением false
в конфигурацию загрузчиков (если поддерживается).
Например, с помощью html-загрузчика выполните следующие действия: https://webpack.js.org/loaders/html-loader/#esmodule