Uppy 核心引擎 @uppy/core 完全指南:事件总线、状态管理与插件化文件上传架构
前端UI组件后端【免费下载链接】uppyThe next open source file uploader for web browsers :dog:项目地址https://gitcode.com/gh_mirrors/up/uppy点击查看免费下载uppy/core 是 Uppy 文件上传器的核心模块所有其他插件上传器、界面、远程源、预处理/后处理都以它为基础构建。本文以 packages/uppy/core/README.md 为骨架结合仓库源码深入讲解核心 API、构造参数、限制体系、插件生命周期与上传流水线读完即可独立完成最小集成、参数调优与自定义插件开发。从 README 认识 uppy/coreUppy 是一个精致、模块化sleek, modular的 JavaScript 文件上传器能与任何应用无缝集成。它把开发者的注意力从怎么造一个文件上传器中解放出来让开发者专注于更有价值的问题。其完整能力链路在 README 中概括为三步Fetch从本地磁盘、远程 URL、Google Drive、Dropbox 获取文件或通过摄像头自拍、录像Preview以友好的界面预览文件、编辑元数据Upload上传到最终目的地可选地经过处理/编码流程。其中 uppy/core 就是承载上述全流程的骨架它本身不含任何 UI也不负责实际的上传网络请求而是提供状态管理、事件总线、插件注册、文件生命周期、上传编排这五大核心能力。整个包只有约 8 KB 级别的心智负担所有细节能力都由挂载其上的插件提供。快速开始最小示例README 给出的最小示例只有三行import Uppy from uppy/core const uppy new Uppy() uppy.use(SomePlugin)把它扩充为一个真正可运行的最小集成需要搭配一个上传器插件例如uppy/xhr-upload与一个界面插件例如uppy/dashboard。在仓库的示例目录中可以看到完整参考examples/dashboard 相关示例 以及各框架示例examples/react/src/App.tsx、examples/vue/src/App.vue、examples/sveltekit/src/routes/page.svelte。import Uppy from uppy/core import Dashboard from uppy/dashboard import XHRUpload from uppy/xhr-upload const uppy new Uppy({ debug: true, autoProceed: false, restrictions: { maxFileSize: 5 * 1024 * 1024, allowedFileTypes: [image/*], }, }) uppy.use(Dashboard, { inline: true, target: #app, }) uppy.use(XHRUpload, { endpoint: /upload, }) // 监听事件完成时可以拿到每个文件的响应 uppy.on(complete, (result) { console.log(上传成功, result.successful) console.log(上传失败, result.failed) })安装与引入$ npm install uppy/core当前仓库中uppy/core的版本为 6.1.0见 packages/uppy/core/package.json采用 ESM 模块格式type: module。包的导出映射exports字段提供了细粒度的子路径uppy/core主入口lib/index.jsuppy/core/store-default默认状态仓库实现src/store/index.tsuppy/core/utils文件模型与工具函数src/utils/index.tsuppy/core/companion-client远程源/Companion 客户端src/companion-client/index.tsuppy/core/provider-views远程源浏览视图组件uppy/core/css/style.min.css与uppy/core/css/style.scss样式文件README 还提到如果不使用打包器也可以使用预构建 bundleTransloadit 的 Smart CDN。在该场景下Uppy会挂载到全局window.Uppy对象上。仓库内对应的聚合入口可参考 packages/uppy/src/bundle.ts它汇总了全部官方插件并暴露全局Uppy命名空间适合无构建工具的 CDN 直引场景。核心架构一个类承担五种职责Uppy类源码见 src/Uppy.ts是整个框架的心脏注释明确写道它负责Manages plugins, state updates, acts as an event bus, adds/removes files and metadata管理插件、状态更新、充当事件总线、增删文件与元数据。具体可以拆解为五个子系统状态容器内部使用 Store 保存整个上传会话的状态files、currentUploads、meta、totalProgress等默认是 DefaultStore一个极简的订阅发布实现可通过opts.store换成 Redux 等自定义 Store事件总线基于namespace-emitter实现所有on/once/off/emit方法都委托给它事件签名统一收敛在UppyEventMap类型中插件注册中心use()实例化插件、校验唯一 ID、登记到#plugins并按 type 分组getPlugin()/removePlugin()/iteratePlugins()负责查询、卸载与遍历文件管理器addFile/addFiles/removeFile/setFileMeta/getFile等构成文件的完整生命周期上传编排器维护三类处理函数集合——preProcessors预处理、uploaders实际上传、postProcessors后处理upload()会按顺序串行执行它们。类上还通过static VERSION packageJson.version暴露版本号并在debug: true时把实例挂到window[this.opts.id]上便于调试。构造参数 UppyOptions 详解UppyOptions的完整定义与默认值都可以从 src/Uppy.ts 与构造函数同文件第 487-567 行中核对。下表整理了全部参数及其默认值参数类型默认值说明idstringuppy实例 IDdebug 模式下会作为window上的全局键名autoProceedbooleanfalse添加文件后是否自动开始上传源码中通过#startIfAutoProceed()以 4ms 定时器调度allowMultipleUploadBatchesbooleantrue是否允许在上传进行中再次创建新批次上传false时上传期间禁止新增上传批次allowMultipleUploadsboolean—已废弃的旧版参数语义与allowMultipleUploadBatches相同debugbooleanfalse开启后使用内置debugLogger输出控制台日志并将实例暴露到windowloggerLoggerjustErrorsLogger自定义日志器若同时设置了logger与debug: true源码会忽略debug并给出警告restrictionsRestrictions全部为null/[]文件限制见下一节metaRecordstring, unknown{}全局元数据会合并进每个新加入文件的metaonBeforeFileAdded(file, files) UppyFile \| boolean \| undefined拒绝已存在的重复文件添加文件前的钩子返回false阻止添加返回对象则替换该文件onBeforeUpload(files) files \| boolean原样返回上传开始前的钩子返回false阻止上传返回对象则替换参与上传的文件集合localeLocale内置英文国际化文案详见 src/locale.tsstoreStoreStatenew DefaultStore()自定义状态仓库可对接 Redux 等infoTimeoutnumber5000信息提示toast的自动隐藏毫秒数其中restrictions采用了默认值与用户值合并的策略源码第 510-516 行确保用户只覆盖需要的字段。元数据默认值处理方式为meta: {}并在构造时写入 state。限制restrictions体系限制由 src/Restricter.ts 中的Restricter类实现Restrictions类型包含七个字段字段类型含义maxFileSizenumber \| null单个文件的最大字节数minFileSizenumber \| null单个文件的最小字节数maxTotalFileSizenumber \| null所有文件合计最大字节数聚合限制maxNumberOfFilesnumber \| null最大文件数量聚合限制minNumberOfFilesnumber \| null最少文件数量在upload()时校验allowedFileTypesstring[] \| null允许的 MIME 类型或扩展名如image/*、.png非数组会被拒绝并抛出TypeErrorrequiredMetaFieldsstring[]上传前必须填写的元数据字段名源码把校验分为两类与 PartialTreeFile 注释 中描述的个体限制与聚合限制一一对应个体限制validateSingleFileallowedFileTypes的匹配逻辑支持两种写法——含/的按 MIME 类型匹配用mime-match会剥离;后的参数以.开头的按扩展名不区分大小写匹配maxFileSize/minFileSize仅在文件大小已知size ! null时校验聚合限制validateAggregateRestrictionsmaxNumberOfFiles会把已有文件排除isGhost的恢复占位文件与新增文件相加后判断maxTotalFileSize对所有文件字节数求和判断。聚合校验较慢源码注释特别说明它单独在循环外执行避免批量添加大量文件时拖慢性能。限制失败会抛出带isRestriction true标记的RestrictionError并通过#informAndEmit触发restriction-failed事件、在界面中以 toast 形式展示最多同时展示 4 条超出部分合并为一条汇总提示。对应的错误文案如youCanOnlyUploadX、exceedsSize、noDuplicates、missingRequiredMetaField都定义在 src/locale.ts 中可通过locale选项整体替换或按 key 覆盖。插件系统use、BasePlugin 与 UIPlugin注册与校验use(Plugin, ...opts)src/Uppy.ts#L1954-L2006的注册流程是实例化插件 → 校验id与type必须存在 → 检查id是否唯一重复会抛错→ 按type分组存入#plugins→ 调用plugin.install()→ 触发plugin-added事件。因此所有插件都必须提供唯一的id可通过选项覆盖和type。BasePlugin无 UI 插件的基类src/BasePlugin.ts 是所有插件的公共基类注释明确指出它不包含 DOM 渲染因此适用于没有用户界面的插件如各种上传器。基类提供了uppy、opts、id、type、VERSION等公共字段getPluginState()/setPluginState()读写该插件在全局 state 中独立命名空间state.plugins[this.id]setOptions()合并新选项并重新初始化 i18n触发 UI 重渲染i18nInit()按[默认文案, uppy 级文案, 插件级文案]的优先级合并翻译四个可扩展生命周期钩子install()、uninstall()、update(state)每次状态变更时调用、afterUpdate()渲染完成后防抖调用addTarget()默认抛错要求子类实现以挂载到其他插件的目标中。UIPlugin带界面的插件基类src/UIPlugin.ts 继承 BasePlugin用 Preact 提供渲染能力适合 Dashboard、ImageEditor 等界面插件。它把 UI 渲染封装进防抖的#updateUI合并到微任务队列并在挂载到body这类特殊 target 时自动创建一个.uppy-Rootdiv 包裹避免 Preact diff 破坏外层结构。getTargetPlugin()支持把 target 指定为插件实例或插件类mount()则负责把渲染结果挂到 DOM 元素或目标插件中。查询与卸载getPlugin(id)遍历所有分组按id查找插件实例iteratePlugins(fn)扁平遍历全部插件removePlugin(instance)先触发plugin-remove再调用instance.uninstall()最后从分组中移除并清空其 state 命名空间src/Uppy.ts#L2050-L2075。以官方插件为参考上传器uppy/xhr-uploadpackages/uppy/xhr-upload/src、断点续传uppy/tuspackages/uppy/tus/src、S3uppy/aws-s3packages/uppy/aws-s3/src均属无 UI 的 BasePlugin 子类而uppy/dashboard、uppy/drag-drop等是 UIPlugin 子类。它们的公共 API 类型通过PluginTypeRegistry的模块增强机制与use的类型推导打通。事件系统UppyEventMap所有事件签名集中在UppyEventMapsrc/Uppy.ts#L355-L428常用事件如下事件回调参数触发时机file-added(file)单个文件成功加入files-added(files[])一批文件加入后触发一次file-removed(file)文件被移除upload(uploadID, files[])创建新上传批次upload-start(files[])上传开始core 会初始化每个文件的progress.uploadStartedupload-progress(file, progress)单个文件进度更新upload-success(file, response)单个文件上传成功响应中含uploadURLupload-error(file, error, response)单个文件上传失败upload-retry(file)重试某个失败文件complete(result)一次上传全部结束result含successful/failed/uploadIDerror(error, file?, response?)全局错误restriction-failed(file, error)文件未通过限制校验progress(progress)整体进度0-100state-update(prevState, nextState, patch)每次状态变更cancel-all/pause-all/resume-all/retry-all—对应批量操作is-offline/is-online/back-online—网络状态变化依赖window在线事件preprocess-progress/preprocess-complete/postprocess-progress/postprocess-complete(file, progress?)预处理/后处理阶段进度事件由 core 内部订阅器统一维护例如upload-error会同步写入state.error与对应文件的file.error、file.responseupload-start会把progress.uploadStarted置为Date.now()upload-success会把文件标记为uploadComplete: true、percentage: 100并设置uploadURL。这些内部监听器在构造时的#addListeners()src/Uppy.ts#L1711-L1927中注册。文件与上传 API添加文件addFile(file)接受原生File对象或 Uppy 文件描述符{ name, type, size, data }结构。源码#transformFile()src/Uppy.ts#L1039-L1108会补全文件名、MIME 类型、扩展名、生成唯一 ID含实例id前缀与初始 progress。单个文件添加失败会抛出首个错误包括限制错误并触发file-added与files-addedaddFiles(descriptors[])批量版本语义不同源码注释第 1265-1280 行限制失败不中断整批合法文件照常加入非法文件各自触发restriction-failed而onBeforeFileAdded等非限制错误会聚合为AggregateError抛出且整批一个都不加入、不触发files-added。批量添加时files-added只触发一次比循环addFile更高效。两个方法都会在autoProceed: true时自动调度上传。移除与重试removeFile(fileID)/removeFiles(fileIDs[])从files与各currentUploads的 fileIDs 中剔除若某上传批次因此清空则删除该批次全部文件移除后重置allowNewUpload、error、recoveredStatecancelAll()触发cancel-all移除全部文件并重置默认上传状态retryAll()/retryUpload(fileID)只重试带error且无缺失必填元数据的文件重试时会以forceAllowNewUpload: true创建新上传批次pauseAll()/resumeAll()/pauseResume(fileID)暂停/恢复依赖capabilities.resumableUploads能力标记uppy/tus等插件会将其置为true。upload() 与上传流水线upload()src/Uppy.ts#L2382-L2457的执行流程检查是否注册了uploader类型插件没有则记录警告自动重试上次失败的、尚未开始上传的文件执行onBeforeUpload钩子返回false则中止校验minNumberOfFiles与必填元数据字段收集所有未开始上传且未归属任何批次的文件创建新的uploadIDnanoid 生成通过#runUpload串行执行流水线预处理处理器preProcessors→ 上传器uploaders→ 后处理处理器postProcessors每一步都以(fileIDs, uploadID)为入参汇总结果按file.error区分successful与failed写入currentUploads[uploadID].result触发complete事件。#createUploadsrc/Uppy.ts#L2201-L2233还通过allowMultipleUploadBatches控制allowNewUpload实现上传进行中是否允许再加新文件。整体进度则由#calculateTotalProgress计算按已上传字节数/总字节数加权平均并以 500ms 节流更新注释解释了节流阈值对 Dashboard 焦点动画与性能的权衡见 src/Uppy.ts#L1631-L1642。元数据、国际化与信息提示setMeta(data)合并全局 meta 并同步合并进所有已有文件的metasetFileMeta(fileID, data)只更新单个文件文件不存在时仅记日志i18n/i18nArray构造时由Translator初始化按[默认 locale, opts.locale]合并缺失的 key 会以 error 级别记日志info(message, type, duration)向state.info追加信息条目type 为info | warning | error | success供 Dashboard 等 UI 显示 toast并在duration毫秒后自动移除同时触发info-visible/info-hiddenlog(message, type)把消息路由到opts.logger的error/warn/debug方法。状态与 StoreState接口src/Uppy.ts#L280-L309包含meta、capabilitiesuploadProgress、individualCancellation、resumableUploads、isMobileDevice、darkMode、currentUploads、allowNewUpload、recoveredState、error、files、info、plugins、totalProgress、companion等字段。capabilities.uploadProgress在构造时通过supportsUploadProgress()src/supportsUploadProgress.ts探测浏览器能力。默认DefaultStoresrc/store/index.ts是一个约 50 行的极简实现getState返回对象、setState浅合并 patch 并通知所有订阅者、subscribe返回取消订阅函数。你也可以注入自定义 Store如 Redux只要满足同样的getState/setState/subscribe接口即可。每次setState都会触发一次state-update事件updateAll()随即把新状态分发给所有插件的update()方法——这就是 Uppy 响应式 UI 的底层机制。调试与日志构造时设置debug: true会启用debugLogger输出到浏览器控制台并把实例暴露为window.uppy默认id。也可以通过logger选项传入自定义日志器例如对接服务端日志或把日志聚合成结构化数据。源码 src/loggers.ts 中定义了debugLogger与justErrorsLogger两个内置实现。在仓库中继续探索核心类与完整 APIpackages/uppy/core/src/Uppy.ts公开导出面packages/uppy/core/src/index.ts导出Uppy、BasePlugin、UIPlugin、RestrictionError、类型与debugLogger等无 UI 插件基类packages/uppy/core/src/BasePlugin.ts带 UI 插件基类packages/uppy/core/src/UIPlugin.ts限制校验实现packages/uppy/core/src/Restricter.ts默认 Storepackages/uppy/core/src/store/index.ts内置文案packages/uppy/core/src/locale.ts文件模型与工具packages/uppy/core/src/utils/index.ts核心单元测试packages/uppy/core/test/Uppy.test.ts 与 packages/uppy/core/test/types.test.ts聚合 bundle 入口packages/uppy/src/bundle.ts理解 uppy/core 之后再去看uppy/xhr-upload、uppy/tus、uppy/aws-s3等上传器如何调用addUploader、addPreProcessor/addPostProcessor以及uppy/dashboard如何用UIPlugin渲染整个界面就能对 Uppy 的插件化架构形成完整的闭环认知。赞分享前端UI组件后端【免费下载链接】uppyThe next open source file uploader for web browsers :dog:项目地址https://gitcode.com/gh_mirrors/up/uppy点击查看免费下载相关推荐突破上传黑盒Uppy状态管理核心技术与实战指南突破上传黑盒Uppy状态管理核心技术与实战指南 Uppy是一款功能强大的开源文件上传器专为现代Web浏览器设计提供直观的用户界面和高效的文件处理能力。它通前端UI组件后端终极指南Uppy自定义文件上传状态类型完全教程终极指南Uppy自定义文件上传状态类型完全教程 Uppy是一个强大的开源文件上传器为现代Web浏览器提供了丰富的文件上传功能。通过自定义上传状态类型开发者前端UI组件后端从文件添加到上传完成Uppy事件系统全解析从文件添加到上传完成Uppy事件系统全解析 你是否曾在开发文件上传功能时遇到这些困扰无法实时显示上传进度、文件状态变化难以追踪、错误处理不及时导致用户体验下前端UI组件后端上一篇Iconify图标颜色控制终极指南从单调图标到彩色emoji的完整解决方案下一篇如何用Ultimate Vocal Remover轻松分离人声与伴奏3步掌握AI音频处理技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →