Splitting into multiple packages
See original GitHub issueWe’ve been planning on splitting Uppy into multiple npm packages for a while. We’re hoping to do it in the coming weeks. I’m opening this issue to explore some of the challenges and propose some ideas on how to do it! A bunch of these were discussed in our Slack call yest.
The easiest way to manage many packages seems to be using lerna. We can have a folder structure like this:
packages/uppy
packages/uppy-core
packages/uppy-dashboard
packages/uppy-tus
packages/uppy-util
packages/uppy-provider-views
packages/uppy-react
These could either be published on npm as uppy-core
or as scoped packages like @uppy/core
. I quite like scoped packages, they clearly show that packages are part of some bigger project. uppy-core
would also work tho and put us on even footing with community packages. That could be good or bad 😃
Here uppy
would be a package that depends on all the other plugins, acting like the current uppy
npm package. You could do import { Dashboard } from 'uppy'
with it. We should provide an ES modules and a CJS entry point for this one so import
syntax gets tree shaking by default when used with webpack.
uppy-core
would contain the Core class.
- It could include the Plugin base class, too.
- We could have the Plugin base class in a separate package.
Personally I like the aesthetics of having it in a separate package more, but it may be better to have the Core and Plugin classes tied to the same version, otherwise you might expect different
uppy-plugin
versions to work with a singleuppy-core
version. I’m not sure if we want to guarantee that.
uppy-dashboard
and other UI plugins would just export their plugin class. Depending on the above decision, I think they would either have a peerDependency on uppy-core
or a direct dependency on uppy-plugin
.
The major issue with UI plugins is how to tackle CSS. Currently, I believe the team’s consensus is leaning towards just sticking a separate CSS file in each plugin, that you have to import separately. Another option is to insert CSS automatically at runtime but this may step on some existing CSS’s toes (where to insert? depending on that choice, we may override some existing rules, or not)
// browserify
const css = require('sheetify')
const Dashboard = require('uppy-dashboard')
css('uppy-dashboard/style.css')
// webpack
import Dashboard from 'uppy-dashboard'
import 'uppy-dashboard/style.css'
uppy-tus
and other plugins that don’t have UI would just export their plugin class, there is not much else to do here.
uppy-util
would serve as our grab bag of utility functions. Instead of a single file like the current Utils.js
, this could be a good opportunity to move functions into separate files. Then plugins can require uppy-util/lib/functionName
. Plugins should just depend directly on uppy-util
, I think. Even if you end up with multiple versions of it in your node_modules folder that would not be a big deal because only a few small functions would be duplicated.
uppy-provider-views
and other Provider-related modules would export whatever they need to, doesn’t really matter how or whatever since users would not include it manually anyway. Like uppy-util
, it’s just for sharing code internally. There is a question about how to deal with CSS here though. Should it expose its own CSS file or should providers like GoogleDrive do it instead? In the latter case, you might end up with lots of duplicate CSS by default. We could also include it in the Dashboard’s CSS file. That would add some unnecessary weight for people who only use local uploads but it would be the easiest solution I think.
uppy-react
would contain all the React components. We could also have separate packages for each component. I think having a single package is fine though. People could do require('uppy-react/lib/Dashboard')
or import {Dashboard} from 'uppy-react'
.
We would need to change the Babel build a little, currently we just run babel-cli to transform src
to lib
but if the src/ is split into packages/*/src
that is a little harder. In munar I used gulp: https://github.com/welovekpop/munar/blob/master/gulpfile.js We could also write a custom script and stick it in ./bin/build-lib
or somethin. That would be more in line with our current build steps, and npm would still be our task runner.
I think it would be cool to have the documentation from the website in each plugin’s README file. You could use readme to read documentation for installed plugins offline. We could probably have a simple prepublish script that inserts the documentation into a readme template like
# uppy-tus
<!-- insert-docs ../../website/src/docs/tus.md -->
Have it strip the yaml front matter. We can do that separately after the fact tho.
Issue Analytics
- State:
- Created 5 years ago
- Comments:19 (14 by maintainers)
In addition to the above I like the way multiple packages abstract over the filesystem; instead of having to reach into
uppy/lib/plugins/Dashboard
, which forces Uppy’s internal organisation to be a public API, you can use@uppy/dashboard
. With lerna changes in our file structure or build process will not affect the public API.The way you use official plugins and third party plugins becomes more similar—the only difference being
@uppy/transloadit
vsuppy-competitor
rather thanuppy/lib/plugins/Transloadit
vsuppy-competitor
.nice!
tiny: link to lerna in first post is not working anymore. should be https://github.com/lerna/lerna