Ответ 1
Большое спасибо Маттиасу Буэленсу, который указал мне правильное направление.
Структура проекта:
-
dist
-
src
-
generic-tsconfig.json
-
main
- (машинописные файлы)
-
tsconfig.json
-
dedicated-worker
- (машинописные файлы)
-
tsconfig.json
-
service-worker
- (машинописные файлы)
-
tsconfig.json
-
src/generic-tsconfig.json
Это содержит конфигурацию, общую для каждого проекта:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"moduleResolution": "node",
"rootDir": ".",
"outDir": "../dist",
"composite": true,
"declarationMap": true,
"sourceMap": true
}
}
Я сознательно избегал вызова этого tsconfig.json
, так как это не сам проект. Адаптируйте вышеизложенное к вашим потребностям Вот важные части:
-
outDir
- это то место, куда пойдут переданный скрипт, объявления и исходные карты. -
rootDir
- при установке этого параметра в каталогsrc
каждый из подпроектов (main
,dedicated-worker
,service-worker
) будет отображаться в качестве подкаталогов вoutDir
, в противном случае они будут пытаться использовать один и тот же каталог и перезаписывать друг друга. -
composite
- это необходимо для TypeScript, чтобы сохранить ссылки между проектами.
Не включайте references
в этот файл. Они будут проигнорированы по какой-то недокументированной причине (вот где я застрял).
src/main/tsconfig.json
Это конфигурация для проекта 'main thread', например, JavaScript, который будет иметь доступ к документу.
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "dom"],
},
"references": [
{"path": "../dedicated-worker"},
{"path": "../service-worker"}
]
}
-
extends
- это указывает на наш общий конфиг выше. -
compilerOptions.lib
- библиотеки, используемые этим проектом. В этом случае JS и DOM. -
references
- так как это основной проект (тот, который мы создаем), он должен ссылаться на все другие подпроекты, чтобы гарантировать, что они также построены.
src/dedicated-worker/tsconfig.json
Это конфигурация для выделенного работника (вид, который вы создаете с помощью new Worker()
).
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
Вам не нужно ссылаться на другие подпроекты здесь, если вы не импортируете вещи из них (например, типы).
Использование выделенных типов работников
TypeScript не делает различий между различными рабочими контекстами, несмотря на то, что они имеют разные глобальные переменные. Как таковые вещи становятся немного грязными:
postMessage('foo');
Это работает, так как типы "webworker" TypeScript создают глобальные переменные для всех выделенных рабочих глобальных переменных. Тем не мение:
self.postMessage('foo');
… Это терпит неудачу, поскольку TypeScript дает self
несуществующему типу что-то вроде абстрактного рабочего глобально.
Чтобы это исправить, включите это в свой источник:
declare var self: DedicatedWorkerGlobalScope;
export {};
Это устанавливает self
в правильный тип.
Бит declare var
не работает, если файл не является модулем, а фиктивный экспорт заставляет TypeScript рассматривать его как модуль. Это означает, что вы объявляете self
в области видимости модуля, которой в данный момент не существует. В противном случае вы пытаетесь объявить его в глобальном, где он уже существует.
src/service-worker/tsconfig.json
То же, что и выше.
{
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "webworker"],
}
}
Использование сервисных рабочих типов
Как и выше, типы "webworker" TypeScript создают глобальные переменные для всех выделенных рабочих глобальных переменных. Но это не выделенный работник, поэтому некоторые типы неверны:
postMessage('yo');
TypeScript не жалуется на вышесказанное, но он потерпит неудачу во время выполнения, поскольку postMessage
не входит в глобальный сервисный работник.
К сожалению, вы ничего не можете сделать, чтобы исправить реальную глобальность, но вы все еще можете исправить self
:
declare var self: ServiceWorkerGlobalScope;
export {};
Теперь вам нужно убедиться, что каждый глобал, который является специальным для сервисных работников, доступен через self
.
addEventListener('fetch', (event) => {
// This is a type error, as the global addEventListener
// doesn't know anything about the 'fetch' event.
// Therefore it doesn't know about event.request.
console.log(event.request);
});
self.addEventListener('fetch', (event) => {
// This works fine.
console.log(event.request);
});
Те же проблемы и обходные пути существуют для других типов работников, таких как рабочие листы и общие работники.
Строительство
tsc --build src/main
И это оно!