首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用worker-loader与with工作者一起创建类型记录库

如何使用worker-loader与with工作者一起创建类型记录库
EN

Stack Overflow用户
提问于 2020-12-12 20:05:41
回答 1查看 2.8K关注 0票数 2

我试着用网络工作者创建打字本库。当我用webpack-dev-server测试我的代码时,所有的文件都找到了,但是当我让npm运行构建并尝试在另一个本地项目(npm / local /path)中使用lib时,我在浏览器控制台中看到了GET http://localhost:8080/X.worker.js

webpack.config.js:

代码语言:javascript
复制
const path = require('path');

module.exports = {
    devtool: 'inline-source-map',
    entry: {
        'mylib': './src/index.ts',
        'mylib.min': './src/index.ts',
    },
    output: {
        path: path.resolve(__dirname, '_bundles'),
        filename: '[name].js',
        libraryTarget: 'umd',
        library: 'mylib',
        umdNamedDefine: true
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js']
    },
    optimization: {
        minimize: true
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'awesome-typescript-loader',
                exclude: /node_modules/,
                query: {
                    declaration: false,
                }
            },
            {
                test: /\.worker\.js$/,
                use: {
                    loader: "worker-loader"
                }
            },
        ]
    }
};

tsconfig.json

代码语言:javascript
复制
{
    "compilerOptions": {
        "target": "es5",
        "module": "es6",
        "lib": [
            "webworker",
            "es2015",
            "dom"
        ],
        "moduleResolution": "node",
        "sourceMap": true,
        "strict": true,
        "alwaysStrict": true,
        "outDir": "lib",
        "resolveJsonModule": true,
        "declaration": true,
        "skipLibCheck": true,
        "allowJs": true
    },
    "include": [
        "**/*.ts",
        "**/*.tsx"
    ],
    "exclude": [
        "node_modules",
        "lib",
    ]
}

package.json

代码语言:javascript
复制
{
  "name": "mylib",
  "version": "1.0.0",
  "description": "",
  "main": "_bundles/mylib.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack",
    "build": "rm -rf ./lib && tsc",
    "serve": "webpack-dev-server",
    "clean": "rm -rf _bundles lib lib-esm",
    "newbuild": "npm run clean && tsc && tsc -m es6 --outDir lib-esm && webpack"
  },
  "repository": {
    "type": "git",
    "url": "..."
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "..."
  },
  "homepage": "...e",
  "devDependencies": {
    "prettier": "^2.1.2",
    "tslint": "^6.1.3",
    "tslint-config-prettier": "^1.18.0",
    "worker-loader": "^3.0.5"
  },
  "dependencies": {
     ...
  }
}

关于如何导入工作人员的示例:

代码语言:javascript
复制
import X from "worker-loader!./X";
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-13 05:18:04

几个月前我发现自己也处于同样的情况。我找到了一个对我有用的解决方案,但首先让我们讨论一下为什么会发生这种情况。

问题是:

这里有三层。

  1. 库的开发层。
  2. 库的构建层。
  3. 使用库构建的应用程序。

第一层很简单。在您想要创建一个新工作人员的任何文件中,比如它的index.ts,您都可以执行import X from "worker-loader!./X"。您的index.ts确切地知道在哪里找到您的工作文件。这就是为什么在你的webpack开发服务器上工作的原因。

第二层是事情变得奇怪的地方。使用worker-loader处理工作文件时,webpack会输出多个文件。您的配置为filename: '[name].js',它将为源文件夹中的每个文件输出一个文件,所有文件都位于_bundles文件夹中的同一级别。Webpack看到了您的import X from "worker-loader!./X",它还看到了导入文件的目标名称和位置,以及正在进行导入的文件。它将worker文件在index.js输出包中的位置重写为相对于包的其余部分的绝对路径。您可以通过在worker-loader中使用publicPath选项来更仔细地控制这一点。但这并不能真正解决问题,因为您只是将publicPath设置为绝对路径,这将导致我们进入步骤3.

第三层,您尝试消费您的包,是哪里出了问题。您不可能预料到在代码中尝试import { makeAWorker } from 'your-library'的位置。不管在哪里导入,构建文件(在消费者应用程序的node_modules中)将使用webpack在index.js构建中所写的路径来查找工作文件,但现在绝对路径相对于您的消费者项目(通常是主路径,比如index.html所在的位置),而不是构建的node_modules文件夹。因此,您的用户应用程序不知道在哪里可以找到工作文件。

我的解决方案:一点点黑客

在我的场景中,我决定工作文件的内容非常简单,可以从字符串创建一个工作人员,并以这种方式导入它。例如,一个工作文件如下所示:

代码语言:javascript
复制
// worker.ts

// Build a worker from an anonymous function body
export default URL.createObjectURL(
  new Blob([
    '(',
    function () {

      // actual worker content here

    }.toString(),
    ')()', ],
    { type: 'application/javascript' }
  )
);

然后在我想生工人的地方:

代码语言:javascript
复制
// index.ts

import workerScript from './worker';

const myWorker = new Worker(workerScript, {worker_options});

这是因为现在您不再要求webpack创建一个文件并为您编写正确的导入位置。最后,您甚至不会在包中为您的工作脚本提供单独的文件。您可以完全抛弃worker-loader。您的index.ts将创建Blob及其URL,您的使用者应用程序将在该URL中找到在运行时动态生成的辅助脚本。

一次真正的黑客

这种方法有一些严重的缺点,使我不得不问捆绑web工作人员作为npm包的组成部分,提供单文件webpack输出这个问题。问题是,在工作脚本中,您实际上没有任何选项可以导入任何内容。我很幸运,因为我的工人相对简单。它依赖于一个node_module,它本身没有依赖关系。我一开始只是在脚本中包含了该模块的源,但是由于我有多个脚本需要同一个外部模块,所以当它被生成时,我会将它作为一条数据传递给工作人员:

代码语言:javascript
复制
import { Rainbow } from './utils';

var data = {
  id,
  data              
  RainbowAsString: Rainbow.toString(),
};

myWorker.postMessage(data);

然后,在工作人员中,我简单地将RainbowAsString转换回一个函数并使用它。如果您想了解更多细节,可以查看我使用以下方法构建的库:小叶地形图。查看src/TopoLayer.ts文件以了解工作人员的使用情况,并查看src//workers文件夹如何设置工作人员blobs。

结论

我想一定有更好的办法。一个可能的快速修复方法是编写一个复制脚本,将工作文件从node_modules/yourLibrary复制到用户应用程序的构建文件夹。但这并不能提供很好的可移植性,其他用户也将不得不做同样的事情来让你的库使用他们的应用程序。我的解决方案并不完美,但它适用于简单的工作脚本。我仍在考虑一种更有力的解决方案,允许工人自行进口。

编辑:正确的解决方案:

所以写完这个答案后,我被启发加入了webpack-装载机回购的对话我如何使用这个包库呢?。显然,当webpack 5在大约2个月前发布时,他们增加了对这个语法的支持:

代码语言:javascript
复制
new Worker(new URL('./path/to/worker.js', import.meta.url))

我还没有尝试过这一点,但是它看起来像你需要的解决方案(以及两个月前我在想出我的黑客时所需要的解决方案)。尝试一下--这可能正是您需要告诉webpack将您的库捆绑在一起的地方,同时仍然保持工作脚本与导入它的脚本之间的关系。

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

https://stackoverflow.com/questions/65269305

复制
相关文章

相似问题

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