17

I am setting up my React app project using create-react-app.

I was wondering if there is a way to turn-off the chunking mechanism that is built-in into the react scripts. The thing is that I need to fix the name of the bundle created on the build.

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
Darko
  • 525
  • 1
  • 4
  • 14

6 Answers6

15

It can be done by extending your CRA with react-app-rewired package which allows you to modify webpack config.

Changes needed to remove hash in build file names.

  1. Install react-app-rewired

npm install react-app-rewired --save-dev

  1. create config-overrides.js file in your root folder (where package.json is)

  2. place the following code to the config-overrides.js file. It keeps all CRA settings, only remove the hash part from filenames.

    module.exports = function override(config, env) {
        config.output = {
            ...config.output, // copy all settings
            filename: "static/js/[name].js",
            chunkFilename: "static/js/[name].chunk.js",
        };
        return config;
    };
  1. use the new config. In the package.json file in scripts section replace "build": "react-scripts build", with "build": "react-app-rewired build",

Unless you are going to change more configuration, it is enough to only use react-app-rewired in build. Otherwise replace react-scripts with react-app-rewired in others scripts except eject

fandasson
  • 2,158
  • 21
  • 20
7

I've found that you can disable chunking by setting splitChunks webpack configuration. For more details check https://github.com/facebook/create-react-app/issues/5306#issuecomment-431431877

However, this does not remove the contenthash part from the bundle name and you will still have that random string in the name.

To remove this, go to your webpack.config and edit the bundle name

'static/js/[name].[contenthash:8].js' => 'static/js/[name].js'

Darko
  • 525
  • 1
  • 4
  • 14
  • 1
    Thanks, you probably saved us the ability to use the embedded React app in our project. Worked like a charm for issues related to embedding React app inside iframe. – Paweł Hajduk May 17 '20 at 18:28
7

This is extended and improved version of Darko's answer. I created it mostly to save time for others who is not fully satisfied with solution mentioned in this comment and didn't have a patience to dig to this comment that solved the issue in much nicer way.

Main idea of this "hacky" approach is to re-write standard react-scripts's webpack configuration on the fly and inject it back to original scripts.

For that you would need to install rewire package from npmjs.org, like so:

npm install rewire --save-dev

Then you create separate build script that will will "wrap" original react build script and make sure that it will relieve corrected webpack configuration. Conventional way is to save this file inside ./scripts folder. So let's call it ./scripts/build.js. It's content:

const rewire = require('rewire');
const path = require('path');

// Pointing to file which we want to re-wire — this is original build script
const defaults = rewire('react-scripts/scripts/build.js');

// Getting configuration from original build script
let config = defaults.__get__('config');

// If we want to move build result into a different folder, we can do that!
// Please note: that should be an absolute path!
config.output.path = path.join(path.dirname(__dirname), 'custom/target/folder');

// If we want to rename resulting bundle file to not have hashes, we can do that!
config.output.filename = 'custom-bundle-name.js';

// And the last thing: disabling splitting
config.optimization.splitChunks = {
    cacheGroups: {
        default: false,
    },
};
config.optimization.runtimeChunk = false;

Then, we should use this build script instead of standard one in our packages.json, something like so:

...
  "scripts": {
    "start": "react-scripts start",
    "build": "node ./scripts/build.js",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
...
shytikov
  • 9,155
  • 8
  • 56
  • 103
7

As others have pointed out you can try this with react-app-rewired instead of ejecting. Here is a version that also handles css and media files:

After installing npm install react-app-rewired --save-dev I created a config-overrides.js with the following content:

module.exports = function override(config, env) {
    if (env !== "production") {
        return config;
    }

    // Get rid of hash for js files
    config.output.filename = "static/js/[name].js"
    config.output.chunkFilename = "static/js/[name].chunk.js"

    // Get rid of hash for css files
    const miniCssExtractPlugin = config.plugins.find(element => element.constructor.name === "MiniCssExtractPlugin");
    miniCssExtractPlugin.options.filename = "static/css/[name].css"
    miniCssExtractPlugin.options.chunkFilename = "static/css/[name].css"

    // Get rid of hash for media files
    config.module.rules[1].oneOf.forEach(oneOf => {
        if (!oneOf.options ||  oneOf.options.name !== "static/media/[name].[hash:8].[ext]") {
            return;
        }
        oneOf.options.name = "static/media/[name].[ext]"
    });

    return config;
};
Giraphi
  • 1,383
  • 1
  • 11
  • 26
4

There is a hack without needing eject:

  1. yarn add --dev rewire

  2. create file in root and name it build-non-split.js

  3. fill inside it by below codes:

    const rewire = require('rewire');
    const defaults = rewire('react-scripts/scripts/build.js');
    let config = defaults.__get__('config');
    
    config.optimization.splitChunks = {
        cacheGroups: {
            default: false,
        },
    };
    
    config.optimization.runtimeChunk = false;
    
  4. change the build script inside your package.json to:

    "build": "node ./scripts/build-non-split.js",
    
  5. yarn build

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
  • Possible source of this solution: https://github.com/facebook/create-react-app/issues/5306#issuecomment-433425838 – TomTasche Dec 23 '21 at 12:41
  • how do you make it work for css files as well ? – Michel Hua Feb 18 '22 at 05:59
  • @MichelHua, I used css-in-js, if you want use other CSS methods, thats ok, you should import CSS as css-modules, like: `import styles from './styles.css';` and then in using you must use it like: ``. – AmerllicA Feb 18 '22 at 08:00
3

I don't know how to turn off chunking but what you could do try achieve you goal

Update to latest react and react-dom , run 'yarn react@next react-dom@next' (or npm command to do same)

You should now have the latest react versions - so you can code split using React.lazy/React.Suspense, use hooks and so on.

So now you can name your chunks using (component or dependency examples below)

 const MyComp = lazy(() =>   import(/* webpackChunkName: 'MyChunkNmame'
*/ './MyComp'), );

const myLib= await import(/* webpackChunkName: "myLib" */ 'myLib');

If you have an issue with errors when using the import syntax you need to use the babel-plugin-syntax-dynamic-import plugin. Put the "babel" field in your package json.

Now you can name your chunks and implement the latest way to code split - hope that helps. Here is a link to React.lazy React.Suspense - https://reactjs.org/blog/2018/10/23/react-v-16-6.html

dorriz
  • 1,927
  • 3
  • 12
  • 19
  • It is not what I am looking for but, thank you. Naming the chunks can definitely come handy in some cases. I've actually found a couple of GitHub discussions with similar questions. I'll write an answer soon. – Darko Apr 30 '19 at 09:38