7. React deployment on Nodejs and Express.js (1). Introduction and Production and development discrepancies or errors

1. Build the React app for production

First, use npm start and verify that your application runs ok. 

Then install serve (if you have not installed it before) and run the production code

#Install globally the "serve" javascript web server
sudo npm install -g serve  

#Run the application
serve -s buid

And now point to "http://localhost:3000" in your browser and test if it runs well

2. Development and Production irregularities or errors 

Maybe it cannot run as desired. This  "commented" code works in development but not in production

  //const isFirstRender = useRef(true); //Avoid executing code in the beginning 

  useEffect(() => {
    /* Works with development but DO'NT work with production build!!!!!
    if (isFirstRender.current) {             
      isFirstRender.current = false;         
      return; // return early if first render
    }                                        
    */
    if (code && code.length>10 ) {
      axiosFetchConf()
      alert ('url='+ window.location.href)
    }
  }, []);


Maybe some other trouble may arise...

3. Install the Express server in a folder  (i.e. myExpressServer) 

# create the folder
mkdir myExpressServer

#Install required files (express)
cd myExpressServer
npm init -y
npm install express --save

4. Create a subfolder (i.e. my-react-app)  and copy the generated production files 

# create the folder in the server folder (myExpressServer)
mkdir my-react-app

#copy the contents of the build directory into this folder
cd my-react-app
cp -RT <route_to_reat_app>/build build

Now you have this structure "myExpressServer/my-react-app/build

5. Create index.js file in the server folder (myExpressServer)

const express = require('express');
const app = express();

// serve up production assets
app.use(express.static('my-react-app/build'));

// let the react app to handle any unknown routes 
// serve up the index.html if express does'nt recognize the route
const path = require('path');
app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'my-react-app', 'build', 'index.html'));
});

// if not in production use the port 5000
const PORT = process.env.PORT || 5000;
console.log('server started on port:',PORT);
app.listen(PORT);


And now execute the application as

#Run the application
node index.js

And now point to "http://localhost:5000" in your browser and test if it runs well


Take into account that you can have CORS problems.

So if you have a server application with servlets, you must test CORS. For instance, this java class takes it into account:

6. A java program to add new CORS 

The server in port 5000 has been added.

package ximodante.rest.init;

import java.io.IOException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * Allow requests from localhost:3000 (typescript with nodej in VStudio)
 * @author ximo
 * @see https://stackoverflow.com/a/69335433 and https://howtodoinjava.com/java/servlets/java-cors-filter-example/
 *
 */
@WebFilter(asyncSupported = true, urlPatterns = { "/*" })
public class MyCORSFilter implements Filter{

	    
	    private static final String[] allowedOrigins = {
	            "http://localhost:3000", "http://localhost:5000", //"http://localhost:5501",
	            "http://127.0.0.1:3000", "http://127.0.0.1:5000" //, "http://127.0.0.1:5501"
	    };

	    @Override
	    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
	        HttpServletRequest request = (HttpServletRequest) servletRequest;

	        String requestOrigin = request.getHeader("Origin");
	        if(isAllowedOrigin(requestOrigin)) {
	            // Authorize the origin, all headers, and all methods
	            ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Origin", requestOrigin);
	            ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Headers", "*");
	            ((HttpServletResponse) servletResponse).addHeader("Access-Control-Allow-Methods",
	                    "GET, OPTIONS, HEAD, PUT, POST, DELETE");

	            HttpServletResponse resp = (HttpServletResponse) servletResponse;

	            // CORS handshake (pre-flight request)
	            if (request.getMethod().equals("OPTIONS")) {
	                resp.setStatus(HttpServletResponse.SC_ACCEPTED);
	                return;
	            }
	        }
	        // pass the request along the filter chain
	        filterChain.doFilter(request, servletResponse);
	    }

	    private boolean isAllowedOrigin(String origin){
	    	if (origin==null) return true;
	        for (String allowedOrigin : allowedOrigins) {
	            if(origin.equals(allowedOrigin)) return true;
	        }
	        return false;
	    }
	}







Comentarios

Entradas populares de este blog

14. Next.js Tutorial (1)

15. Next.js Tutorial (2). Fetching data. Async functions getStaticProps, getServerSideProps, getStaticPaths

17. Next.js Tutorial (4). API Routes