'How to compress build files in create react app without ejecting?

I'm trying to figure out how to best optimize my build file and ran across the notion of compressing text files like js and css. From what I've come across every article either assumes you have access to the webpack config file or you've ejected from CRA. I don't want to.

So I added a post build script to my package.json file:

"scripts": {
    "build": "npm run build --prefix client",
    "prod-compress": "gzip client/build/static/js/*.js && gzip client/build/static/css/*.css",

which results in the /client/build/static/js and /client/build/static/css folders looking like this:

enter image description here enter image description here

I then went into my app.js file and added the following code:

app.get('*.js', function(req, res, next) {
    req.url = req.url + '.gz';
    res.set('Content-Encoding', 'gzip');
    res.set('Content-Type', 'text/javascript');
    next();
});

app.get('*.css', function(req, res, next) {
    req.url = req.url + '.gz';
    res.set('Content-Encoding', 'gzip');
    res.set('Content-Type', 'text/css');
    next();
});

If I understand what's happening correctly, the f/e /client/public/index.html file will still reference a regular .js file. However, when the file is requested from the server, it will respond with the .js.gz file.

However, when I compress the files the entire site goes blank, like it can't find anything to serve up. enter image description here



Solution 1:[1]

If you don't mind adding a new dependency, I would recommend using express-static-gzip which will automatically serve your compressed files:

const express = require("express");
const expressStaticGzip = require("express-static-gzip");
const app = express();

const buildPath = path.join(__dirname, '..', 'build', 'static');
app.use("/", expressStaticGzip(buildPath);

You also have the choice to add other types of compression like brotli by passing an options object:

const buildPath = path.join(__dirname, '..', 'build', 'static');
  app.use(
    '/',
    expressStaticGzip(buildPath, {
      enableBrotli: true,
      orderPreference: ['br', 'gz']
    })
  );

Brotli gives you even more optimized files than gzip but it's not supported by all browsers. Thankfully, express-static-gzip automatically picks the correct file to send based on the Accept-Encoding/Content-Encoding header the user's browser sends to it.

If you want to use brotli, I recommend taking a look at compress-create-react-app. It's specifically made for React apps but should work with any files.

Disclaimer: I'm the author of compress-create-react-app

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jnsjknn