Search code examples
reactjswebpackcreate-react-appcraco

How can I selectively render code in a Create React App SPA?


In my React app (built with Create React App cli, and not ejected) I have it set up so if there is no REACT_APP_API_URL defined then it uses mocked data.

I do this by suppling a fakeFetch function to redux-api-middleware ala

import { apiMiddleware as aMl, createMiddleware } from 'redux-api-middleware'
import fakeFetch from 'fixtures/utils/fakeFetch'

const apiMiddleware = apiBase ? aMl : createMiddleware({ fetch: fakeFetch })

// etc... configure the `redux` store with the middleware

That's fine when developing, but I'd like for that code to be completely detached from the build when actually building for deployment.

Is there any way I can do something along the lines of

<% if process.env.REACT_APP_API_URL %>
import { apiMiddleware } from 'redux-api-middleware'
<% else %>
import { createMiddleware } from 'redux-api-middleware'
import fakeFetch from 'fixtures/utils/fakeFetch'

const apiMiddleware = createMiddleware({ fetch: fakeFetch })
<% endif %>

// etc... configure the `redux` store with the middleware

to prevent webpack from including up all my fixtures / fake data in the production build, while giving me a very simple way to switch between mock vs live data?

I do not want to have to eject the app, but am open to using a webpack plugin that's injected using Create React App Configuration Overrides.


Solution

  • I think webpack code-splitting with dynamic imports could be your best bet. This way, your mock data is bundled but never sent to the client (which I think is the main goal here).

    import { apiMiddleware, createMiddleware } from 'redux-api-middleware'
    
    const getMiddleware = async () => {
       if (process.env.REACT_APP_API_URL) {
          return apiMiddleware;
       } else {
          // loads bundle over network
          const { default: fakeFetch } = await import('fixtures/utils/fakeFetch');
          return createMiddleware({ fetch: fakeFetch });
       }
    }
    

    I know this does not answer the question directly but on a side note, I think the cleanest way would be to utilise a mock sever such as mock-server.com. In development, you would just use the mock server url in process.env.REACT_APP_API_URL. This way, the test data lives in a completely different environment and provide a clear separation of concerns. You could probably also just create a simple local express app that just returns hardcoded JSON if you don't want to use third-party tools.