Kirin
Published on 2025-11-29 / 1 Visits
0
0

低代码开发问题(一)

问题

在低代码应用中除了应用本身的资源外,还会动态加载放在oss上的静态资源,如:业务组件库。

业务组件库build打包后只有一个bundle js(css)文件,oss开启跨域后,应用中可以正常加载这些资源。

但是web worker在vite默认build行为中是单独打包一个trunk, 所以bundle js文件里会有加载web worker的逻辑

无论是在bundle中加载web worker的路径是相对路径还是绝对路径,请求域名肯定是前端域名,但是我们要加载的是oss的web worker资源,所以需要更改web worker请求路径,比如:

应用域名:portal.app.wkirin.com
业务组件库资源地址:https://xxxx.oss-cn-hangzhou.aliyuncs.com/fe-resources/test/20230331100155-xxxxx/index.umd.js
web worker资源地址:https://xxxxx.oss-cn-hangzhou.aliyuncs.com/fe-resources/test/20230331100155-xxxx/assets/web-worker.js

当前默认行为请求的web worker资源地址为:https://portal.app.wkirin.com/xxxxxx/assets/web-worker.js

更改资源请求路径

vite实验性特性renderBuiltUrl

renderBuiltUrl(filename, { hostType }) {
 if (hostType === 'js') {
  return {
   runtime: `window.__formatOssPath(${JSON.stringify(filename)})`,
  };
 }
 return {
  relative: true,
 };
},

以上代码会在编译时,将请求路径替换为window.__formatOssPath(资源相对路径), 然后在入口处声明并实现__formatOssPath方法即可

window.__formatOssPath = (filename: string) => {
 const script = document.querySelector('script[data-name="t-runtime-erp"]');
 const prefix = script?.attributes.getNamedItem('data-basename')?.value || window.location.origin + window.location.pathname;

 return prefix + '/' + filename;

};

以上例子中请求web worker地址会更改为正确的地址https://xxxxxx.oss-cn-hangzhou.aliyuncs.com/fe-resources/test/20230331100155-cvLq/assets/web-worker.js

资源地址正确了,但是在浏览器中又得到如下错误:

Uncaught SecurityError: Failed to construct 'Worker': Script at 'https://xxxxxx.oss-cn-hangzhou.aliyuncs.com/fe-resources/test/20230331100155-cvLq/assets/web-worker.js' cannot be accessed from origin

因为oss已经设置了跨域请求头,但是仍然得到这个错误,那就是浏览器本身不支持跨域加载web worker资源

内联web worker代码

为了解决跨域问题,要么在portal中做代理,将https://portal.app.wkirin.com/xxxxxx/assets/web-worker.js代理到正确的oss资源上,但是如果要nginx正确分辨该资源是否是web worker要加载的资源,需要做很多限制,影响灵活性

要么就将web worker中的代码直接打进bundle中,这样不需要再去加载资源, vite支持以下配置:

By default, the worker script will be emitted as a separate chunk in the production build. If you wish to inline the worker as base64 strings, add the inline query:

import MyWorker from './worker?worker&inline' // worker代码就内联到bundle中

但是因为该web worker是用xlsx这个库去做表格解析, 所以也会把xlsx整体内联进去,但是内联过程中加了一些转义符和\n导致代码无法执行,并且bundle整体体积会变得很大,所以改用importScripts的方式,在web worker中加载xlsx相应的cdn资源

到此portal线上环境web worker加载问题解决

本地加载

但是跑本地的时候vite仍然是以module的方式去加载web worker导致importScripts无法使用

The worker script can also use import statements instead of importScripts() - note during dev this relies on browser native support and currently only works in Chrome, but for the production build it is compiled away.

所以用NODE_ENV来区分本地和线上,线上文件打包.prod文件优先,线上走importScripts加载cdn逻辑,本地仍然走import


Comment