从多个TypeScript类创建单个CommonJS模块

时间:2022-09-25 11:58:51

I'm trying to work out the best way to split my application into a few CommonJS modules that can be consumed by other applications.

我正在尝试找出将应用程序拆分为几个可供其他应用程序使用的CommonJS模块的最佳方法。

I have 5 TS classes, and I'd like to bundle them as a single CommonJS module. I then intend to publish this module to a private NPM repo, so it can be consumed by other applications. Ideally I'd like to package the relevant *.d.ts definition files with it.

我有5个TS类,我想将它们捆绑为一个CommonJS模块。然后我打算将此模块发布到私有NPM仓库,因此可以被其他应用程序使用。理想情况下,我想用它打包相关的* .d.ts定义文件。

What's the best way to do this? I'm using external TS modules, but these produce a separate CommonJS module per TS class.

最好的方法是什么?我正在使用外部TS模块,但是这些模块为每个TS类生成一个单独的CommonJS模块。

2 个解决方案

#1


14  

As far as i know typescript doesn't support combining external modules yet. From their wiki on codeplex:

据我所知,typescript不支持组合外部模块。从他们在codeplex上的wiki:

TypeScript has a one-to-one correspondence between external module source files and their emitted JS files. One effect of this is that it's not possible to use the --out compiler switch to concatenate multiple external module source files into a single JavaScript file.

TypeScript在外部模块源文件与其发出的JS文件之间具有一对一的对应关系。这样做的一个影响是不可能使用--out编译器开关将多个外部模块源文件连接成一个JavaScript文件。

However, you can do a trick by using internal modules in typescript, since the tsc compiler has the ability to compile them into a single file, and then you can just add one more file with a module.exports directive for the whole namespace to make it a CommonJS module.

但是,你可以通过在typescript中使用内部模块来做一个技巧,因为tsc编译器能够将它们编译成单个文件,然后你可以添加一个带有module.exports指令的文件,用于整个命名空间。它是一个CommonJS模块。

Here is a step by step example. Let's say you have the following internal modules split into three files:

这是一个循序渐进的例子。假设您将以下内部模块拆分为三个文件:

Validation.ts:

Validation.ts:

module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
}

ZipCodeValidator.ts

ZipCodeValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var numberRegexp = /^[0-9]+$/;
    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

LettersOnlyValidator.ts

LettersOnlyValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }
}

If you compile these with with the --out parameter in the tsc compiler you can combine them into a single file. However, that doesn't make them a CommonJS module. To export them you use a trick to add one more ts file called ValidationExport.ts containing the export directive for the namespace:

如果使用tsc编译器中的--out参数编译它们,则可以将它们组合到单个文件中。但是,这并不能使它们成为CommonJS模块。要导出它们,您可以使用一个技巧来添加一个名为ValidationExport.ts的ts文件,其中包含命名空间的export指令:

var module: any = <any>module;
module.exports = Validation;

And then you can run the tsc command to compile everything to a single file called "validationmodule.js":

然后你可以运行tsc命令将所有内容编译成一个名为“validationmodule.js”的文件:

tsc --out validationmodule.js Validation.ts ZipCodeValidator.ts LettersOnlyValidator.ts ValidationExport.ts

The output is a CommonJS module you can use in Node.js:

输出是您可以在Node.js中使用的CommonJS模块:

var Validation = require("./validationmodule");

var zipCodeValidator = new Validation.ZipCodeValidator();
var lettersOnylValidator = new Validation.LettersOnlyValidator();

console.log(zipCodeValidator.isAcceptable("16211"));
console.log(lettersOnylValidator.isAcceptable("5555"));

#2


1  

