Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more entry points #1084

Open
riceyeh opened this issue Nov 22, 2016 · 120 comments
Open

Add more entry points #1084

riceyeh opened this issue Nov 22, 2016 · 120 comments

Comments

@riceyeh
Copy link

riceyeh commented Nov 22, 2016

In addition to src/index.js, I have other entry points in my app. How do I add them?

@riceyeh riceyeh changed the title Add more entry points for my app Add more entry points Nov 22, 2016
@tbillington
Copy link

tbillington commented Nov 22, 2016

You could render to multiple html elements in index.js, is that what you mean?

reactdom.render(<App1/>, div1)
reactdom.render(<App2/>, div2)
reactdom.render(<App3/>, div3)

@thien-do
Copy link
Contributor

@riceyeh I think you asked this already? is there anything here different from #1079

@gaearon
Copy link
Contributor

gaearon commented Nov 22, 2016

Can you explain your use case in more detail? While you asked this earlier, I wonder if I misunderstood your use case.

@jkarttunen
Copy link

For example, when preparing multiple apps I might want to do index.html for web and touch-kiosk.html for other devices. Basically using components and composition to do multiple apps. For this I need not just few html files but multiple entry points for webpack.

@kulakowka
Copy link

kulakowka commented Dec 16, 2016

I would like to be able to create multiple bundles.

For example:

admin.bundle.js       # for admin section in my site
client.bundle.js      # for client section 

Now I am forced to create two applications:

create-react-app admin
create-react-app client

This approach seem to be excessive. It would be great if it was possible to separate the bundles within a single application.

@gaearon
Copy link
Contributor

gaearon commented Dec 16, 2016

Thanks for sharing the use cases. We might support this eventually but for now I recommend either separate apps or ejecting and manually configuring Webpack.

@tbillington
Copy link

tbillington commented Dec 17, 2016

You could do something funky with shell scripting. Not sure how practical this is but it will solve your problem (from how I interpret it).

Have two entry point js files, lets go with user.js and admin.js.

Have two build commands in package.json; build-user, build-admin.

When you go to run build-user, before running react-scripts build, have some shell code that copies user.js to index.js in your source code. Same for build-admin, just copy it's entry point to index.js before running the actual build command. This way if you're working on the same entry point consistently, you can still use build.

package.json

"build": "react-scripts build",
"build-user": "cp src/user.js src/index.js && react-scripts build",
"build-admin": "cp src/admin.js src/index.js && react-scripts build"

@jkarttunen
Copy link

Maybe we could pass entry point to webpack instead? Then add instructions of shell scripting it.

@carruthe
Copy link

I ran in to a similar issue today, and there appears to be an easier and more elegant workaround to this, similar to what @tbillington had mentioned. Keep in mind, I am pretty new to React/Webpack/Babel/etc, so forgive me any nube mistakes.

You can simulate having multiple HTML files by using URL parameters on the Index.html file. In index.js, you simply parse out the URL param and serve the appropriate React Component into the root div based on that parameter. In this case, the default would be App, but if you load it with

http://www.myhost.com/index.html?startPage=SecondApp

... it will serve up the SecondApp React component.

The App.js and index.html are the boilerplate created by create-react-app.

Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import SecondApp from './SecondApp';
import './index.css';


// Copied from http:jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html
function getUrlVars() {
  var vars = [], hash;
  var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
  for (var i = 0; i < hashes.length; i++) {
    hash = hashes[i].split('=');
    vars.push(hash[0]);
    vars[hash[0]] = hash[1];
  }
  return vars;
}

var urlParams = getUrlVars();

switch (urlParams["startPage"]) {
  case "SecondApp":
    ReactDOM.render(<SecondApp />, document.getElementById('root'));
    break;

  case undefined:
  default:
    ReactDOM.render(<App />, document.getElementById('root'));
    break;
}

SecondApp.js

import React, { Component } from 'react';

