如何运行编译成单个文件的带有AMD模块的TypeScript应用程序?

19

我相信我在这里完全错过了一些微不足道的东西,但是我无论如何也想不出来。最近我开始使用AMD(RequireJS)。我的应用程序将在浏览器中运行。


设置

在TypeScript 1.8中,当使用AMD时,可以将由外部模块组成的整个项目tsc为一个单独的输出文件可能

因此,出于这个原因,我终于决定放弃内部模块,并使我的所有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找不到该模块。


我认为你没有正确地做这件事。你需要使用普通的<script>标签在加载require.js之后,再使用普通的<script>标签包含main.js。然后你就可以“require”它们,但它们已经被加载了。 - Corey Alix
4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
7

您应该通过脚本标签加载已构建的文件:

<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 以获取一个dojo示例。 请参见https://github.com/ca0v/react-lab/blob/master/rawgit.html 以获取一个requirejs示例。 请参见https://github.com/ca0v/html-playground/blob/master/playground/svg/svgeditor/index.html 以获取一个almond示例。 或者,您可以使用data-main来加载requirejs配置。该配置可以将构建脚本指定为依赖项。例如:
requirejs.config({
    paths: {
        "openlayers": "bower_components/ol3/ol",
        "jquery": "bower_components/jquery/dist/jquery.min"
    },
    deps: ["built/run"],
    callback: () => {
        requirejs(["app"], run => run());
    }
});

然后使用 data-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

这确实是一个微不足道的错误——对于高级的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>

注意: 在包含Require.js时,必须省略data-main属性,否则模块将被加载两次(或者至少上面的示例记录了两次)。

注意2: 这只是完整解决方案的一部分。对于TypeScript编译器发出的所有模块,都必须指定module -> file映射,这是不可行的。然而,相关问题有一个适用的答案


我相信,当你使用相对模块名称('./Project/MainModule')而不是命名模块名称('Project/MainModule')时,你将能够解决映射问题。 - ahz
非常感谢您提供的信息。这对我起到了很好的帮助,让我能够顺利开始。 - user3076647

2

TypeScript编译器仅生成define调用。要触发模块加载,您需要至少一个顶级require调用。

使用RequireJS的r.js进行捆绑时,有一个很好的选项

不确定如何使用--outFile来实现这一点。我相信您需要直接在.ts.js文件中以类似于在index.html中所做的方式使用RequireJS API。只需调用require(["Project/MainModule"]);即可。

您为什么不想或不能使用r.jsbrowserifywebpack的解决方案呢?


你不想或者不能使用r.js、browserify或webpack,有什么原因吗?我希望我的代码库与模块加载实现无关。这样一来,我只需要翻转一个开关,就可以为npm、AMD或ES6语法编译相同的代码库。 - John Weisz
无论如何,似乎我都需要添加一个额外的构建步骤。感谢您的建议。 - John Weisz
1
当然。我假设您使用TypeScript语法编写模块-然后是编译器/构建工具的设置来创建运行时模块。所有三个都支持这种方法。对于r.js,您需要使用“tsc”本身预编译代码库(与现在执行的方式相同,只需省略“--outFile”)-额外的构建步骤。使用webpack和browserify,所有内容都在内存流中完成-替换“tsc”作为构建步骤。 - ahz
如果你指的是ES6语法:import {SubComponent} from "Components/SubComponent" -- 是的,那就是我使用的。 - John Weisz
是的,在您的代码库中。然后只需为所需的运行时模块系统切换 - commonjs(npm),AMD(浏览器),ES6(SystemJS或未来)。 - ahz

0

我已经为这个确切的用例编写了SAMD: https://github.com/morris/samd

它提供了一个最小的AMD实现,足以支持TypeScript AMD捆绑包和通过常规脚本标记包含的依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,