5

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.

jivenox793
  • 169
  • 2
  • 7

2 Answers2

6

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 html-webpack-inline-source-plugin@1.0.0-beta.2
  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.

rdworth
  • 1,052
  • 7
  • 9
1

I've followed this article and it worked for me like a charm.

It uses Gulp to bundle the whole app in one HTML file.

  1. Install: npm install --save-dev gulp gulp-inline-source gulp-replace
  2. Create .env file in the root folder.
INLINE_RUNTIME_CHUNK=false
GENERATE_SOURCEMAP=false
SKIP_PREFLIGHT_CHECK=true
  1. Create a gulpfile.js file in the root folder.
const gulp = require('gulp')
const inlinesource = require('gulp-inline-source')
const replace = require('gulp-replace')

gulp.task('default', () => {
    return gulp.src('./build/*.html')
        .pipe(replace('.js"></script>', '.js" inline></script>'))
        .pipe(replace('rel="stylesheet">', 'rel="stylesheet" inline>'))
        .pipe(inlinesource({
            compress: false,
        }))
        .pipe(gulp.dest('./build'))
});
  1. Run npx gulp (you may include it in your package.json build script)
pierre-vr
  • 19
  • 5