1

I'm designing a React application that needs to have multiple different builds that use different styles and images, e.g. header.png image that differs between different deployed applications.

I've used the create-react-app to initialize my project, and I'd love to structure my project so that I have one common directory for common CSS/images, and then a custom directory for each build, something along the lines of:

node_modules
public
  \--index.html
src
  |--resource
  |    |--common
  |    |    |--img
  |    |    \--styles
  |    |--build1
  |    |    |--img
  |    |    \--styles
  |    \--build2
  |         |--img
  |         \--styles
  |--App.js
  \--index.js
package.json

How would I do this in a way where a) the final build would only include files intended for that build and b) I wouldn't have to worry about the current build everywhere in the code.

2
  • so you mean there are multiple apps in a project, and each app has it's own build? Commented Jun 16, 2020 at 8:45
  • There is just one app, but it needs to look different for different clients. Images, styles, etc. change, while functionality and content stay the same Commented Jun 16, 2020 at 9:10

1 Answer 1

1

There are three things have to do.

Import path

I assume that your image files in img folder such as jpg, png, SVG will be import into component.

I will use customize-cra and react-app-rewired to override webpack config to configure different import paths depends no different clients.

First you have to install them, then you can create a file called config-overrides.js in your project root, and set alias path for your resource such as CSS, SVG icon in config-overrides.

config-overrides.js

const path = require('path');
const { addWebpackAlias, override } = require('customize-cra')

const resolveApp = relativePath => path.resolve(__dirname, relativePath)

module.exports.configOverrides = {
  webpack: override(
    addWebpackAlias({
      'common': resolveApp('src/resource/common'),
      '@': resolveApp(`src/resource/${process.env.CLIENT}`)
    })
  ),
}

process.env.CLIENT is your client name, it will correspond to your folder name such as build1, build2, after setup webpack alias, you don’t have to worry about the import path, and you can use only one code.

in your component, you can write this like so

import Layout from 'components/Layout';
import { ReactComponent as IconUser } from 'common/img/icon-user.svg';
import styles from '@/styles/header.css';
import { ReactComponent as Logo } from '@/img/logo.svg';
import HeaderImg from '@/img/header.jpg';

function App() {
  return (
    <Layout>
      <div className={styles.header}>
        <img src={HeaderImg>
        <Logo />
        <div>{user.name}</div>
      </div>
    </Layout>
  )
}

If your process.env.CLIENT is build1, '@/img/logo.svg' will reference to resource/build1/img/logo.svg, and vice versa

Development

you can setup different start cmd in your package.json to start different clients with different process.env.CLIENT

{
  "scripts": {
    "start:build1": "process.env.CLIENT=build1 npm run start",
    "start:build2": "process.env.CLIENT=build2 npm run start",
  }
}

Production build

Right after the build process finishes, write a command that copies the build folder content to folder of each client, in this way, the codes of different client builds will not cover each other.

{
  "scripts": {
    "build:build1": "process.env.CLIENT=build1 npm run build && mv build build1",
    "build:build2": "process.env.CLIENT=build2 npm run build && mv build build2",
  }
}

I'm not sure if this is what you want, if you have any problem please let me know, thanks!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.