我有一个使用TypeScript并由Vue-CLI3构建的Vue项目。
我要实现的目标是让Webpack为我的工作人员构建单独的捆绑软件。我已经在vue.config.js
中阅读过Webpack Code Splitting和configureWebpack的内容,但到目前为止,将它们组合在一起并没有运气。
项目设置是标准的vue create
类型。我有一个./src/main.ts
作为主要入口点,还有一堆TypeScript模块,我想作为带有各自的依赖树的单独捆绑包(如果无法避免,我可以进行代码重复)。
我想得到
./dist/js/all main stuff
./dist/js/workers/worker1.6e3ebec8.js
./dist/js/workers/worker2.712f2df5.js
./dist/js/workers/worker3.83041b4b.js
所以我可以在主代码中进行new Worker(worker1.6e3ebec8.js)
。
我可以通过生成javascript代码,将其放入blob并从中进行实例化来从主程序包中启动工作程序,但是看起来很尴尬。此外,我的工作程序代码会导入其他模块,因此无论如何似乎不是一个选择。
我对所有这一切都很陌生,所以也许我甚至没有朝着正确的方向前进。
在此堆栈上执行此操作的常规方法是什么?
答案 0 :(得分:0)
您可以使用import()
,它将返回一个Promise并将解析您的模块。
在使用Vue-CLI 3时,Webpack已准备就绪,它将自动拆分捆绑包。
const moduleName = 'coolModuleName'
import (
/* webpackChunkName: "[moduleName]" */
`@/my/module/path/${moduleName}.js`
).then(moduleCode => {
// use your module
})
// load them in parallel
const getModuleDynamically(path, moduleName) => import(
/* webpackChunkName: "[moduleName]" */
`@/${path}/${moduleName}.js`
)
Promise.all([
getModuleDynamically(path, moduleName1),
getModuleDynamically(path, moduleName2),
getModuleDynamically(path, moduleName3)
])
答案 1 :(得分:0)
最后我到了那里。正确设置所有红润的配置非常痛苦。
我仍然不太确定这是应该这样做的方式,因此,我欢迎更多评论和答案。我已经修改了Vue的默认设置,以便为诸如src/main
,src/shared
和src/workers
之类的主要内容提供单独的代码区域。
重点是,由于全局命名空间中的类型不同(但有重叠),因此您必须分别编译工作程序和主程序,并且您需要具有不同的标头集在lib
的{{1}}的{{1}}中。但是,您显然希望将整个事情用一个简单的compilerOptions
进行编译,并让VSCode识别您在这里所做的事情。因此,您需要为工作人员分别调用webpack和一组单独的配置文件。
文件夹结构如下(省略无关的内容):
tsconfig
yarn build
和src/
src/main/
src/main/tsconfig.json -- extends ../../tsconfig.base.json
src/shared/
src/workers/
src/workers/tsconfig.json -- extends ../../tsconfig.base.json
package.json -- contains another call to webpack before build or serve
tsconfig.base.json -- specifically renamed
vue.config.js -- modified with both configureWebpack and chainWebpack
webpack.config.workers.js -- this one deals with the workers part
都包含src/workers/tsconfig
,因此名称为src/main/tsconfig
。
最令人沮丧的是,webpack和VSCode都尊重类型和引用。而且Vue部分似乎不尊重"../shared/**/*.ts"
中的shared
快捷方式。
请记住,path
并不尊重您在TypeScript配置中拥有的tsconfig.base.json
快捷方式。就像.vue
。
答案 2 :(得分:0)
到达那里! @aquilesb的答案确实有帮助,尽管经过大量实验,我仍然无法从答案中获得getModuleDynamically()
。
更新:看起来像这种解决方案,我无法使用npm模块的导入。我已经尝试过使用worker-loader进行实验,但到目前为止还没有取得任何进展。
以下是一些要点:
target: 'webworker'
必须在那里。用webpack --config ./webpack.config.workers.js
来称呼它,因为Vue对此一无所知。tsconfig.json
。工人的lib设置必须在其中:"lib": ["esnext","webworker","scripthost"]
以及正确的include:[...]
/ exclude:[...]
设置。tsconfig.json
和"lib":["esnext","dom","dom.iterable","scripthost"]
/ include
的主exclude
。这是在vue.config.js
中完成的,您可能需要创建它。我使用Vue config的chainWebpack
配置选项。import()
(即不是变量)名称调用static
来动态加载。我还没有在配置文件中找到这样做的方法,但这没关系:您无法在某个地方对名称进行硬编码,Webpack怎么会知道它必须捆绑和拆分代码?new Worker(filename)
。为此,我使用了Webpack CLI的--json
选项。可以通过多种方式实现所有这些目标。这就是我的项目中最终的样子:
文件夹结构:
webpack.config.workers.js
vue.config.js
tsconfig.base.json
src/main/
src/main/tsconfig.json -- extends tsconfig.base.json
src/shared/ -- this code may be duplicated by the Vue app bundles and by workers bundle
src/workers/
src/workers/tsconfig.json -- extends tsconfig.base.json
webpack.config.workers.js
:包含一个条目-主工作程序文件,用于加载其他内容。
entry: {
worker: './src/workers/worker.ts'
}
build.workers.sh
:该脚本调用Webpack CLI并生成带有产生的工作人员名称的JSON文件(省略了对文件夹的琐碎操作)。我唯一需要的一个叫做“工人”。其余的将由它动态加载。
#!/bin/bash
# Map entry name -> bundle file name
# "assetsByChunkName":{"entryN":"entryN.[hash].js", ...}
json=$(webpack --config ./webpack.config.workers.js --json $@|tr -d "\n\r\t "|grep -Eo '"assetsByChunkName":.+?}')
# Remove "assetsByChunkName"
json=$(echo "${json:20}")
echo $json
echo $json > "$target/$folder/workers.json"
在运行时加载workers.json
。另一个选择是在编译时使用const VUE_APP_MAIN_WORKER = require("path to/workers.json").worker
并使用此env常量为Vue config使用它。
现在我们有了主工作程序文件的名称,可以执行new Worker("main worker file path we've got from webpack")
。
主工作文件包含静态引用其他模块并动态加载它们的功能。这样,Webpack知道要捆绑什么以及如何拆分代码。
enum WorkerName {
sodium = "sodium",
socket = "socket"
}
function importModule(name: WorkerName): Promise<any> {
switch (name) {
case WorkerName.sodium:
return import(
/* webpackChunkName: "sodium" */
"workers/sodium"
);
case WorkerName.socket:
return import(
/* webpackChunkName: "socket" */
"workers/socket"
);
}
}
使用postMessage
/ message event
API告诉您的主要工作程序代码要加载什么。
const messageHandler = (e: MessageEvent) => {
// here goes app-specific implementation of events
// that gets you the moduleName in the end
importModule(moduleName).then((work) => {
// do smth
});
};
答案 3 :(得分:0)
现在,给出正确答案。
要实现以下目标:
我必须在vue.config.js
中为worker-loader添加一个单独的规则,还必须添加babel-loader。我花了一些时间来找到正确的解决方案,但最后还是放弃了上一个解决方案。对于主要人员和网络工作人员,我仍然分别使用tsconfig.js
。
我仍然不满意的是,那个vue-cli或fork-ts-checker
插件似乎不知道我的worker类中特定于Webworker的类型(所以我不能使用{例如{1}}。