Reputation: 31
I have a page with 20% of React components and 80% of normal html content. It is necessary to place several react components at different points of the page, and therefore I need several entry points in index.html. I want to use create-react-app, but I don’t want to use redux, since the page is rather small. Are there ways it’s relatively easy to make 2 entry points in index.html so that ALL react components on the page have access to the single parent's props? .. Or is it possible to use global variables with an event listener for their changes that would triger update the react components in different entry points? .. Please tell me the best practice for such tasks, because I don't want to develop a whole page by using jsx from a single entry point.
Upvotes: 3
Views: 3826
Reputation: 13353
Adding multiple entry points require modifying the default react-scripts
configuration. Ejecting (i.e. extracting all configuration from react-scripts
and manage them yourself) is one way to do so.
Ejecting lets you customize anything, but from that point on you have to maintain the configuration and scripts yourself. This can be daunting if you have many similar projects. In such cases instead of ejecting we recommend to fork react-scripts and any other packages you need
Please visit https://create-react-app.dev/docs/alternatives-to-ejecting for details.
When I came across this problem, I created a fork of the script and made it available at https://www.npmjs.com/package/@linsight/react-scripts. Please try it out.
Do remember updating the react-app-env.d.ts
file to:
/// <reference types="@linsight/react-scripts" />
Upvotes: 0
Reputation: 10966
I know it's a delayed answer, but just for future searches, the steps are:
yarn eject
)appAdminHtml: resolveApp('public/admin.html'),
webpack.config.js
to include one entry per entry point.entry: {
index: [
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
].filter(Boolean),
admin: [
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + '/admin/index.js',
].filter(Boolean)
},
webpack.config.js
)output: {
path: isEnvProduction ? paths.appBuild : undefined,
pathinfo: isEnvDevelopment,
// This is the important entry
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/[name].bundle.js',
futureEmitAssets: true,
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: isEnvProduction
? info =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
jsonpFunction: `webpackJsonp${appPackageJson.name}`,
globalObject: 'this',
},
webpack.config.js
).// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
chunks: ['index'],
template: paths.appHtml,
filename: 'index.html'
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Generates an `admin.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
chunks: ['admin'],
template: paths.appAdminHtml,
filename: 'admin.html',
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
ManifestPlugin configuration to include the new entry point (also inside
webpack.config.js`):new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
generate: (seed, files, entrypoints) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
let entrypointFiles = [];
for (let [entryFile, fileName] of Object.entries(entrypoints)) {
let notMapFiles = fileName.filter(fileName => !fileName.endsWith('.map'));
entrypointFiles = entrypointFiles.concat(notMapFiles);
};
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
webpackDevServer.config.js
. historyApiFallback: {
disableDotRule: true,
verbose: true,
rewrites: [
{ from: /^\/admin/, to: '/admin.html' },
]
},
Since Prod server settings can be quite different, I'll let you figure it out.
This post describes everything in more detail.
Upvotes: 1
Reputation: 1551
To avoid ejecting you might want to check rescripts, you can add entry points to be added to index.html like so:
create .rescriptsrc.js file in projects main directory:
module.exports = [
config => {
config.entry = {
app: ["./src/index.js"],
content: ["./src/content.js"],
};
}
];
Upvotes: 1