Note: This article will cover one use case of Webpack which involves having a single webapp consisting of a React.js front-end, communicating with an Express.js REST API running all data transactions.This article will NOT cover more complex cases such as running multiple Node.js servers through the same HTTP port (i.e. using proxies), the usage of sub-domains, or the usage of third-party services hosted on a different domain.With this in mind, let’s jump into it…

First of all, if we put it simply, all web development projects will have at least two stages: DEV and PROD. (Again, I’m oversimplifying. I know I’m skipping over industry standards that apply TEST and STAGING stages, but for simplicity’s sake I’m omitting these concepts)

DEV can happen either at your computer or at a cloud server provisioned with everything needed for you to write and test code on the fly. DEV environments hold no real data and are meant to be safe playgrounds for web app development.

PROD, a.k.a production, is the culmination of all DEV work, as in, a server in the cloud running the web app which end-users will use in their day-to-day. Ideally (emphasis in ideally) things should have already been thoroughly tested before reaching this stage, so that once your code arrives at PROD, nothing can go wrong. PROD holds all user data.

Now, with that in mind, let me bluntly assert that:

Cross-Origin Resource Sharing (CORS) problems in Webpack/React.js projects will only arise during the DEV stage of development.

The reasons why are quite easily explained through the following example:

Let’s say you’re building a web app consisting of a React.js front-end and an API which in the end (PROD) will reside in https://yoursite.co (read more on how to implement https certificates for free here).

During development (DEV) your front-end might be served at:

https://localhost:8080

and your API at:

https://localhost:8081/api/v1/

Here’s where your browser will begin to freak out when you try to access your web app, which, in turn, tries to access the API, because of that port difference. More on that in just a moment.

To finish up with the example, once your app reaches PROD, on the other hand, the routes will look like this:

Since Hot Module Reloading is one of the strongest selling points of Webpack as a development tool, this means that your front-end is not served directly from the source files you have stored in your hard-drive, but generated in real-time and read from memory.

This limits the ability to serve your API from the same port as the front-end, so much so that in order to emulate the ability for your front-end to be able to speak to your API on the same port you would have to use a proxy to route HTTP requests accordingly.

Production packaging

Once a development cycle has ended and your web app is ready to be “pushed to PROD“, when using Webpack you will simply run in your terminal:

$ webpack -p

this will generate a single bundle.js file holding all of the code necessary to run your front-end.

For all intents and purposes, the most sane thing to do in order to serve your web app is to configure an HTTP server to serve the generated index.html and bundle.js files, as well as any other static asset (images, etc).

And the same server can be configured to serve your API through the appropriate routes.

It truly is as simple as that.

CORS Error Scenarios and Solutions

I will be showing you two scenarios which you may encounter out in the wild:

One in which the API url is injected into the app so that we can develop knowing the app will fetch the content from the correct port. The other one in which we simply want to call the API as a relative path to the current domain in both DEV and PROD.

To make things easier to test for you, I have created an example app which I uploaded to github. You can find it here.

Be sure to clone it and follow the instructions from the README to install its dependencies.

Before we continue, I’ll simply state that the example app is a React.js hello world which has a HelloWorld React component that loads the words Hello and World from a back-end API via the fetch command (AJAX).

Solution 1: When injecting the API’s url

If you downloaded the example repo, checkout the branch broken as follows:

As you can see from the code, the API_URL environment variable is used to define the api_url const, which is, well, the url where the API is at. If API_URL is not present we simply leave the api_url string empty so that we fetch from the site’s root. This is so that in DEV we can inject the url with the different port, and then in PROD we can assume that both the front-end and API will live under the same port. To inject the aforementioned API_URL environment variable, I simply added it into the configurations loaded into server.js from the webpack.config.js file like so:

You can see clearly what I was stating before: the CORS error only happens in DEV not in PROD Here’s where the first solution comes in. Considering that what we want is for the API to allow for its contents to be loaded from a different port, we need to fix things on the API side of things, not on Webpack. That’s where the cors npm package comes in to save the day. First we install the package as so:

Great!

But to be fair, injecting the API’s url into the app when in DEV mode is a bit of a hack and adds unnecessary complexity. I have included this solution because in the real world people might need to monkey patch things as just described, but ideally I would urge you to consider the next solution.

Solution 2: Using a proxy for webpack-dev-server

Let’s take the previous example and refactor things a little. I’m going to remove that ugly url injection and the cors package from the server code:

Now if you run the app in DEV mode you should see:Now that’s not a CORS error, but it’s an error nonetheless.It’s not able to get the strings because now it’s trying to get them from the front-end port (8080) rather than the API port (8081).But with a quick fix in the webpackDevServer definition:

Bingo!:

This is the ideal solution. It’s really simple and can be managed from a single spot in the code that spins up the DEV server, with no way to muddy up production with API_URL related errors.To test this solution simply checkout the proxy branch:

Jean Maurice Lescure is a Costa Rican software developer and an entrepreneur, known for his pioneering works in connecting Ruby on Rails with Hadoop. He's an avid conference speaker and technology writer focused on expanding knowledge of his fellow techno-geeks on subjects related but not limited to cloud-based learning networks, scalable asynchronous streaming protocols, GPU vs CPU enhancements, and anything related to Ruby and NodeJS.

Comments (3)

3 Comments

Arthur White on April 21, 2017 at 12:33 am

“Once a development cycle has ended…” webpack – p “…It truly is as simple as that”

Can you go into a little detail? Do you need to use Nginx or Apache to configure this? Is there a tutorial on deploying an app that has an api and a frontent? Thanks! Great tutorial. Too bad it is not high enough on Google. Will share.