首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有用typescript开发模块化serviceworker的工具?

有没有用typescript开发模块化serviceworker的工具?
EN

Stack Overflow用户
提问于 2020-03-14 21:06:58
回答 1查看 355关注 0票数 2

我想在web应用程序和服务工作者之间共享源代码模块(类),但无法找到仅使用typescript的方法。在使用amd时,只要我导入一个模块,"self“就不再位于初始线程上。所有的模块源代码都需要同步加载,这与我的web应用不同,在我的web应用中,我可以在异步中请求()它。我尝试使用es2015模块而不是amd,但遇到了“无法在模块外使用导入语句”的问题。即使它成功了,我也会遇到和amd一样的问题。在服务工作者中使用importScripts()似乎是无可避免的。

如果我可以指示typescript我的目标是来自tsconfig.json文件的worker,那么理论上它可以生成serviceworker风格的导入,但我看不到这样的支持。所以我的问题是:

有没有一种方法可以从typescript构建一个模块化的服务工作者解决方案?

失败:

代码语言:javascript
复制
import { Module1 } from "./mods/module1.js";

self.addEventListener("install", (event: any) => {
  new Module1("from index");
});

我怀疑没有好的答案,因为importScripts没有返回任何内容。这些脚本需要使用repo进行注册。如果almond.js有一个同步模式,我想就可以解决我的问题了,因为Typescript会生成这样的代码:

代码语言:javascript
复制
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的模式:

代码语言:javascript
复制
self.importScripts("../node_modules/almond/almond.js");
self.addEventListener("install", event => {
  requirejs(["worker/index"], (worker: { run: () => void }) => worker.run());
});

我现在正在开发它,所以可能会遇到一些限制。worker/index.ts如下所示:

代码语言:javascript
复制
import {Module1} from "../mods/module1";
export function run() {
    new Module1("running from worker");
}

并且因此使开发者返回到标准的typescript模块。

更新:

下面的tsconfig.json运行得很好:

代码语言:javascript
复制
{
  "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:

代码语言:javascript
复制
{
  "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文件加载软件包:

代码语言:javascript
复制
<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将其导出:

代码语言:javascript
复制
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:

代码语言:javascript
复制
{
  "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:

代码语言:javascript
复制
declare var requirejs: Function;

self.importScripts("../static/almond.js");
requirejs(["serviceworker/index"], (worker: { run: (worker:any) => void }) => worker.run(self));
EN

回答 1

Stack Overflow用户

发布于 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内部的模块进行异步导入和下载。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60683081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档