Как запустить приложение TypeScript, скомпилированное в один файл с модулями AMD?
Я уверен, что здесь я пропустил нечто совершенно тривиальное, но для его жизни я не могу понять это. Только недавно я начал использовать AMD (RequireJS). Мое приложение будет (будет) работать в браузерах.
Настройка
В TypeScript 1.8, возможно до tsc
весь проект, состоящий из внешних модулей, в один выходной файл при использовании AMD.
По этой причине я, наконец, решил оставить внутренние модули позади и сделать все мои проекты VS2015 .ts
и .tsx
внешними модулями, а затем скомпилировать их в один файл со следующими аргументами компилятора:
--module AMD --outFile main.js
Выход
Файл с одним выходом main.js создается, как ожидается, в нем перечислены все модули, которые являются частью проекта:
main.js
define("Project/MainModule", ["require", "exports" ...], function (require, exports ...) {
"use strict";
console.log("MainModule defined");
// ...
});
...
Использование (?)
Теперь, как мне получить Project/MainModule
для запуска из - например - index.html(чтобы он регистрировал "MainModule defined" в консоли)? Я загрузил RequireJS для обработки синтаксиса AMD, а также файл main.js, указанный для немедленной загрузки:
index.html
<script data-main="main" src="Require.js"></script>
Это правильно загружает main.js
, который я обеспечил включением вызова console.log
после огромного списка определений в этом файле (внешние модули). Простите меня, если это тривиальный вопрос, я не мог найти ничего о том, как использовать скомпилированное приложение с этим подходом (возможно, я не использовал правильные ключевые слова?).
Изменить: я попробовал модуль с именем:
index.html
<script>
window.onload = function () {
require(["Project/MainModule"], function () {
// this
});
}
</script>
... но это нехорошо, RequireJS не может найти модуль.
Ответы
Ответ 1
Вы должны загрузить встроенный файл с помощью тега script:
<head>
<script src="bower_components/dojo/dojo.js"></script>
<script src="built/run.js"></script>
</head>
Затем вы можете загрузить модули, используя require:
<body>
<script>require(["app"], run => run());</script>
</body>
tsconfig.json:
{
"compilerOptions": {
"declaration": false,
"module": "amd",
"target": "es5",
"noImplicitAny": true,
"sourceMap": false,
"out": "./built/run.js",
"moduleResolution": "node"
},
"exclude": [
"bower_components"
]
}
См. https://github.com/ca0v/ags-lab/blob/master/index.html для рабочего примера.
В качестве альтернативы вы можете использовать data-main для загрузки конфигурации requirejs. Эта конфигурация может указывать встроенную script как зависимость. Например:
requirejs.config({
paths: {
"openlayers": "bower_components/ol3/ol",
"jquery": "bower_components/jquery/dist/jquery.min"
},
deps: ["built/run"],
callback: () => {
requirejs(["app"], run => run());
}
});
И загрузите это с помощью main-данных:
<head>
<script src="bower_components/requirejs/require.js" data-main="config.js"></script>
</head>
См. https://github.com/ca0v/ol3-lab/blob/master/index.html
Ответ 2
TypeScript компилятор производит только вызовы define
. Для запуска загрузки модуля вам потребуется хотя бы один вызов верхнего уровня require
.
При использовании RequireJS r.js
для связывания по этой причине есть хороший вариант.
Не знаю, как использовать --outFile
для достижения этой цели. Я считаю, что вам нужно будет использовать RequireJS API непосредственно в .ts
или .js
аналогичным образом в вашем index.html. Вызов просто require(["Project/MainModule"]);
должен быть достаточным.
Это причина, по которой вы не хотите или не можете использовать решение с r.js, browserify или webpack?
Ответ 3
Это действительно была тривиальная ошибка - для продвинутых пользователей RequireJS.
Определения модулей, созданные при компиляции с синтаксисом AMD и --outFile
, называются модулями в соответствии с RequireJS.
Чтобы использовать именованный модуль, он должен быть определен в конфигурации RequireJS путем сопоставления имени модуля с модулем. В этом случае нам нужно определить, что именованный модуль Project/MainModule
находится в модуле (файле) main
:
index.html
<script>
require.config({
paths: {
"Project/MainModule": "main"
}
});
</script>
И затем требуется модуль по его имени, которое теперь можно искать из файла, назначенного ему:
index.html
<script>
require(["Project/MainModule"], function () {
console.log("app loaded");
});
</script>
Примечание: атрибут data-main
должен был быть опущен при включении Require.js, иначе модуль будет загружен дважды (или, по крайней мере, приведенный выше пример дважды записывался в журнал).
Примечание 2: это только часть полного решения. Сопоставления module -> file
должны быть указаны для всех модулей, выпущенных компилятором TypeScript, что вообще невозможно. Однако этот связанный вопрос имеет применимый .