Closed saitonakamura closed 1 year ago
I tried to come up with a way that doesn't require current users to mandatory use a provider if they are fine with yoga-layout-prebuilt
. There's one, however it complicates the code too much IMO so I don't like it, but here it is
Instead of calling useYoga inside Flex and Box, allow to accept yoga as a prop
Then on an entrypoint level provide wrappers that either import yoga-layout-prebuilt
(vanilla) or get the value from the provider (wasm experience). Probably will look like
index.tsx
import { Flex: FlexImpl, FlexProps } from './Flex'
import Yoga from 'yoga-layout-prebuilt'
export const Flex = (props: FlexProps) => <FlexImpl yoga={Yoga} {...props} />
outerRuntime.tsx
import { Flex: FlexImpl, FlexProps } from './Flex'
import { useYoga } from './hooks'
export const Flex = (props: FlexProps) => {
const Yoga = useYoga()
return <FlexImpl yoga={Yoga} {...props} />
}
If you know another way to do this without breaking change, please speak up
@astahmer wasm experience will work like this. Let me know if works for you
import YogaWasmFile from 'yoga-layout-wasm/dist/yoga.wasm?url' // ?url this a vite thing to force file-loader
function App() {
const initYoga = useCallback(() => Yoga.init(YogaWasmFile), [])
return (
<YogaProvider initYoga={initYoga}>
{...}
</YogaProvider>
)
}
will it making it easier if we host the yoga wasm (for instance yoga.pmnd.rs)? that's how useGLTF with draco currently works. the binary is hosted by google in that case and it's usually pre-cached by the browser. we do give users the ability to self host, in which case they'll have to put binaries into /public and the loader then merely xhr-fetches them.
it could look like this:
import { Flex } from '@react-three/flex'
const Layout = () => (
<Flex>
import { Flex } from '@react-three/flex'
const Layout = () => (
<Flex binary="/yoga/index.wasm">
though i think "Flex" is just a generic component, haven't used it for longer. im also OK with a provider, though perhaps in that case as well Flex could function without any breaking changes if we default it to a CDN.
<Yoga binary="/index.wasm">
<Flex>
...
</Yoga>
at least that's how threejs deals with wasm and i think it works quite well for them. imports would be also fine if bundlers can deal with them.
It will, but only partly. It will help with settings up file-loader style of wasm file import (there was a problem with because it tries to precompile wasm files), for other bundles it's just a chore (but can be tricky if certain framework isn't flexible enough, create-react-app for instance).
But that's only one side of a coin, another side is that yoga-layout-wasm js glue tries to import path
and fs
for some reason, it's even somewhat mentioned in the docs, but trying to set it to false with webpack lead me to webpack complaining that it should be a string
Because of the latter issue I couldn't set yoga-layout-wasm
up in neither of bundlers expect vite (I tried webpack and esbuild). And simultaneously, vite is the only one that can't use yoga-layout-prebuilt
. I mean, it's basically a mess so that led me to idea that since there's no one-size-fits-all yoga js bindings, I'm essentially exposing a way to pass an outer runtime
I'll be trying to write my own wasm binding for yoga, maybe even without emscripten, but I'm pretty sure that's gonna take a long time so...
Disclaimer: my original idea was to just replace
yoga-layout-prebuilt
withyoga-layout-wasm
(like #67 or #37 ), but my experements proved importing wasm files and usingyoga-layout-wasm
in general is not easy task and requires configuring userland bundler, hurting the UX. For instance, I experienced cryptic webpack errors in storybook, vite tried to prebuild the wasm file instead of importing it as a url and so on. So I decided that if we can provide a way to pass a outer yoga runtime while still having the ability to use vanillayoga-layout-prebuilt
experience -- that's the right wayThis is mainly to allow usage of yoga-layout-wasm. From now on there's 2 entrpoints, a default one with YogaPrebuiltProvider (which uses yoga-layout-prebuilt) and outerRuntime that exports YogaProvider that allows to pass an arbitrary runtime (that conforms with Yoga types)
This is a breaking change because library users will have to place a YogaProvider/YogaPrebuiltProvider in their code
Fixes #66