Относительный путь для импорта модуля Typescript, указывающий на неправильный каталог

У меня есть прикладной уровень, написанный на /questions/tagged/visual-studio-2017 с использованием машинописи. У меня также есть веб-ресурсы, которые построены с использованием JavaScript и HTML. HTML для веб-ресурсов использует requirejs для включения скомпилированного кода Typescript, где это необходимо. Проблема, которую я вижу, связана с относительными путями, которые я использую в своем Typescript. Когда я публикую веб-ресурсы в Microsoft Dynamics, RequireJS пытается загрузить относительные пути из моего Typescript относительно файла html, а не относительно переданного файла Javascript.

WebAPI

Транспортируется в build/CCSEQ/WebAPI.js (Model.js находится в build/CCSEQ/Model.js)

"use strict";

import * as Model from "./Model.js";

export class WebAPI{
  // Code here
}

main.html

Расположен по адресу /WebResources/html/Main.html

<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Main</title>   
</head>
<body>
    <script src="require.js" data-main="../js/Main.js"></script>
</body>
</html>

Main.js

Расположен на /WebResources/js/Main.js

"use strict";

// Require fails because it is looking for /WebResources/html/Model.js rather than /build/CCSEQ/Model.js
require(["WebAPI.js"], function(WebApi){
  // Code Here
});

1 ответ

Первое, что вы должны сделать, это бросить .js из ваших названий модулей (оба ваши require позвони и твой import заявление). Имена, которые вы передаете require а также define являются названиями модулей. Они выглядят как пути, но на самом деле они не являются путями. RequireJS берет имена модулей и преобразует их в пути, используя map, paths а также baseUrl параметры конфигурации (чтобы назвать наиболее часто используемые). Когда вы не используете эти параметры, он использует разумные значения по умолчанию.

Если вы используете .js в имени модуля RequireJS предполагает, что вы передаете путь, а не фактическое имя модуля. (То же самое верно, если вы начинаете строку с косой черты, используйте параметр запроса, как в (foo?blah), или если в строке есть двоеточие, которое RequireJS принимает за указание на то, что вы используете протокол (например, http://).) В этом случае нет преобразования имени модуля в путь, поэтому map, paths а также baseUrl все игнорируются. Вот кусок кода:

        //If a colon is in the URL, it indicates a protocol is used and it is just
        //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
        //or ends with .js, then assume the user meant to use an url and not a module id.
        //The slash is important for protocol-less URLs as well as full paths.
        if (req.jsExtRegExp.test(moduleName)) {
            //Just a plain path, not module name lookup, so just return it.
            //Add extension if it is included. This is a bit wonky, only non-.js things pass
            //an extension, this method probably needs to be reworked.
            url = moduleName + (ext || '');
        } else {

Значение req.jsExtRegExp является /^\/|:|\?|\.js$/,

(Вы можете сохранить свой .js в значении, которое вы передаете data-main так как data-main особенный.)

Более того, нужно что-то сделать, чтобы require(["WebAPI"]... разрешит правильный путь. Вы можете сделать это, установив baseUrl в вашей конфигурации RequireJS, которая указывает на каталог, содержащий файл WebAPI.js, Или вы можете использовать paths:

paths: {
  WebAPI: '../../build/CCSEQ/WebAPI',
}

Обратите внимание, как значение для ключа WebAPI также не хватает .js расширение. Вы не должны иметь его там тоже. Значение там - это путь (не имя модуля) и проблема, с которой вы столкнетесь .js есть то, что RequireJS попытается найти файл с .js.js расширение!

Если вы хотите узнать больше о разнице между именами модулей (или идентификаторами модулей) и путями, у меня есть ответ, который касается этого конкретно.

Другие вопросы по тегам