Какую стратегию построения модулей мне следует использовать для модуля Typescript, который можно использовать для браузера или узла?
Я хожу по кругу здесь - позвольте мне изложить мое понимание модулей, как я в настоящее время понимаю это. Поправьте меня, если я ошибаюсь в каких-либо пунктах.
Модули полезны, чтобы избежать загрязнения пространства имен (т. Е. Переменных с одинаковыми именами), а также позволяют вам писать свой код так, чтобы вы знали, что вы зависите от модуля.
(то есть альтернатива - это день, когда вы пишете немного кода, который предполагает, что jquery существует как глобальная переменная, и это делает его схематичным, удаляя различные зависимости, так как вы не уверены, используются они или нет.)
CommonJS - это решение, созданное для Nodejs, а RequireJS (иначе AMD) - для браузеров.
Однако, начиная с ES2015, существует стандартная спецификация для модулей в Javascript - и современные браузеры поддерживают ее, пока она работает над NodeJS.
Typescript - Насколько я понимаю, TypeScript будет компилировать, в котором когда-либо указана стратегия модуля compilerOptions.module
- т.е. "module": "commonjs"
будет компилироваться в синтаксис, который использует CommonJS, в то время как "module" : "amd"
скомпилируется с синтаксисом require. Я предполагаю что "module": "es2015"
компилируется в стандартный синтаксис модуля ES2015.
Что я пытаюсь сделать:
Я пытаюсь написать пару библиотек, содержащих простые классы ES6. Эти библиотеки будут затем использоваться другой библиотекой, которая также будет использовать Typescript.
Начать:
mkdir foo bar biz
В каждом каталоге:
tsc --init && npm init
Это даст нам tsconfig.json по умолчанию из
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code */
"strict": true, /* Enable all strict type-checking options. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
}
}
Но немного грязно иметь .ts
и скомпилированный .js
в той же папке, а также мы хотим файлы декларации, поэтому я буду менять его на это в каждой папке:
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"outDir": "./lib/", /* Redirect output structure to the directory. */
"rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"strict": true, /* Enable all strict type-checking options. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
}
}
В package.json нам также нужно изменить это:
"main": "lib/index.js",
(но вопросы об этом позже).
В фу:
**src/index.ts**
export function hello() : string {
return "hello!";
}
export function myRandom() : number{
return Math.random();
}
И мы побежим:
tsc
sudo npm link
это даст нам в lib/
папка:
Lib/index.d.ts
export declare function hello(): string;
export declare function myRandom(): number;
//# sourceMappingURL=index.d.ts.map
Библиотека /index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAK,MAAM,CAE/B;AAED,wBAAgB,QAAQ,IAAK,MAAM,CAElC"}
Lib/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function hello() {
return "hello!";
}
exports.hello = hello;
function myRandom() {
return Math.random();
}
exports.myRandom = myRandom;
В баре:
SRC / alpha.ts
import {hello, myRandom} from "foo";
export class Alpha {
blurp () : string {
return hello() + myRandom();
}
}
SRC / beta.ts
export class Beta {
flurf () : number {
return Math.random();
}
}
и мы свяжем это с нашим модулем foo и скомпилируем с:
ссылка sudo npm foo tsc ссылка sudo npm
И это прекрасно компилируется: в нашей папке lib / есть:
- alpha.d.ts
- alpha.d.ts.map
- alpha.js
- beta.d.ts
- beta.d.ts.map
- beta.js
И интересный файл там будет lib / alpha.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var foo_1 = require("foo");
var Alpha = /** @class */ (function () {
function Alpha() {
}
Alpha.prototype.blurp = function () {
return foo_1.hello() + foo_1.myRandom();
};
return Alpha;
}());
exports.Alpha = Alpha;
Но это то, где все рушится для меня:
В бизнесе
Я хочу быть в состоянии сделать что-то вроде этого:
SRC / app.ts
import {hello} from "foo";
import {Alpha, Beta} from "bar";
const a = new Alpha();
const b = new Beta();
console.log(a.blurp());
console.log(b.flurf());
console.log(hello());
Но то, что мы получаем здесь, [ts] Cannot find module 'bar'
,
Теперь это имеет смысл, возможно. Package.json бара указывает на index.js
который не существует
Теперь я могу попробовать изменить tsconfig бара, чтобы установить выходной файл в lib/index.js
- но машинопись не такая:
tsconfig.json:5:5 - error TS6082: Only 'amd' and 'system' modules are supported alongside --outFile.
5 "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
~~~~~~~~
tsconfig.json:13:6 - error TS6082: Only 'amd' and 'system' modules are supported alongside --outFile.
13 "outFile": "./lib/index.js", /* Concatenate and emit output to single file. */
Так что я могу изменить модуль на "amd", но тогда он не найдет пакет "foo"
src/alpha.ts:1:31 - error TS2307: Cannot find module 'foo'.
1 import {hello, myRandom} from "foo";
Вы получаете картину.
Кто-нибудь получил какой-нибудь большой совет о том, что мне нужно понять здесь?
Я предпочитаю использовать import {ItemA, ItemB} from "my-module";
синтаксис, но одна вещь, которая касается, если я пишу модули, которые требуют определенной конфигурации импорта на их конце.
Я положил весь код здесь:
1 ответ
Лучшее решение, которое у меня есть, - это создать index.ts
файл и заполните его:
export * from "./alpha.ts";
export * from "./beta.ts";
и т.п.
Это также дает вам контроль над тем, какие модули вы на самом деле экспортируете.