class SecondApp extends Component {
    constructor() {
        super();
    }
    render() {
        return <div>MY SECOND APP!</div>;
    }
}

export default SecondApp;

This way, everything will get packaged, minified, transmorgrifacated, etc. It seems a lot more palatable to do it this way than ejecting entirely. If you have legacy HTML/Javascript that isn't part of the module system, you put that in the public directory (and subdirectories), and Webpack will just copy it untouched.

Let me know if this is helpful.

Nick

@juliaogris
Copy link

I'm also trying to implement a User / Admin scenario.

@carruthe, I believe your approach is not working for me because the User part is simple and should be as light weight (code size wise) as possible as it's expected to be accessed mainly on mobile. The Admin part is more complex with more dependencies and expected to be accessed predominantly on desktop. I'd therefore prefer separate JS bundles for Client and Admin.

@tbillington, I think your suggestion should work with a bit of extra scripting to merge the separate build outputs into one, or am I passed duct-tape-strength?

@smmoosavi
Copy link

For admin/user use case you can use require.ensure(dependencies, callback) to load module async.
more detail

but I like create-react-app support multiple entry/bundle.

@gaearon
Copy link
Contributor

gaearon commented Feb 9, 2017

I agree it's something we'd like to see in the future.

@kohver
Copy link

kohver commented Mar 10, 2017

I've implemented this as proof of concept, so you can try it already by installing spiking-react-scripts@0.9.2-fork.2 on an existed CRA project:

  1. npm uninstall --save-dev react-scripts
  2. npm install --save-dev spiking-react-scripts@0.9.2-fork.2

To add a new entry point:

  1. Create the ./pages folder in the root of project and put in them a *.js file (for example ./pages/admin.js)
  2. npm run start (npm run build also works)
  3. Open http://localhost:3000/admin.html 🎉

Also I think it's a good first step for prerendred pages. All we need now is to generate *.html pages differently (see static-site-generator-webpack-plugin). What do think about the API?

Changes: stockspiking@fced96e

Known issues of this POC
  1. Dev server doesn't recompile after adding new entries
  2. New separated chunk /static/js/polyfills.js may be added after other scripts.
  3. It's not possible to change html template

@andymac4182
Copy link

@kohver Do you think it would be best to have a separate html file or using react-router to lazy load those extra js required. Something like this http://moduscreate.com/code-splitting-for-react-router-with-es6-imports/

@Alexter-progs
Copy link

My use case of having multiple entry points is that i'm developing plugins for cloud solutions of atlassian (jira, confluence) and all plugins injected into the system by iframe, so in different places like admin panel, main page panel, sections inside issues e.t.c. i need html page, since i want to use react i need to split my app into multiple pieces. It's quite inconvinient to create different folders for each section of the whole app bcs they could be very small and it would be easier to split them into folders by page or section. So the only way to me (for now) is to create my own build process.

@dan-kez
Copy link

dan-kez commented May 7, 2017

I also have a similar use case as Alexter-progs. I am developing a chrome extension which requires both background.js and inject.js files. At present, there isn't a way for me to generate separate bundles to be able to make a chrome extension.

@miraage
Copy link

miraage commented May 22, 2017

If you ask me, application should be separated into logical bundles and modules. It may sound a bit complicated, but let me explain.

For example, we want to build large application, with frontend (landing page), customer dashboard and admin dashboard.

We'll have 3 bundles, let's call them frontend, customer, admin. They are nothing but entry-points, only containing routes. Bundles should be able to reuse code, e.g. frontend will display plans for customers, which is edited/maintained in admin dashboard. Now we're approaching modules.

Module - set of components/reducers/middlewares/actions/etc grouped by logic, e.g. Users, Plans, Notifications, UIKit. Each module could communicate with each other and also be used by bundles only via single index.js containing all module's exports. Each module should be loaded on-demand, so we separate each bundle and module into it's own chunk.

