SoFunction
Updated on 2025-04-11

Create-react-app is modified to multi-enterprise compilation method

Requirements and starting points

We will have more small single-page applications, mainly simple pages and activities. These pages have no intersection with each other, but there will be some code that can be shared, such as resources, interfaces, components, etc.

We came up with two solutions:

  • react-router routing scheme;
  • Multi-enterprise compilation of the same project;

In response to our business needs, the react-router solution actually has two minor problems:

  • Modification of a single activity actually requires compiling the entire project;
  • If you do not perform compilation optimization, the packages of the entire project will be relatively large, but in fact there is no need. Of course, this can be solved by react-router loading;

After weighing the trade-offs, we chose the second solution - transforming the project into multi-enterprise compilation.

File structure design

After improvement, the structure of the entire project is roughly as follows:

- project
  - build
  - config
  - public
  - scripts
  - src
    - api
    - component
    - site
      - site1
        - 
        - 
        - ...
      - site2
        - 
        - 
        - ...
  - 

All folders under the site folder are an independent project. The general code and resources of the project are extracted into the outer folder, such as API, component, etc., and the folder will have their own and , which will be used as the html template and entry file for the project. Next, let's see how to modify the compilation process.

Modify entrances and exits

Compilation requires specifying the compilation entry and output location. In the code generated by create-react-app, there are only single entry and single exit, but in fact webpack supports multiple entry and multiple exits.

Entrance modification

There is a file in the config folder generated by the create-react-app command, which exports the more commonly used paths. Here, I traverse the folders inside the src/site folder and generate them as objects. The specific code is as follows:

// all site paths
function allSitePath(source) {
 const { lstatSync, readdirSync } = fs
 const { join } = path
 const result = {}
 const isDirectory = source => lstatSync(source).isDirectory()
 readdirSync(source).map(name => {
  let path = join(resolveApp(source), name)
  if (isDirectory(path)) result[name] = path
 })
 return result
}

 = {
 ...
 allSites: allSitePath('src/site'),
}

The entry property found in / is modified to:

// Dynamic generation entryconst entry = {}
().forEach(item => {
 entry[item] = [
  ('./polyfills'),
  ('react-dev-utils/webpackHotDevClient'),
  ('react-error-overlay'),
  [item]
 ]
})

 = {
 ...
 entry: entry,
 ...
}

Export modification

The modification of the export is divided into two parts, part of which is output, adding name to make static resources differentiate between different projects:

 = {
 ...
 output: {
  path: ,
  pathinfo: true,
  filename: 'static/js/[name].',
  chunkFilename: 'static/js/[name].',
  publicPath: publicPath,
  devtoolModuleFilenameTemplate: info =>
   ().replace(/\\/g, '/'),
 },
 ...
} 

The other part is the modification of plugin. In webpack, the output of each HTML file is actually an HtmlWebpackPlugin. We need to add multiple HtmlWebpackPlugin to generate multiple HTML:

// Dynamically generate pluginsconst plugins = []
().forEach(item => {
 (new HtmlWebpackPlugin({
  inject: true,
  chunks: [item],
  template: `${[item]}/`,
  filename: `${item}/`,
 }))
})

 = {
 ...
 plugins: [
  ...
 ].concat(plugins),  
 ...
}

Modify webpack Dev Server configuration

After the above configuration is completed, the theory can package the multi-entry version; but after starting with npm start, it is found that no matter whether it is input/or/, it seems that the content is the same as the original/display. Even the input of / which obviously does not exist is displayed as /.

Here, we also need to modify /config/ to make some additional configurations.

const rewrites = []
().forEach(item => {
 ({
  from: new RegExp(`^\\/${item}/`, 'i'),
  to: `/${item}/`,
 })
})

...

 = function(proxy, allowedHost) {
 return {
  ...
  historyApiFallback: {
   // Paths with dots should still use the history fallback.
   // See /facebookincubator/create-react-app/issues/387.
   disableDotRule: true,
   // Indicate which paths are mapped to which html   rewrites: rewrites,
  },
  ...
 };
};

OK, here, the entire transformation is completed.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.