我想在web应用程序和服务工作者之间共享源代码模块(类),但无法找到仅使用typescript的方法。在使用amd时,只要我导入一个模块,"self“就不再位于初始线程上。所有的模块源代码都需要同步加载,这与我的web应用不同,在我的web应用中,我可以在异步中请求()它。我尝试使用es2015模块而不是amd,但遇到了“无法在模块外使用导入语句”的问题。即使它成功了,我也会遇到和amd一样的问题。在服务工作者中使用importScripts()似乎是无可避免的。
如果我可以指示typescript我的目标是来自tsconfig.json文件的worker,那么理论上它可以生成serviceworker风格的导入,但我看不到这样的支持。所以我的问题是:
有没有一种方法可以从typescript构建一个模块化的服务工作者解决方案?
失败:
import { Module1 } from "./mods/module1.js";
self.addEventListener("install", (event: any) => {
new Module1("from index");
});我怀疑没有好的答案,因为importScripts没有返回任何内容。这些脚本需要使用repo进行注册。如果almond.js有一个同步模式,我想就可以解决我的问题了,因为Typescript会生成这样的代码:
define(["require", "exports", "./mods/module1.js"], function (require, exports, module1_js_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
self.addEventListener("install", function (event) {
new module1_js_1.Module1("from index");
});
});如果require()不是异步的,我可以在同一个线程上访问"self“,事情应该会顺利进行。从almond.js中删除setTimeout()会中断加载器。
更新:有一个使用amd和almond loader的模式:
self.importScripts("../node_modules/almond/almond.js");
self.addEventListener("install", event => {
requirejs(["worker/index"], (worker: { run: () => void }) => worker.run());
});我现在正在开发它,所以可能会遇到一些限制。worker/index.ts如下所示:
import {Module1} from "../mods/module1";
export function run() {
new Module1("running from worker");
}并且因此使开发者返回到标准的typescript模块。
更新:
下面的tsconfig.json运行得很好:
{
"compilerOptions": {
"outFile": "./app/service_worker.js",
"target": "ES2015",
"module": "amd",
"strict": true,
"inlineSourceMap": true
},
"files": ["./app/service_worker.ts","./app/serviceworker/index.ts"]
}使用此package.json:
{
"name": "pwa-poc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"server": "cd server && tsc && node server.js",
"worker": "tsc -p tsconfig-worker.json",
"test": "cd tests && tsc -p tsconfig.json",
"app": "tsc -p tsconfig.json",
"watch:worker": "npm run worker -- -w",
"watch:test": "npm run test -- -w",
"watch:app": "npm run app -- -w",
"all": "npm-run-all -p server watch:worker watch:app watch:test"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"almond": "^0.3.3",
"typescript": "^3.8.2",
"xml2js": "^0.4.23"
},
"devDependencies": {
"@types/chai": "^4.2.10",
"@types/mocha": "^7.0.2",
"chai": "^4.2.0",
"mocha": "^7.1.0",
"npm-run-all": "^4.1.5"
}
}重要的依赖项是almond。生成的index.js包含所有的和定义实例,并且almond实现了define方法。
index.html文件加载软件包:
<body class="theme">
<script src="../static/almond.js"></script>
<script src="index.js"></script>
<script>
window.addEventListener('load', () => {
require(["index"], App => {
App.run();
});
});
</script>
</body>run()是可用的,因为index.ts将其导出:
import { TableExplorer } from "./ux/TableExplorer";
import { MetaForm } from "./ux/MetaForm";
import { DataGrid } from "./ux/DataGrid";
import { saveFormData } from "./ux/saveFormData";
import { getServices } from "./fun/getServices";
export async function run() {
navigator.serviceWorker.register("./service_worker.js");
const params = new URLSearchParams(window.location.search);
const table = params.get("table");
const family = params.get("family") || "";
const offline = !!params.get("offline");
// ask service work to install all metadata
const registration = await navigator.serviceWorker.ready;
offline && registration.sync.register("offline");
const services = getServices();
if (!table) {
const explorer = new TableExplorer({ services, family, useLinks: true });
document.body.appendChild(await explorer.render());
return;
}
document.title = table;
const form = new MetaForm({ family, table, services });
await form.render();
document.body.appendChild(form.form);
form.form.onsubmit = event => {
saveFormData({ family, table, services, form });
event.preventDefault();
grid.refresh();
};
const grid = new DataGrid({ family, table, services });
await grid.render();
document.body.appendChild(grid.grid);
}tsconfig-worker.json:
{
"compilerOptions": {
"outFile": "./app/service_worker.js",
"target": "ES2015",
"module": "amd",
"strict": true,
"inlineSourceMap": true
},
"files": ["./app/service_worker.ts","./app/serviceworker/index.ts"]
}最后是service_worker.ts:
declare var requirejs: Function;
self.importScripts("../static/almond.js");
requirejs(["serviceworker/index"], (worker: { run: (worker:any) => void }) => worker.run(self));发布于 2020-07-30 19:48:35
唯一的解决方案是使用rolluo和plugin typescript,然后转换到systemjs,它有一个serviceworker兼容的加载器,允许ESM风格的导入到工人内部,其他模块系统也可以工作,例如: AMD UMD,但这都是为了捍卫ServiceWorker的滚动更新概念。
在浏览器工作人员中提供有关ESM支持的重要常规信息
ESM即使在浏览器中得到支持,它本身直到今天在工作人员和服务工作者中大多数时间都不受支持,但是systemjs是一个可以工作的填充程序。
重要的一般信息为什么没有模块支持
由于Service Worker被设计为通过滚动更新进行部署,因此模块系统通常会中断部署
所以不要使用模块,总是要部署SingleFileServiceWorker.js
您可以为每个路径注册不同的serviceWorker.js文件,每个路径只能有一个。
强烈建议不惜一切代价避免从service worker内部的模块进行异步导入和下载。
https://stackoverflow.com/questions/60683081
复制相似问题