DEV Community

Discussion on: React Beginner Question Thread ⚛

Collapse
 
iamandrewluca profile image
Andrei Luca • Edited

For example I am working on a white-label product. And one component should look different for different environments. CSS and HTML also may differ. How would be a right way to make, kind of, interface for a component, and use a specific implementation for a environment.
I tried to make something like this, it seems to work. But is this the right way?

app.js
MyCmp/
  index.js
  env1.js
  env2.js
  ...

// index.js
const MyCmp = require(`./${process.env.MY_ENV}`)
export default MyCmp

// app.js
import MyCmp from './MyCmp'

process.env.MY_ENV gets assigned depending on env.

Collapse
 
sompylasar profile image
Ivan Babak

Not quite relevant, but I'd like to share some experience on that because I believe this kind of problems is quite rare.

When my team was building a white-label product (not entirely in React and no variations in component behavior and HTML markup, mostly styles and texts in different languages, texts included HTML in a few places), we made a build system that spits out separate bundles for each "partner" and an app loader that loads the respective bundle given the "partner" identifier in runtime.

We split the bundled code into the core bundle which contained all the component implementations and the core component styles, a "partner" style bundle which included partner style overrides (we relied on CSS cascade to apply the overrides), and a messages bundle which included the translations compiled for the "partner" from the base and the overrides during the build.

This happened before the CSS modules came into play, so this might not be the best possible implementation, but it works for several years now, and gradual introduction of React into the app didn't change the approach. We used the BEM naming methodology for our components' CSS class names and LESS mixins provided by the components to ensure theming uses the appropriate style overrides in the "partner" bundles.

Collapse
 
dan_abramov profile image
Dan Abramov

It's a pretty abstract question. It's not clear what you mean by "environments", what actually gets deployed, whether there is any common code (and if there is, what differs between environments). It would help to see a more specific (small) example.

Collapse
 
iamandrewluca profile image
Andrei Luca • Edited

When devloping a white-label product, and have more customers with their own brand books. You want to make UI to look different for each one. And sometimes just CSS does not help. You need to have different markup so component could look different for each customer. I know it's pretty abstract :)

github.com/iamandrewluca/white-lab...

Now if I change REACT_APP_CUSTOMER in .env file I get different src/components/customer

Thread Thread
 
dan_abramov profile image
Dan Abramov • Edited

Why not export a component that takes props? In your example, <Customer name="Dan" /> or <Customer name="Andrew" />. Then you can have different apps render the same component with different props.

Of course in practice you'd have more props, but you can also pass a whole object with them, e.g. <Customer brandData={{name: 'Andrew', color: 'red'}} />. If it’s too cumbersome to pass it down the tree to every component you can also use context for this.

The reason I dislike your solution is that you end up bundling all variations for every single deployment. So your bundle for a baby powder brand would also contain all the strings you use for a vodka brand. Not great.

Thread Thread
 
iamandrewluca profile image
Andrei Luca • Edited

Actually I looked into compiled sources and is not bundling all variations.
Thanks for your reply!

Thread Thread
 
dan_abramov profile image
Dan Abramov

Good to know! I guess webpack is smart enough to do the replacement earlier :-). This is still not a great future-proof approach because it relies on requires whereas the ecosystem has been moving to ES modules. It’s also much harder for any other tools to understand what’s going on in your modules.