Search code examples
reactjswebpackcreate-react-approllup

How can I create one bundle file from react-create-app


I am trying to build react-create-app into one file (including JS, CSS, PNG, etc...).

It is possible and how?

Should I try to use rollup or it is possible using webpack?

I tested https://www.npmjs.com/package/html-webpack-inline-source-plugin but looks like outdated and not working.


Solution

  • Yes, it is possible to do this with CRA (create-react-app) and webpack. I'll detail 3 options below that I've gotten to work.

    Setup - Install react-app-rewired

    Each option below makes use of react-app-rewired to be able to customize webpack config within create-react-app without ejecting. As a first step, follow the install instructions on https://github.com/timarney/react-app-rewired#how-to-rewire-your-create-react-app-project

    If you already have ejected or you want to eject, you can still use any of the options below, you'll just modify the plugins directly in config/webpack.config.js instead of programmatically through react-app-rewired's config-overrides.js.

    Note: two of the options below have require('html-webpack-plugin'). Don't yarn add this, to ensure you get the version installed by create-react-app.

    Option 1 - Use html-webpack-inline-source-plugin

    For this one, I had to manually specify the latest beta version. When I ran npm install --save html-webpack-inline-source-plugin without a version specified, I got version 0.0.10 and it failed.

    1. Install react-app-rewired (see Setup section above)
    2. yarn add [email protected]
    3. Edit config-overrides.js:
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
    
    module.exports = function override(config, env) {
      if (env === 'production') {
        config.plugins
          .find(plugin => Object.getPrototypeOf(plugin).constructor.name === 'HtmlWebpackPlugin')
          .options.inlineSource = '.(js|css)$'
        config.plugins.push(new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin))
      }
      return config
    }
    

    Note: this plugin is not actively maintained (see the note at top of https://github.com/dustinjackson/html-webpack-inline-source-plugin#readme) but it works for me.

    Option 2 - Use script-ext-webpack-plugin and style-ext-html-webpack-plugin

    1. Install react-app-rewired (see Setup section above)
    2. yarn add script-ext-html-webpack-plugin style-ext-html-webpack-plugin
    3. Edit config-overrides.js:
    const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
    const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin')
    
    module.exports = function override(config, env) {
      if (env === 'production') {
        config.plugins.push(new ScriptExtHtmlWebpackPlugin({
          inline: /.+[.]js/
        }))
        config.plugins.push(new StyleExtHtmlWebpackPlugin())
      }
      return config
    }
    

    Note: this option will fail (StyleExtHtmlWebpackPluginError: StyleExtHtmlWebpackPlugin: could not find ExtractTextWebpackPlugin's generated .css file) if you don't have any .css files. If so, just comment-out or delete these two lines

    //const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin')
    {...}
        //config.plugins.push(new StyleExtHtmlWebpackPlugin())
    

    Option 3 - Use react-dev-utils/InlineChunkHtmlPlugin

    1. Install react-app-rewired (see Setup section above)
    2. (No yarn add needed here, as react-dev-utils is part of create-react-app)
    3. Edit config-overrides.js:
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
    
    module.exports = function override(config, env) {
      if (env === 'production') {
        config.plugins.push(new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/.+[.]js/]))
      }
      return config
    }
    

    Note: this option will only inline js files, not css files.