I would be really happy if we can have current create-react-app structure as simple application and smth called advanced similar to I've described above. E.g. create-react-app foo creates simple app by default, but if we use create-react-app foo --advanced it would switch to advanced mode.

/cc @gaearon

@plievone
Copy link

Hi, using webpack built-in MultiCompiler it is quite easy to run different builds at the same time (including shared cache and quick rebuilding when watching).

In the most basic setup it would use the same index.html template and generate index.html, index2.html and indexanything.html from index.js, index2.js and indexanything.js, with minimal page-specific bundles, but using the same output dirs for assets. That would necessitate changing only a few lines in create-react-app react-scripts. I could send a PR as a discussion point, so we could see how it affects testing, routing etc? Somebody more knowledgeable in create-react-app customs could continue from there.

It might also be possible to configure source templates, output paths, etc, from package.json fields or file system structure (such as src/pages/indexname/index.js), but I would guess that outputting properly to different paths would need more involved changes depending on how paths are handled in build scripts. I could look into this briefly too, if you have opinions on how it should work...

@maoshuai
Copy link

maoshuai commented Jun 15, 2017

I met the same problem, here is my way, it works :

Four steps to add multiple entry points to create-react-app

(say we add an admin.html):

1. Eject the project

npm run eject  

2. Add multiple entry to webpack.config.dev.js

entry: {
    index: [
      require.resolve('react-dev-utils/webpackHotDevClient'),
      require.resolve('./polyfills'),
      require.resolve('react-error-overlay'),
      paths.appIndexJs,
    ],
    admin:[
      require.resolve('react-dev-utils/webpackHotDevClient'),
      require.resolve('./polyfills'),
      require.resolve('react-error-overlay'),
      paths.appSrc + "/admin.js",
      ]
  },
  output: {
    path: paths.appBuild,
    pathinfo: true,
    filename: 'static/js/[name].bundle.js',
    chunkFilename: 'static/js/[name].chunk.js',
    publicPath: publicPath,
    devtoolModuleFilenameTemplate: info =>
      path.resolve(info.absoluteResourcePath),
  },

3. Modify HtmlWebpackPlugin

add a new plugin node:

    new HtmlWebpackPlugin({
      inject: true,
      chunks: ["index"],
      template: paths.appHtml,
    }),
    new HtmlWebpackPlugin({
      inject: true,
      chunks: ["admin"],
      template: paths.appHtml,
      filename: 'admin.html',
    }),

4. webpack Dev Server

rewrite urls
/config/webpackDevServer.config.js:

    historyApiFallback: {
      disableDotRule: true,
      // 指明哪些路径映射到哪个html
      rewrites: [
        { from: /^\/admin.html/, to: '/build/admin.html' },
      ]
    }

detail: http://imshuai.com/create-react-app-multiple-entry-points/

@BrunoFenzl
Copy link

Thanks @maoshuai. Works perfectly!

@Sowed
Copy link

Sowed commented Jul 26, 2017

@maoshuai, Worked out well, thanks. Though I had to change the value of filename to 'admin.html', without the build/ like this...

 new HtmlWebpackPlugin({
      inject: true,
      chunks: ["admin"],
      template: paths.appHtml,
      filename: 'admin.html',
    }),

@maoshuai
Copy link

@Sowed You are right, I had amended it.

@codering
Copy link

codering commented Sep 9, 2017

Have some effects when change the output file name? The filename is "bundle.js" definitely in react-dev-utils/webpackHotDevClient.js.
https://github.com/facebookincubator/create-react-app/blob/master/packages/react-dev-utils/webpackHotDevClient.js#L36

@kresli
Copy link

kresli commented Sep 26, 2017

HI guys. I'm just wonder how you feel about extending webpack.config? Same or similar way as Storybook did it https://storybook.js.org/configurations/custom-webpack-config/? In that way you'll give more power to the end user. I can imagine something like this will kick off creating plugins for react-create-app and it could became quite conflicting. However, I believe this could be handled by some conflict message which warn user whenever overwriting property trying to overwrite already overwritten property. Thanks

