I am working on a web app in which I need locally-defined React components to 'over-write' (i.e. take precedence over) default React components that are in a common code base. The common code base is required as a dependency by the local app, and it provides the server code and the default components.
The goal is that if you require the common code base and run the app without making any changes, you get a vanilla version of the app, but if you locally define a component (for example Logo.jsx), then the app should use that version of Logo.jsx rather than the default component in the underlying code base.
My first thought is to solve this by using a dynamic import statement in all of the components in the underlying code base, so that at build time webpack would simply look for local versions of the components and then either include the local version in the dependency graph or else use the fallback component. In pseudocode, my ideal version of this solution would look something like this:
define a custom import statement (importCustomOrDefaultComponent.js):
function importCustomOrDefaultComponent(name) {
// check for a component with this name in the local project, and if so, return
// if no local component exists, return the default component from this repo
}
module.exports = importCustomOrDefaultComponent;
use that custom import statement in all components in underlying code base (e.g. a NavBar component):
import React from 'react';
const importCustomOrDefaultComponent = require('../importCustomOrDefaultComponent.js');
const Logo = importCustomOrDefaultComponent('Logo.jsx')
function NavBar () {
return (
<div>
...
<Logo />
...
</div>
);
};
export default NavBar;
I have been fiddling with this and it does not seem possible to do as I have outlined above, because webpack won't let you use a custom import statement like this to affect how it builds the dependencies. I tried writing importCustomOrDefaultComponent using 'fs' to look for the custom file, but that didn't work because webpack tried to bundle the function in with everything else and ultimately I got an error because 'fs' will not be available in the browser... It seems you can only use require('xxx') or import xxx from 'xxx'. Is the above possible to do, and if so, how would that importCustomOrDefaultComponent(name) operate?
If this can't be done via a custom import function in the source, could this be done via a webpack plugin? I was unable to find any that handle this case.
If this can't work, are there alternative patterns to accomplish my goal?
- I have looked into code splitting, but while it splits up the code it does not seem to provide a solution for being able to dynamically choose whether to include component A or component B at build time.
- I also considered pursuing a plugin architecture, where custom components are stored in redux state and are accessed dynamically client side instead of trying to make these decisions while building the client bundle. Is that a better approach?