vite打包第三方wasm项目,生产报错的问题
前言
现有的项目中使用了第三方wasm项目。本地开发的时候没问题,但是打包后在生产出现了问题
问题定位
原因是打包后获取不到import_meta.url,导致new URL报错
解决方案
直接修改第三方包的源码(不推荐)
这段代码是在第三方包中的。像我使用的wasm-xlsxwriter。
位置在node_modules/wasm-xlsxwriter/web/wasm_xlsxwriter.js
if (typeof module_or_path === 'undefined') {
module_or_path = new URL('wasm_xlsxwriter_bg.wasm', import.meta.url);
}
改为
if (typeof module_or_path === 'undefined') {
module_or_path = new URL('wasm_xlsxwriter_bg.wasm', window.location.origin);
}
这样打包的时候就会修改为相对路径
但是这样肯定是不行的,以后不好维护
写一个rollup插件处理
我的项目是基于vben构建的,所以这里的文件夹都是基于vben来的。你们使用的时候根据自己的项目情况修改就行
取消wasm文件名称处理
找到vite中关于rollup的配置
我的配置文件路径:shop_web_admin\internal\vite-config\src\config\application.ts
找到viteConfig->build->rollupOptions->output->assetFileNames
目前的配置:
assetFileNames: '[ext]/[name]-[hash].[ext]',
修改为:
assetFileNames: (assetInfo) => {
return assetInfo.names[0]?.includes('.wasm')
? '[ext]/[name].[ext]'
: '[ext]/[name]-[hash].[ext]';
},
这样打包后的wasm文件就没有hash了,方便后续处理
写一个处理插件
我的插件目录:shop_web_admin\internal\vite-config\src\plugins
在该目录下新增插件:
const MagicString = require('magic-string');
export default function ParseWasmUrl() {
return {
name: 'parse-wasm-url',
transform: {
handler(code: string, id: string) {
const matches = [
...code.matchAll(
/new URL\((?:'|")([^'"]+)(?:'|"),\s*import\.meta\.url\)(\.href)?/g,
),
];
if (matches.length > 0) {
const s = new MagicString(code);
for (const match of matches) {
const start = match.index;
const [str] = match;
// 这里因为我的项目只使用了一个wasm组件,所以直接写死了
if (id.includes('wasm_xlsxwriter')) {
s.overwrite(
start,
start + str.length,
`new URL('/wasm/wasm_xlsxwriter_bg.wasm',window.location.origin)`,
);
}
}
return {
code: s.toString(),
map: s.generateMap({ source: id }),
};
} else {
return null;
}
},
order: 'post',
},
};
}
使用插件:
import parseWasmUrl from './parse-wasm-url';
/**
* 根据条件获取通用的vite插件
*/
async function loadCommonPlugins(
options: CommonPluginOptions,
): Promise<ConditionPlugin[]> {
const { devtools, injectMetadata, isBuild, visualizer } = options;
return [
{
condition: true,
plugins: () => [
topLevelAwait(),
viteVue({
script: {
defineModel: true,
// propsDestructure: true,
},
}),
viteVueJsx(),
wasm(),
parseWasmUrl(),
],
},
];
}
这样基本就没问题了,我们build一下
可以看到存在wasm文件夹
第三方的wasm文件已经打包好了
我们继续看打包后的源码
可以看到,已经修改成功。我们在页面上尝试一下:
已经成功获取
我们试一下功能
成功解决
参考:
https://www.rollupjs.com/plugin-development/#transform
https://www.rollupjs.com/configuration-options/#output-assetfilenames
vite打包第三方wasm项目,生产报错的问题
https://xuyuanhang.com/archives/viteda-bao-di-san-fang-wasmxiang-mu-sheng-chan-bao-cuo-de-wen-ti