Typescript: выполнить IIFE из модуля UMD, который импортирует отдельный модуль

У меня есть такой tsconfig.json:

{
  "compilerOptions": {
    "lib": ["es2017", "dom"],
    "module": "umd",
    "outDir": "dist",
    "target": "es5",
    "declaration": true
  },
  "compileOnSave": true,
  "files": [
    "myClass.ts"
    "demo.ts"
  ]
}

Мой машинописный текст, demo.ts:

import { MyClass } from './myClass';

(() => {
  console.log('fired IIFE');
  document.onreadystatechange = function () {
    if (document.readyState === 'interactive') {
      console.log('hello world', MyClass);
    }
  };
})();

Который компилируется в:

(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./myClass"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var myClass_1 = require("./myClass");
    (function () {
        console.log('fired IIFE');
        document.onreadystatechange = function () {
            if (document.readyState === 'interactive') {
                console.log('hello world', myClass_1.MyClass);
            }
        };
    })();
});

Мой HTML:

<!DOCTYPE HTML>
<html>
<head>
  <title>Test</title>
  <script src="./dist/myClass.js"></script>
  <script src="./dist/demo.js"></script>
</head>
<body>
  <p>test</p>
</body>
</html>

Я также пробовал:

<!DOCTYPE HTML>
<html>
<head>
  <title>Test</title>
</head>
<body>
  <p>test</p>
  <script src="./dist/myClass.js"></script>
  <script src="./dist/demo.js"></script>
</body>
</html>

Ни один из способов не выполняет сценарий, и ни один оператор журнала не печатается. Что я делаю не так?


person inorganik    schedule 15.02.2019    source источник
comment
Во что компилируется этот TypeScript? Этот метод находится внутри модуля UMD. Вам нужно будет загрузить модуль для выполнения метода.   -  person    schedule 15.02.2019
comment
Вы уверены, что ваш текущий demo.ts компилируется в ./dist/demo.js? Что дает вам tsc --version?   -  person JGFMK    schedule 15.02.2019
comment
Вы также можете найти это полезным, если typescript не был установлен глобально. stackoverflow.com/a/46783952/495157   -  person JGFMK    schedule 15.02.2019
comment
@JGFMK и Эми - извините, я пропустил часть своего кода, потому что думал, что это не имеет значения - я обновил свой вопрос.   -  person inorganik    schedule 15.02.2019
comment
Это должно уметь из window.myClass (думаю)? У меня ограниченный опыт работы с модулями UMD.   -  person    schedule 15.02.2019
comment
@amy проблема в том, что с импортом import { MyClass } from './myClass'; в верхней части demo.ts IIFE никогда не срабатывает, потому что он заключен в модуль UMD. Поскольку он импортирует MyClass, вы ссылаетесь на него таким образом MyClass   -  person inorganik    schedule 15.02.2019
comment
Я тоже нечасто пользовался UMD, но тот факт, что вы сказали, что что-то не работает, заставил меня задуматься об устранении очевидного в первую очередь. Посмотрев здесь github.com/umdjs/umd/issues/124 - вы пробовали импортировать вот так import './umd-foo.js'   -  person JGFMK    schedule 15.02.2019
comment
Должен ли я использовать другой стиль модуля? Я думал, что UMD был наиболее совместимым в целом   -  person inorganik    schedule 15.02.2019


Ответы (1)


Оказывается, вам нужно использовать requirejs для выполнения модуля UMD, сгенерированного машинописным текстом:

<!DOCTYPE HTML>
<html>
<head>
  <title>Test</title>
  <script data-main="dist/demo" type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.1/require.min.js"></script>
</head>
<body>
  <p>test</p>
</body>
</html>

Здесь происходит то, что data-main указывает на файл .js, который загружает все остальное. Вам не нужно загружать скрипт класса отдельно, require.js сделает это за вас.

Это сбило меня с толку, потому что с пакетом gulp-wrap-umd предоставляемая им оболочка не создавала изолируемую область для вложенного сценария, она была фактически глобальной, тогда как созданные машинописью UMD-скрипты с оболочкой имеют изолирующие области.

В этой реализации мой скрипт начальной загрузки demo.js выглядит так:

(function (factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
      var v = factory(require, exports);
      if (v !== undefined) module.exports = v;
  }
  else if (typeof define === "function" && define.amd) {
      define(["require", "exports", "./myClass"], factory);
  }
})(function (require, exports) {
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  require(["./dist/myClass"], (myClassModule) => {

    console.log('my class:', myClassModule.MyClass);
  });

Там, где находится оператор журнала, вы можете запустить любой скрипт, не нуждаясь в document.onready... или window.onload.

person inorganik    schedule 15.02.2019
comment
Рад, что вы решили эту проблему - ваше упоминание require.js вызвало у меня воспоминания. Исчезла она у меня в закладках. davidbcalhoun.com/2014/what-is-amd-commonjs -и-umd github.com/umdjs/umd addyosmani.com/writing-modular-js - person JGFMK; 16.02.2019