从CRA迁移到Vite后react-dropzone-uploader生产环境报Minify React错误#130
问题根因
该报错(React Minified Error #130)本质是生产环境下拿到的Dropzone不是合法的React组件,而是包裹了组件的CommonJS模块对象,问题出在Vite和CRA对CommonJS格式第三方包的默认导入处理逻辑差异:
react-dropzone-uploader是基于CommonJS规范打包的组件库- CRA内置的webpack对CommonJS的默认导入做了兼容处理,直接
import Dropzone from 'react-dropzone-uploader'就能拿到组件本身 - Vite开发环境为了兼容热更新,对CJS包的导入做了特殊适配,所以开发环境运行正常
- Vite生产构建时默认会把CJS包的导出封装为
default属性挂载的对象,此时你导入的Dropzone实际是{ default: [组件对象] },渲染时传入非React节点就会抛出130错误
解决方案
方案1(最快生效,无需改配置)
修改导入语句,兼容CJS包的导出格式:
// 替换原来的import语句 import DropzonePkg from "react-dropzone-uploader"; const Dropzone = DropzonePkg.default || DropzonePkg;
如果是TypeScript项目也可以直接写:
import Dropzone = require("react-dropzone-uploader");
方案2(修改Vite配置,全局兼容CJS包处理)
在vite.config.js/vite.config.ts中添加如下配置,强制Vite对该包做正确的CJS转ESM处理:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], // 开发环境预构建包含该包 optimizeDeps: { include: ['react-dropzone-uploader'] }, // 生产构建CJS转译规则包含该包 build: { commonjsOptions: { include: [/react-dropzone-uploader/, /node_modules/] } } })
额外代码优化提示
你当前代码中getUploadParams方法内存在变量名冲突:方法入参有body,内部又定义了const body = new FormData(),导致你无法拿到外层传入的body参数,如果需要把传入的body参数内容塞入FormData,需要修改内部变量名,同时注意FormData不能用Object.keys遍历,正确写法参考:
const getUploadParams = ({file, meta}) => { const formData = new FormData() // 遍历传入的body参数,塞入FormData if (body) { Object.keys(body).forEach(k => { formData.append(k, body[k]) }) } formData.append('title', file.name.split(".")[0]) formData.append('file', file) return { url: `${api.getURL()}${url ? url : 'user/files'}`, body: formData, field: {}, headers: {Authorization: `Bearer ${api.Auth.getAccessToken()}`}, meta: meta } }
内容的提问来源于stack exchange,提问作者Victor Smits
相关产品推荐
相关产品推荐