Having a separate CommonJS module per file is completely appropriate. All the require calls in TypeScript will translate to CommonJS require calls in JavaScript, and the .d.ts files will be picked up in the process. (If you're doing something silly like requireing classes outside your source directory... stop.)

每个文件具有单独的CommonJS模块是完全合适的。 TypeScript中的所有require调用都将转换为使用JavaScript的CommonJS require调用,并且将在此过程中拾取.d.ts文件。 (如果你正在做一些愚蠢的事情,比如要求你的源目录之外的类......停止。)

You would only need to consider a packaging step if you intended to use this NPM package in other applications, in which case look into Browserify

如果您打算在其他应用程序中使用此NPM程序包,则只需要考虑打包步骤,在这种情况下请查看Browserify

#1


14  

As far as i know typescript doesn't support combining external modules yet. From their wiki on codeplex:

据我所知,typescript不支持组合外部模块。从他们在codeplex上的wiki:

TypeScript has a one-to-one correspondence between external module source files and their emitted JS files. One effect of this is that it's not possible to use the --out compiler switch to concatenate multiple external module source files into a single JavaScript file.

TypeScript在外部模块源文件与其发出的JS文件之间具有一对一的对应关系。这样做的一个影响是不可能使用--out编译器开关将多个外部模块源文件连接成一个JavaScript文件。

However, you can do a trick by using internal modules in typescript, since the tsc compiler has the ability to compile them into a single file, and then you can just add one more file with a module.exports directive for the whole namespace to make it a CommonJS module.

但是,你可以通过在typescript中使用内部模块来做一个技巧,因为tsc编译器能够将它们编译成单个文件,然后你可以添加一个带有module.exports指令的文件,用于整个命名空间。它是一个CommonJS模块。

Here is a step by step example. Let's say you have the following internal modules split into three files:

这是一个循序渐进的例子。假设您将以下内部模块拆分为三个文件:

Validation.ts:

Validation.ts:

module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
}

ZipCodeValidator.ts

ZipCodeValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var numberRegexp = /^[0-9]+$/;
    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

LettersOnlyValidator.ts

LettersOnlyValidator.ts

/// <reference path="Validation.ts" />
module Validation {
    var lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }
}

If you compile these with with the --out parameter in the tsc compiler you can combine them into a single file. However, that doesn't make them a CommonJS module. To export them you use a trick to add one more ts file called ValidationExport.ts containing the export directive for the namespace:

如果使用tsc编译器中的--out参数编译它们,则可以将它们组合到单个文件中。但是,这并不能使它们成为CommonJS模块。要导出它们,您可以使用一个技巧来添加一个名为ValidationExport.ts的ts文件,其中包含命名空间的export指令:

var module: any = <any>module;
module.exports = Validation;

And then you can run the tsc command to compile everything to a single file called "validationmodule.js":

然后你可以运行tsc命令将所有内容编译成一个名为“validationmodule.js”的文件:

tsc --out validationmodule.js Validation.ts ZipCodeValidator.ts LettersOnlyValidator.ts ValidationExport.ts

The output is a CommonJS module you can use in Node.js:

输出是您可以在Node.js中使用的CommonJS模块:

var Validation = require("./validationmodule");

var zipCodeValidator = new Validation.ZipCodeValidator();
var lettersOnylValidator = new Validation.LettersOnlyValidator();

console.log(zipCodeValidator.isAcceptable("16211"));
console.log(lettersOnylValidator.isAcceptable("5555"));

#2


1  

Having a separate CommonJS module per file is completely appropriate. All the require calls in TypeScript will translate to CommonJS require calls in JavaScript, and the .d.ts files will be picked up in the process. (If you're doing something silly like requireing classes outside your source directory... stop.)

每个文件具有单独的CommonJS模块是完全合适的。 TypeScript中的所有require调用都将转换为使用JavaScript的CommonJS require调用,并且将在此过程中拾取.d.ts文件。 (如果你正在做一些愚蠢的事情,比如要求你的源目录之外的类......停止。)

You would only need to consider a packaging step if you intended to use this NPM package in other applications, in which case look into Browserify

如果您打算在其他应用程序中使用此NPM程序包,则只需要考虑打包步骤,在这种情况下请查看Browserify