@oklas
Copy link

oklas commented Apr 28, 2020

The mentioned questions is not related to the year and bundle version. It is application configuration and with same errors it will be bundled same way today (as before).

@iamandrewluca
Copy link
Contributor

@oklas his point was to show how app bundle can be splitted, not what actually is included in bundle

This weekend I experimented with angular-cli. They have a config, where you can add multiple projects

e.g.
image

For each project you can configure a lot of options

e.g
image

Maybe react-scripts should start moving to use this aproach maybe, to have a config file.

@harshalpandey
Copy link

Hello Guys,

Thanks a lot for your reply, But I am still not clear about the implementation with react application.

Let me try to tell you the exact use case of what exactly I want to achieve in my application.

Basically I need two entry points in the application one for the mail application and another is for the admin panel.

For Ex.
localhost:3000/app - it should run the main application.
localhost::3000/adminApp - it should run the application which will only be having menus that are related to admin.

Please let me know what is the exact solution I can use which will resolve my problem.

if something other then multiple entry points we can do to achieve this without ejecting the application that will also be fine.

@oklas
Copy link

oklas commented Apr 28, 2020

import Loadable from 'react-loadable'
import Loading from './my-loading-component'
import {BrowserRouter as Router, Switch, Route} from "react-router-dom"

const LoadableApp = Loadable({
  loader: () => import('./my-app'),
  loading: Loading,
});

const LoadableAdmin = Loadable({
  loader: () => import('./my-admin'),
  loading: Loading,
});

const App = () => (
  <Router>
    <Switch>
      <Route path="/app"><LoadableApp/></Route>
      <Route path="/admin"><LoadableAdmin/></Route>
    </Switch>
  </Router>
)

@9jaGuy
Copy link

9jaGuy commented Apr 29, 2020

In my situation, I have my main App.js using index.html but I also have chromecast-receiver.html for Google Chromecast application, I can't figure out a way to build and bundle my Chromecast App with CRA

@harshalpandey
Copy link

@oklas
Thanks for your solution.

I have one doubt/question. The solution which you have mentioned in which we are anyway using React Routes.

So after deploying build of my application on the server.

if I run my application and hit URL https://example.com it will initiate the route and then I can hit any of the URL (/app , /admin), and accordingly, it will load the related component.

But If I directly hit the URL https://example.com/app or https://example.com/admin , I think it will search for app or admin directory in my build folder and it will give me an error that

Not Found
The requested URL /app was not found on this server.

Do we have any solution for this?

@iamandrewluca
Copy link
Contributor

@harshalpandey when having a SPA, in most of cases server should return index.html when no request handler found.

@gino8080
Copy link

gino8080 commented May 8, 2020

You could do something funky with shell scripting. Not sure how practical this is but it will solve your problem (from how I interpret it).

Have two entry point js files, lets go with user.js and admin.js.

Have two build commands in package.json; build-user, build-admin.

When you go to run build-user, before running react-scripts build, have some shell code that copies user.js to index.js in your source code. Same for build-admin, just copy it's entry point to index.js before running the actual build command. This way if you're working on the same entry point consistently, you can still use build.

package.json

"build": "react-scripts build",
"build-user": "cp src/user.js src/index.js && react-scripts build",
"build-admin": "cp src/admin.js src/index.js && react-scripts build"

this sadly is still the best solution to avoid to eject

maybe is possible to use https://github.com/timarney/react-app-rewired/ and use some webpack plugin / configuration?

@9jaGuy
Copy link

9jaGuy commented May 8, 2020

any recommendation for me?

@Dmarcoux111
Copy link

Dmarcoux111 commented May 8, 2020

ugh, let me throw another one at u guys...

