Как сделать веб-работников с помощью TypeScript и webpack
У меня возникли проблемы с правильной компиляцией моего typescript, когда я пытаюсь использовать веб-работников.
У меня есть рабочий, определенный следующим образом:
onmessage = (event:MessageEvent) => {
var files:FileList = event.data;
for (var i = 0; i < files.length; i++) {
postMessage(files[i]);
}
};
В другой части моего приложения я использую загрузчик рабочего стола webpack для загрузки моего рабочего следующим образом: let Worker = require('worker!../../../workers/uploader/main');
У меня, однако, есть некоторые проблемы с тем, что объявления typescript не кричат на меня, когда приложение должно быть переписано.
Согласно моим исследованиям, я должен добавить еще один стандартный lib в мой файл tsconfig, чтобы выявить глобальные переменные, к которым рабочий должен получить доступ. Они я так сказал:
{
"compilerOptions": {
"lib": [
"webworker",
"es6",
"dom"
]
}
}
Теперь, когда я запускаю webpack, чтобы построить все, я получаю кучу таких ошибок: C:/Users/hanse/Documents/Frontend/node_modules/typescript/lib/lib.webworker.d.ts:1195:13
Subsequent variable declarations must have the same type. Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.
Итак, мой вопрос: как я могу указать, что webworker использует определения lib.webworker.d.ts, а все остальное следует за нормальными определениями?
Ответы
Ответ 1
В вашем tsconfig.json
файле, в compilerOptions
установите это:
{
"compilerOptions": {
"target": "es5",
//this config for target "es5"
"lib": ["webworker", "es5", "scripthost"]
//uncomment this for target "es6"
//"lib": ["webworker", "es6", "scripthost"]
}
}
Веб-работники не могут получить доступ к объектам DOM, window
, document
и parent
(полный список поддерживаемых объектов здесь: Доступны функции и классы для веб-работников); dom
lib из TypeScript несовместим и переопределяет некоторые элементы, которые определены в lib.webworker.d.ts
Ответ 2
Используя ответ batressc, мне удалось на самом деле заставить передачу сообщений туда-сюда работать, довольно приятным образом.
В дополнение к его ответу с помощью библиотек, код Typescript также нуждается в некоторых толчках, чтобы начать работать.
Сначала создайте файл, чтобы загрузчик файлов взаимодействовал с вами при импорте. У меня есть файл с именем file-loader.d.ts
со следующим содержимым:
declare module "file-loader?name=[name].js!*" {
const value: string;
export = value;
}
Далее, в ваш main.ts
импортируйте работника с помощью загрузчика файлов:
import * as workerPath from "file-loader?name=[name].js!./test.worker";
Этот workerPath
может затем использоваться для создания фактического работника:
const worker = new Worker(workerPath);
Затем создайте фактический рабочий файл test.worker.ts
со следующим содержимым:
addEventListener('message', (message) => {
console.log('in webworker', message);
postMessage('this is the response ' + message.data);
});
Затем вы можете отправлять сообщения туда и обратно в файле main.ts
:
worker.addEventListener('message', message => {
console.log(message);
});
worker.postMessage('this is a test message to the worker');
Я собрал все в репозитории github, если кому-то нужна полная перспектива, чтобы все заработало: https://github.com/zlepper/typescript-webworker
Этот репозиторий также имеет webpack.config.js
, чтобы показать, как веб-пакет может быть настроен для этого.
Ответ 3
Решение rasmus-hansen в своей базовой форме не позволяет рабочим самостоятельно импортировать модули. После некоторого дополнительного поиска я обнаружил, что пример приведен в https://github.com/Qwaz/webworker-with-typescript. Я протестировал версию в worker-loader
и смог тривиально добавить простой модуль, который можно импортировать как worker.ts
и entry.ts
.