Supabase客户端在Shopify Hydrogen开发环境触发MiniOxygen错误排查
在基于最新版Shopify Hydrogen/Remix的pnpm monorepo项目中,将@supabase/supabase-js导入server.ts或特定路由时,执行shopify hydrogen dev --codegen会触发MiniOxygen错误:
MiniOxygen couldn't load your app's entry point. ReferenceError: exports is not defined at /@fs/home/xx/repos/root/node_modules/.pnpm/@supabase+postgrest-js@1.18.1/node_modules/@supabase/postgrest-js/dist/cjs/index.js?v=1f494df2:5:23 at /@fs/home/xx/repos/root/node_modules/.pnpm/@supabase+postgrest-js@1.18.1/node_modules/@supabase/postgrest-js/dist/esm/wrapper.mjs?v=1f494df2:1:110 at /@fs/home/xx/repos/root/node_modules/.pnpm/@supabase+supabase-js@2.48.1/node_modules/@supabase/supabase-js/dist/module/SupabaseClient.js?v=1f494df2:2:31
但执行npm run build && shopify hydrogen preview可正常启动项目,Supabase功能完全正常。项目中supabase-js安装在子目录working_folder,但错误指向根目录node_modules中的依赖;已尝试指定自定义fetch实现,问题未解决,临时采用直接请求调用Supabase的方案。
核心疑问解答
1. Vite在Worker环境下处理@supabase/supabase-js或@supabase/postgrest-js是否存在开发环境问题?
是的,这是Vite开发环境处理混合模块(CJS+ESM)的典型问题。Supabase相关依赖(如@supabase/postgrest-js)打包时混用了CJS和ESM格式,MiniOxygen开发环境基于Vite的Worker runtime,而Vite在开发模式下对CJS模块的转译不彻底——当模块内部使用exports却被ESM模块引入时,Worker环境(无Node.js CommonJS模块系统)会抛出exports is not defined错误。生产构建时Vite会完成全量打包转译,将所有模块统一处理为Worker兼容格式,因此不会报错。
2. 如何配置MiniOxygen/Vite环境解决exports is not defined错误?
推荐尝试以下几种方案:
- 强制Vite转译Supabase依赖:在项目
vite.config.ts中,将Supabase相关包加入optimizeDeps.include和ssr.noExternal,确保开发环境下Vite转译这些依赖:
import { defineConfig } from 'vite'; import hydrogen from '@shopify/hydrogen/plugin'; export default defineConfig({ plugins: [hydrogen()], optimizeDeps: { include: ['@supabase/supabase-js', '@supabase/postgrest-js'], }, ssr: { noExternal: ['@supabase/supabase-js', '@supabase/postgrest-js'], }, });
- 直接使用Supabase的ESM入口:修改导入语句,跳过CJS模块加载:
import { createClient } from '@supabase/supabase-js/dist/esm/index.js';
- 调整pnpm monorepo依赖隔离:在子目录
working_folder的package.json中添加配置,确保Supabase依赖安装在子目录而非根目录:
{ "pnpm": { "public-hoist-patterns": ["@supabase/*"] } }
执行pnpm install重新安装依赖,确保依赖路径正确。
- 自定义Vite插件修复CJS导出:如果以上方案无效,可写简单插件替换CJS模块中的
exports写法:
import { defineConfig } from 'vite'; import hydrogen from '@shopify/hydrogen/plugin'; export default defineConfig({ plugins: [ hydrogen(), { name: 'fix-cjs-exports', transform(code, id) { if (id.includes('@supabase/postgrest-js/dist/cjs')) { return code.replace(/exports\./g, 'globalThis.exports = globalThis.exports || {}; exports.'); } return code; }, }, ], });
3. 是否有开发者在MiniOxygen等Worker环境中遇到并解决过该问题?
是的,不少Hydrogen开发者在社区反馈过类似问题,核心解决思路均围绕Vite配置强制转译依赖、调整pnpm依赖安装策略或使用ESM入口展开。例如在Shopify Hydrogen的Discord社区和GitHub Issues中,多个用户通过添加ssr.noExternal配置解决了Supabase的模块兼容问题。
4. Vite或Worker配置中是否存在导致该差异的设置?
开发与生产环境的差异主要源于Vite打包策略:
- 开发环境:Vite采用按需编译,对CJS模块转译仅做浅层次处理,未完全转换导出方式,而Worker环境无Node.js的
module和exports对象,因此报错。 - 生产环境:Vite会完成Tree Shaking和全量模块转译,将所有依赖打包为Worker兼容的ESM格式,自动处理CJS到ESM的转换,因此无报错。
此外,pnpm的依赖提升机制可能导致子项目加载了根目录的CJS版本依赖,而非子目录中安装的ESM兼容版本,这也是差异产生的原因之一。
内容的提问来源于stack exchange,提问作者jip101