Electron application where you want 'modals', or, components in different windows, and you want said windows written in React. I have to pass different html files to electron, and it would be awesome if I could have multiple entry points because then my project looks like

/public
  index.html
  modal.html
/src
  /features
    /app
    /modal
  index.js
  modal.js

It seems to be a real pain to acheive this without ejecting and knowing everything about webpack

@jednano
Copy link

jednano commented May 8, 2020

You could do something funky with shell scripting. Not sure how practical this is but it will solve your problem (from how I interpret it).
Have two entry point js files, lets go with user.js and admin.js.
Have two build commands in package.json; build-user, build-admin.
When you go to run build-user, before running react-scripts build, have some shell code that copies user.js to index.js in your source code. Same for build-admin, just copy it's entry point to index.js before running the actual build command. This way if you're working on the same entry point consistently, you can still use build.
package.json

"build": "react-scripts build",
"build-user": "cp src/user.js src/index.js && react-scripts build",
"build-admin": "cp src/admin.js src/index.js && react-scripts build"

this sadly is still the best solution to avoid to eject

maybe is possible to use https://github.com/timarney/react-app-rewired/ and use some webpack plugin / configuration?

I have to keep pointing out that this is NOT a solution, as it eliminates the possibility of bundle optimizations between entry points. If that doesn't matter to you, then I suppose it's an OK solution. Just don't want to lead anyone astray here.

@iamandrewluca
Copy link
Contributor

iamandrewluca commented May 8, 2020

Maybe owners should add the repo on issuehunt to collect donations for most wanted features, or fixing issues.

@Dmarcoux111
Copy link

Dmarcoux111 commented May 8, 2020

lol, 'eh'

My solution was:

use react-app-rewired

Config for anyone who needs it in the future

const HtmlWebpackPlugin = require('html-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin');

const path = require( 'path' )

module.exports = {
  webpack: ( config, env ) => {
    // We need a way to transpile web workers so we can use them within react,
    // so it was necessary to override the default webpack config. This may
    // not be necessary in the future
    config.module.rules.push({
      test: /\.worker\.js$/,
      use: { loader: 'worker-loader' }
    })

    // We also need a way to use node modules in web workers, so we override the
    // default target to electron-renderer
    config.target = 'electron-renderer';

    //  Push the other html page
    config.plugins.push( new HtmlWebpackPlugin( {
      inject: true,
      chunks: ["test"],
      filename: 'test.html',
      template: path.join( __dirname, 'public', 'test.html' ),
    } ) )

    //  Tell React Dev server to use other names than main
    config.plugins.push( new ManifestPlugin( {
      fileName: 'asset-manifest.json',
      publicPath: '/',
      generate: (seed, files, entrypoints) => {
        const manifestFiles = files.reduce((manifest, file) => {
          manifest[file.name] = file.path;
          return manifest;
        }, seed);
        // Previous code
        // const entrypointFiles = entrypoints.main.filter(
        //   fileName => !fileName.endsWith('.map')
        // );
        const entrypointFiles = {};
        Object.keys(entrypoints).forEach(entrypoint => {
          entrypointFiles[entrypoint] = entrypoints[entrypoint].filter(fileName => !fileName.endsWith('.map'));
        });
        return {
          files: manifestFiles,
          entrypoints: entrypointFiles,
        };
      },
    } ) )

    //  Necessary for some reason I don't entirely know
    config.output['globalObject'] = 'this';
    return config
  },
  jest: ( config ) => {
    return config
  },
  devServer: ( configFunction ) => {
    return ( proxy, allowedHost ) => {
      const config = configFunction( proxy, allowedHost )
      return config
    }
  },
  paths: ( paths, env ) => {
    return paths
  }
}

Then in index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import './index.css'

// We wrap the application in a global store provider to use redux functionality
// with React hooks

//  Components
import App from './features/app/component'
import Test from './features/test/component'

import { remote } from 'electron'

