Skip to content

Instantly share code, notes, and snippets.

@joeldenning
Last active March 4, 2024 09:05
Show Gist options
  • Save joeldenning/79f2592086ad132fae8ee5aae054c0b6 to your computer and use it in GitHub Desktop.
Save joeldenning/79f2592086ad132fae8ee5aae054c0b6 to your computer and use it in GitHub Desktop.
create-react-app + react-app-rewired + single-spa
module.exports = {
webpack(config, env) {
config.entry = './src/single-spa-entry.js';
config.output = {
...config.output,
filename: 'project-name.js',
libraryTarget: 'system',
}
config.plugins = config.plugins.filter(plugin => plugin.constructor.name !== 'HtmlWebpackPlugin' && plugin.constructor.name !== 'MiniCssExtractPlugin')
delete config.optimization
return config;
},
devServer(configFunction) {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost);
config.disableHostCheck = true
config.headers = config.headers || {}
config.headers['Access-Control-Allow-Origin'] = '*'
return config
}
}
}

This Gist works for CRA 3. For CRA 4, you can try community maintained craco plugin for converting to a single-spa application at https://github.com/hasanayan/craco-plugin-single-spa-application (thanks @hasanayan):

  1. Install react-app-rewired, as explained in https://github.com/timarney/react-app-rewired.
  2. Create a file in src called single-spa-entry.js (or tsx for typescript)
  3. Modify config-overrides.js, as shown in the config-overrides.js file provided in this gist.
  4. (Optional) remove src/main.js, since single-spa-entry is the new entry
  5. (Optional) remove public/index.html, since single-spa applications share a single html file, instead of one html file per project.
@joeldenning
Copy link
Author

How to fix the error that System is not defined?

Are you intending to use SystemJS? If so, here are the webpack modifications required for SystemJS: https://github.com/systemjs/systemjs#compatibility-with-webpack. If not, change the webpack output.libraryTarget to not be System.

@albertocorrales
Copy link

Hi,

first of all, thanks for this gist, it has been really helpful.

I'm trying to create a test app, to load one CRA micro-frontend with Single-Spa. I managed to load the application, but I cannot see the svg image when I load the application. Am I missing anything? this is my full example https://github.com/albertocorrales/single-spa-cra-example

@joeldenning
Copy link
Author

For CRA 4 users, here's a community maintained craco plugin for converting to a single-spa application (thanks @hasanayan):

https://github.com/hasanayan/craco-plugin-single-spa-application

@gabrielcerutti
Copy link

gabrielcerutti commented Aug 27, 2021

Hi all, I'm working on a CRA micro-frontend template, a Container App (aka Main SPA) and a demo app including two micro-frontends with nested routes in case you want to take a look.
Any comment is welcome! Thanks!

@JeffWeim
Copy link

JeffWeim commented Apr 7, 2022

@joeldenning @hasanayan Does the https://github.com/hasanayan/craco-plugin-single-spa-application plugin allow you to run a CRA application as a standalone single-spa application?

@fupengl
Copy link

fupengl commented May 25, 2022

If you use react-app-rewired, you can use react-app-rewired-single-spa, which can be quickly integrated into the react-scripts project, supports 4.x 5.x, and supports hot updates

// use `customize-cra`
const { rewiredSingleSpa, rewiredSingleSpaDevServer } = require("react-app-rewired-single-spa");
const { override, overrideDevServer } = require("customize-cra");

module.exports = {
  webpack: override(
    rewiredSingleSpa({
      orgName: "you",
      projectName: "test",
      reactPackagesAsExternal: true,
      peerDepsAsExternal: true,
      orgPackagesAsExternal: true,
    })
  ),
  devServer: overrideDevServer(rewiredSingleSpaDevServer()),
};

@ThaddeusJiang
Copy link

@sameroso
Copy link

sameroso commented Aug 18, 2022

I could config my cra with rewired with this configuration

the publicPath property loaded my assets correctly in the root frontend

const ASSET_PATH = process.env.ASSET_PATH || 'http://localhost:3000/';

module.exports = {
  webpack(config, env) {
    config.output = {
      ...config.output,
      filename: "mfe-1.js",
      libraryTarget: "system",
      publicPath:ASSET_PATH
    };
    delete config.optimization;
    return config;
  },
  devServer(configFunction) {
    return function (proxy, allowedHost) {
      const config = configFunction(proxy, allowedHost);
      config.disableHostCheck = true;
      config.headers = config.headers || {};
      config.headers["Access-Control-Allow-Origin"] = "*";
      return config;
    };
  },
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment