2.2.2 • Published 2 years ago

react-app-rewire-multiple-entry-extended v2.2.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

React App Rewire Multiple Entry - Extendend Version

React App Rewire Multiple Entry Extendend is a fork of React App Rewire Multiple Entry that lets you configure multiple entries in Create React App without ejecting.

This fork allows you to omit the hash in the compiled filenames. Use the original unless you really need this functionality. This module has only been published as the PR with the changes has not been merged to React App Rewire Multiple Entry yet.

Usage

  1. Add React App Rewire Multiple Entry Extendend to your Rewired React app:

    npm install --save-dev react-app-rewired react-app-rewire-multiple-entry-extendend

    or

    yarn add -D react-app-rewired react-app-rewire-multiple-entry-extendend

    For create-react-app 1.x or react-scripts-ts with Webpack 3

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

    or

    yarn add -D react-app-rewired@1.6.2
  2. Modify package.json

      "scripts": {
    -   "start": "react-scripts start",
    +   "start": "react-app-rewired start",
    -   "build": "react-scripts build",
    +   "build": "react-app-rewired build",
    -   "test": "react-scripts test",
    +   "test": "react-app-rewired test",
        "eject": "react-scripts eject"
    }
  3. Add React App Rewire Multiple Entry to config-overrides.js in your React app directory:

    Basic Usage

    // config-overrides.js
    
    const multipleEntry = require('react-app-rewire-multiple-entry-extended')([
      {
        entry: 'src/entry/landing.js',
        template: 'public/landing.html',
        outPath: '/landing.html'
      }
    ]);
    
    module.exports = {
      webpack: function(config, env) {
        multipleEntry.addMultiEntry(config);
        return config;
      }
    };

    Work with customize-cra

    // config-overrides.js
    
    const multipleEntry = require('react-app-rewire-multiple-entry-extended')([
      {
        entry: 'src/entry/landing.js',
        template: 'public/landing.html',
        outPath: '/landing.html'
      }
    ]);
    
    const {
      // addBundleVisualizer,
      override,
      overrideDevServer
    } = require('customize-cra');
    
    module.exports = {
      webpack: override(
        multipleEntry.addMultiEntry
        // addBundleVisualizer()
      )
    };

Extended example

When running the React build script with the example settings above the filenames will have two hashes appended to it, one appended by the React webpack and one appended by react-app-rewire-multiple-entry. To remove all hashes from the filenames and store the hashes in a JSON-file one can use the following:

// webpack-metadata-plugin - will write hashes to meta.json
const fs = require("fs");

class MetadataPlugin {
  constructor(options) {
    this.options = { filename: "meta.json", ...options };
  }

  apply(compiler) {
    compiler.hooks.done.tap(this.constructor.name, (stats) => {
      const metaInfo = {
        hash: stats.hash,
      };
      stats.compilation.chunks.forEach((chunk) => {
        metaInfo[chunk.name] = chunk.hash;
      });
      const json = JSON.stringify(metaInfo);
      return new Promise((resolve, reject) => {
        fs.writeFile(this.options.filename, json, "utf8", (error) => {
          if (error) {
            reject(error);
            return;
          }
          resolve();
        });
      });
    });
  }
}

module.exports = MetadataPlugin;
// config-overrides.js
const path = require("path");
const MetadataPlugin = require("./webpack-metadata-plugin");

const multipleEntry = require("react-app-rewire-multiple-entry-extended")([
  {
    name: "discovery",
    entry: path.resolve(__dirname, "./src/entries/entry-discovery.tsx"),
    outPath: "discovery.html",
    template: path.resolve(__dirname, "./src/entries/templates/discovery.html"),
    omitHash: true,
  },
  {
    name: "global-search",
    entry: path.resolve(__dirname, "./src/entries/entry-global-search.tsx"),
    outPath: "global-search.html",
    template: path.resolve(__dirname, "./src/entries/templates/global-search.html"),
    omitHash: true,
  },
  {
    name: "tools",
    entry: path.resolve(__dirname, "./src/entries/entry-tools.tsx"),
    outPath: "tools.html",
    template: path.resolve(__dirname, "./src/entries/templates/tools.html"),
    omitHash: true,
  },
  {
    name: "articles",
    entry: path.resolve(__dirname, "./src/entries/entry-articles.tsx"),
    outPath: "articles.html",
    template: path.resolve(__dirname, "./src/entries/templates/articles.html"),
    omitHash: true,
  },
]);

module.exports = function (config, env) {

  // Filenames
  config.output.filename = "static/js/[name].js";
  config.output.chunkFilename = "static/js/[name].js";

  // Group common vendor files in separate chunk named common
  config.optimization.splitChunks = {
    cacheGroups: {
      default: false,
      commons: {
        test: /node_modules/,
        chunks: "initial",
        name: "commons",
        enforce: true,
      },
    },
  };
  config.optimization.runtimeChunk = false;

  // Add entries
  multipleEntry.addMultiEntry(config);

  // Add metadata plugin to store hashes
  if (!config.plugins) {
    config.plugins = [];
  }
  config.plugins.push(new MetadataPlugin({ filename: "meta.json" }));

  config.plugins.forEach((item) => {
    // CSS filenames
    if (item.constructor.name === "MiniCssExtractPlugin") {
      item.options.filename = "static/css/[name].css";
      item.options.chunkFilename = "static/css/[name].css";
    }
  });

  return config;
};

Results

Files generated:

  233.96 KB  build/static/js/commons.js
  10.93 KB   build/static/js/main.js
  8.92 KB    build/static/js/entry-discovery.js
  5.36 KB    build/static/js/entry-global-search.js
  5.29 KB    build/static/js/entry-tools.js
  5.08 KB    build/static/js/entry-articles.js
  4.11 KB    build/static/css/commons.css
  722 B      build/static/css/main.css
  642 B      build/static/css/entry-discovery.css
  642 B      build/static/css/entry-global-search.css
  332 B      build/static/css/entry-articles.css
  330 B      build/static/css/entry-tools.css

Content of meta.json:

{
    "hash":"2fda073f19bb5635aedf",
    "commons":"b5e90583e0d99b8e7d9576dee51db10d",
    "entry-articles":"a267eadd80c030b7861f10139cebae21",
    "entry-discovery":"0f8b3ae0f35916868424224d023524ba",
    "entry-global-search":"fa42f87c40e6f17b64975fd8bdf14fe0",
    "entry-tools":"b1b720f91dd3bc8f3cd1e2e009684e28",
    "main":"1cff87efd698e63902b75974f4695346"
}

If one needs to have different hashes for the CSS and JS files with the same entry name, for example entry-discovery.js and entry-discovery.css, then the metadata plugin has to be changed.

API

Options

You can pass a array of entry configuration options to react-app-rewire-multiple-entry, the entry in the array has attributes below:

  • entry Required Webpack entry JS file. Throw error when empty.
  • template Optional HTML template used in plugin HtmlWebpackPlugin. Default value: public/index.html.
  • outPath: Optional The file wirte the HTML to. You can specify a subdirectory. If empty, it will be calculated by path.relative(process.cwd(), template)

Method

  • addMultiEntry Inject settings for multiple entry in webpack config

That’s it! Now you can control mulitple entries and omitting the hashes, enjoy coding!