const array = window.location.href.split( '/' )
const html = array[ array.length - 1 ]
console.log( html )

ReactDOM.render(
  <Provider store={ remote.getGlobal( 'store' ) }>
    { html === 'index.html'
      ? <App />
      : <Test />
    }
  </Provider>,
  document.getElementById( 'root' )
)

@ashnamuh
Copy link

ashnamuh commented May 13, 2020

My solution is:

scripts on package.json

    "dev": "react-scripts start",
    "dev:admin": "REACT_APP_MODE=admin react-scripts start",

and index.jsx

import React from 'react'
import ReactDOM from 'react-dom'
import CustomerApp from './App'
import AdminApp from './AdminApp'

const App = process.env.REACT_APP_MODE === 'admin' ? AdminApp : CustomerApp

ReactDOM.render(
  <React.StrictMode>
      <App />
  </React.StrictMode>,
  document.getElementById('root')
)

@seven1240
Copy link

seven1240 commented May 15, 2020

this is the patch I have been using

20a21
> const envEntryPoint = process.env.ENTRY_POINT || 'index';
82,83c83,84
<   appHtml: resolveApp('public/index.html'),
<   appIndexJs: resolveModule(resolveApp, 'src/index'),
---
>   appHtml: resolveApp('public/' + envEntryPoint + '.html'),
>   appIndexJs: resolveModule(resolveApp, 'src/' + envEntryPoint),
104,105c105,106
<   appHtml: resolveApp('public/index.html'),
<   appIndexJs: resolveModule(resolveApp, 'src/index'),
---
>   appHtml: resolveApp('public/' + envEntryPoint + '.html'),
>   appIndexJs: resolveModule(resolveApp, 'src/' + envEntryPoint),

so I can do

ENTRY_POINT=index yarn build
ENTRY_POINT=index2 yarn build
ENTRY_POINT=index3 yarn build

@imayka
Copy link

imayka commented Oct 9, 2020

this is the patch I have been using

20a21
> const envEntryPoint = process.env.ENTRY_POINT || 'index';
82,83c83,84
<   appHtml: resolveApp('public/index.html'),
<   appIndexJs: resolveModule(resolveApp, 'src/index'),
---
>   appHtml: resolveApp('public/' + envEntryPoint + '.html'),
>   appIndexJs: resolveModule(resolveApp, 'src/' + envEntryPoint),
104,105c105,106
<   appHtml: resolveApp('public/index.html'),
<   appIndexJs: resolveModule(resolveApp, 'src/index'),
---
>   appHtml: resolveApp('public/' + envEntryPoint + '.html'),
>   appIndexJs: resolveModule(resolveApp, 'src/' + envEntryPoint),

so I can do

ENTRY_POINT=index yarn build
ENTRY_POINT=index2 yarn build
ENTRY_POINT=index3 yarn build

Perfect, i hope it won't broke in the future

@ftruzzi
Copy link

ftruzzi commented Oct 11, 2020

Another use case for this is when you have a mostly static site and you want to add bits of React here and there while being able to take advantage of webpack and keep the bundles separate.

For example, if you have a React form on the homepage of mysite.com and you also want React to handle a list of FAQs at mysite.com/faq, you don't want users visiting the FAQ page to load a bundle containing code that is not relevant.

I can understand if this is out of scope for CRA though.

@narthollis
Copy link

My use case for multiple entry points is implementing an OpenID Connect silent login in an iframe. The second entry point for the applications is a light weight page that is the result of the login redirect, and communicates with the main page via postMessage. This could be done as an application route or similar, but redirecting to a /silent_renew.html that loads just enough JS to communicate feels a lot cleaner to me than redirecting to /silent_renew that is a HTML5 route in the main application.

@seven1240
Copy link

seven1240 commented Oct 11, 2020 via email

@danvc
Copy link

danvc commented Oct 11, 2020 via email

@oklas
Copy link

oklas commented Oct 11, 2020

Fort this, you could be using code splitting

There is an example above

@wespickett
Copy link

I found this post that may help some people with this issue. It seems to work for me.

https://blog.logrocket.com/multiple-entry-points-in-create-react-app-without-ejecting/

"TL; DR
You can create multiple entry points in a CRA application without ejecting by using an environment variable to conditionally import container files. Doing this prevents code from the other containers appearing in the desired bundled build."

@ftruzzi
Copy link

ftruzzi commented Oct 23, 2020

I did it using https://github.com/Derek-Hu/react-app-rewire-multiple-entry in the end.

Thank you @danvc and @oklas for the tip, but I wanted to avoid using react-router if possible.

@danvc
Copy link

danvc commented Oct 24, 2020

@ftruzzi looks at this example that I've implemented (without external modules):

https://github.com/danvc/create-react-app-multiple-entry-points

@yarcowang
Copy link

Hello, guys, what about using React in chrome extension development?
There's no appHtml, but a content script entry which defined in manifest.json.

  "content_scripts": [{
    "matches": "<all_urls>",
    "js": ["./static/js/content.js"]
  }]

@Obooman
Copy link

Obooman commented Dec 8, 2020

Since the create-react-app project has only one public/index.html, and a single src/index.js as js entrance, I use the following solution ( with react-app-rewired or alike package ) for the multiple-page project.

<!-- public/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>React App</title>
  <script> window.__APPLICATION_TEMPLATE__ = "<%= entranceName %>" </script>
</head>
<body>
  <%= require("src/partials/getPageTemplate.js")(entranceName) %>
</body>
</html>
// src/partials/getPageTemplate.js

module.exports = (appType) => {
  if( appType === appEnum.admin ){
    return `<div>Admin</div>`
  }
}
// src/index.js

(async () => {
  if( window.__APPLICATION_TEMPLATE__ = appEnum.admin ){
    await import("./admin")
  } else if( window.__APPLICATION_TEMPLATE__ = appEnum.toolset ){
    await import("./toolset")
  }
})()

here's config-override.js of react-app-rewired

const HTMLWebpackPlugin = require("html-webpack-plugin")

module.exports = {
  webpack(config){
    const configTemplate = config.plugins[0].options;

    const configForAdmin = new HTMLWebpackPlugin(configTemplate);
    
    configForAdmin.options.templateParameters = {
       entranceName: entranceEnum.admin,
       filename: "admin.html"
    }

    //  and any other entrances you want.

    config.plugins.unshift(configForAdmin);
    return config;
  }
}

So we can have index.html and admin.html, thanks to chunk split by dynamic import the two applications' javascript been splitted into different parts, and ejection is not required, and it's a one-time build.

@KurtGokhan
Copy link

KurtGokhan commented May 24, 2022

I have a proposal about this which provides a conventional way to add multiple entry files. How about treating every js-like file under src/entries/ folder like a separate entry file? I have this Craco configuration and it works good for me.

So if you have a folder structure like this:

src/
  ...
  index.tsx
  entries/
    landing.ts
    login.ts

Then it will output 3 entry points. index, landing, login. The html template will be picked from /public/<entry>.html and build will fail if this file does not exist. Output file will be /dist/<entry>.html. This behaviour is too implicit but I think it would be an easy way to add multiple entry points. (For index, the entry name can be main to preserve backward compatibility.)

@ThisIsntPatrick4312
Copy link

Hey @yarcowang did you manage to get this to work? Im trying to add two different content scripts (one uses all_frames, other one doesnt), but I cant seem to get it to work. Any ideas?

@yarcowang
Copy link

yarcowang commented Aug 5, 2022

@ThisIsntPatrick4312 I'm using vite to manage the project, https://stackoverflow.com/questions/70522494/multiple-entry-points-in-vite, it seems simple (than create-react-app) to me.

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

No branches or pull requests