Next.js中Web Worker调用.wasm文件加载异常如何解决?
sql.js的Web Worker脚本默认以相对自身运行路径的规则请求同目录下的sql-wasm.wasm文件。
当你通过new URL(..., import.meta.url)方式引入Worker脚本时,Next.js的构建逻辑会自动将Worker文件输出到/_next/static/chunks/目录,此时Worker内部发起的wasm请求会默认指向chunks目录。但存放在public目录下的wasm文件不会被自动同步到该路径,触发404响应,服务端默认返回HTML格式的404页面,最终触发WebAssembly魔数不匹配的编译错误。
你手动把wasm文件复制到chunks目录后功能正常,也直接印证了这个路径匹配问题。
按实现成本从低到高排序,选一种即可:
方案1:直接用public目录绝对路径引入(零配置首选)
public目录下的静态文件会被Next.js直接映射到站点根路径,不需要经过webpack打包处理:
- 确认
worker.sql-wasm.js和sql-wasm.wasm两个文件都存放在public/assets/目录下 - 直接用根绝对路径初始化Worker即可,不需要额外配置路径:
const createDb = () => { const worker = new Worker("/assets/worker.sql-wasm.js"); worker.onerror = (e) => console.log("Worker error: ", e); return worker; };
这种方式下Worker和wasm文件同属/assets/路径,Worker内部的相对路径请求可以直接命中正确的wasm资源,不需要改任何构建配置。
方案2:自定义locateFile参数(保留打包引入方式)
如果你希望通过import.meta.url的方式引入Worker走webpack打包逻辑,可以通过sql.js提供的locateFile配置项手动指定wasm的公网访问路径:
- 确认
public/assets/sql-wasm.wasm对应的公网访问路径为/assets/sql-wasm.wasm - 修改Worker初始化逻辑,在Worker加载完成后传入路径配置:
const createDb = () => { const worker = new Worker( new URL("../public/assets/worker.sql-wasm.js", import.meta.url) ); // 自定义wasm文件请求路径 worker.postMessage({ action: "config", config: { locateFile: (filename) => filename.endsWith(".wasm") ? "/assets/sql-wasm.wasm" : filename } }); worker.onerror = (e) => console.log("Worker error: ", e); return worker; };
注意:new URL()的相对路径要根据当前页面的实际目录层级书写,避免Worker本身加载404。
方案3:配置webpack自动复制静态资源
如果你不想修改业务代码,可以通过webpack插件在构建/启动开发服务时,自动把wasm文件复制到Next.js的chunks输出目录:
- 安装复制依赖:
npm install copy-webpack-plugin --save-dev
- 修改项目根目录下的
next.config.js配置:
const CopyPlugin = require("copy-webpack-plugin"); const path = require("path"); /** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config, { dir }) => { config.plugins.push( new CopyPlugin({ patterns: [ { from: path.join(dir, "public/assets/sql-wasm.wasm"), to: path.join(dir, ".next/static/chunks/sql-wasm.wasm"), }, ], }) ); return config; }, }; module.exports = nextConfig;
- 重启开发服务或者重新执行生产构建,即可自动完成文件复制,不需要手动操作。
配置完成后打开浏览器开发者工具的网络面板,筛选wasm请求:
- 请求状态码为200
- 响应头
Content-Type为application/wasm - 响应内容为二进制格式,而非HTML文本
满足以上条件即代表资源加载正常,sql.js可以正常初始化数据库实例。
内容的提问来源于stack exchange,提问作者Mxngls

