elements
elements copied to clipboard
Mux Uploader Server Component
Let's take another shot at #712...
How to use it
import MuxUploader, { other, named, imports } from '@mux/mux-uploader-react/rsc';
Defaults
If no endpoint is specified, will use @mux/mux-node to create a direct upload with the following configuration:
{
cors_origin: '*',
new_asset_settings: {
playback_policy: ['public'],
encoding_tier: 'baseline',
}
How to configure
Accepts all the same params as Mux Uploader, as well as
interface MuxUploaderServerProps extends MuxUploaderProps {
clientOptions?: ClientOptions; // allows you to configure the @mux/mux-node client
uploadCreateParams?: Partial<Mux.Video.Uploads.UploadCreateParams>; // allows you to configure the direct upload
uploadRequestOptions?: Partial<Mux.RequestOptions>; // allows you to configure the direct upload request
}
uploadCreateParams will be deep-merged with the default options described above
How it gets bundled
"build:rsc:cjs": "esbuild src/rsc.tsx --target=es2019 --platform=node --bundle --sourcemap --metafile=./dist/cjs-rsc.json --format=cjs --loader:.css=text --outdir=dist --out-extension:.js=.cjs.js --external:react --external:prop-types --external:server-only --external:./index",
"build:rsc:esm": "esbuild src/rsc.tsx --target=es2019 --platform=node --bundle --sourcemap --metafile=./dist/esm-rsc.json --format=esm --loader:.css=text --outdir=dist --out-extension:.js=.mjs --external:react --external:prop-types --external:server-only --external:./index",
lemme point out some interesting flags, here:
--platform=node: in order to avoid bundling dependencies likecrypto, esbuild requires this of us. Luckily, Server Components run on the server, so, this is correct--external:server-only: the contents of this package is literally justthrow new Error('This is a server component and can't be imported in a client component')(paraphrased). If we were to bundle it, our bundle would immediately throw an error. I suspect that, in practice, server-component-compliant bundlers will know to ignore this import. Even so, shouldserver-onlybe marked as a peer dependency? π€--external:./index: In order for server component bundlers to leave the server stuff on the server and the client stuff on the client, we have to ship the server bundle and the client bundle separately. By markingindexas external, we're telling esbuild "don't include the client bundle in the server bundle". Instead, consumer bundlers will see this indist/rsc.mjsand resolvedist/index.mjs(ordist/rsc.cjs.jsanddist/index.cjs.jsrespectively).
TODO items:
- [ ] get some feedback
- [ ] consider this as a way to export the module
- [ ] documentation
- [ ] two questions for those of you who understand bundlers better than I do...
- [ ] am I correct about what I did with
--external:server-onlyand--external:./index? This seems to work in our test Next app, so that's a good sign... - [ ] why is
@mux/mux-uploader-react/rscgiving me a red squiggle in the nextjs example? why can't typescript find it? or is that just something in my environment?
- [ ] am I correct about what I did with
Other passing thoughts
I don't re-export the types, so right now if you want those, you'll have to import type { ... } from '@mux/mux-uploader-react'. TypeScript should pick up on that; I'm not worried
@decepulis is attempting to deploy a commit to the Mux Team on Vercel.
A member of the Team first needs to authorize it.
The latest updates on your projects. Learn more about Vercel for Git βοΈ
| Name | Status | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| elements-demo-create-react-app | β Ready (Inspect) | Visit Preview | π¬ Add feedback | Apr 25, 2024 4:46pm |
| elements-demo-nextjs | β Failed (Inspect) | Apr 25, 2024 4:46pm | ||
| elements-demo-svelte-kit | β Ready (Inspect) | Visit Preview | π¬ Add feedback | Apr 25, 2024 4:46pm |
| elements-demo-vanilla | β Ready (Inspect) | Visit Preview | π¬ Add feedback | Apr 25, 2024 4:46pm |
| elements-demo-vue | β Ready (Inspect) | Visit Preview | π¬ Add feedback | Apr 25, 2024 4:46pm |
What could it look like for this component (or set of them) to be able to return things like an asset ID / playback ID?
Running into a huge blocker with this. Consider the following:
import MuxUploader from '@mux/mux-uploader-react/rsc';
function MuxUploaderPage() {
return (
<MuxUploader onSuccess={console.log} />
);
}
export default MuxUploaderPage;
However, you can't pass client functionality (in our example, console.log) to server components. Props have to be serializable.
Gotta think of another interface if we want this to happen...
What could it look like for this component (or set of them) to be able to return things like an asset ID / playback ID?
@mmcc btw just to answer this. Server Actions would make this really slick. Under the hood, we could implement something like this:
// packages/mux-uploader-react
import 'server-only'
import MuxUploaderClient from './index'
const MuxUploaderServer = (props) => {
const upload = await mux.video.uploads.create(...);
return (
<MuxUploaderClient
endpoint={upload.url}
onSuccess={
"use server"
const assetId = await getAssetIdForUpload(upload.id)
props.onAssetId(assetId)
}
/>
)
}
And it gets more exciting. We could even poll the asset API to provide a UI that updates with the asset preparing status. Cool stuff!
I've actually got this implemented in another branch.
Just gotta think through... my previous comment...