使用 create-react-app 的多个入口点

Posted

技术标签:

【中文标题】使用 create-react-app 的多个入口点【英文标题】:multiple entry points by using create-react-app 【发布时间】:2019-04-28 00:52:24 【问题描述】:

我有一个包含 20% 的 React 组件和 80% 的普通 html 内容的页面。需要在页面的不同点放置多个 React 组件,因此我需要 index.html 中的多个入口点。我想使用 create-react-app,但我不想使用 redux,因为页面很小。有没有相对容易的方法在 index.html 中创建 2 个入口点,以便页面上的所有反应组件都可以访问单亲的道具? .. 或者是否可以将全局变量与事件侦听器一起使用来进行更改,从而触发更新不同入口点中的反应组件? .. 请告诉我此类任务的最佳实践,因为我不想从单个入口点使用 jsx 开发整个页面。

【问题讨论】:

【参考方案1】:

添加多个入口点需要修改默认的react-scripts 配置。弹出(即从react-scripts 提取所有配置并自行管理)是一种方法。

弹出允许您自定义任何内容,但从那时起,您必须自己维护配置和脚本。如果您有许多类似的项目,这可能会令人生畏。在这种情况下,我们建议不要退出,而是 fork react-scripts 和您需要的任何其他包

详情请访问https://create-react-app.dev/docs/alternatives-to-ejecting。

当我遇到这个问题时,我创建了脚本的一个分支,并在https://www.npmjs.com/package/@linsight/react-scripts 上提供了它。请尝试一下。

记得将react-app-env.d.ts 文件更新为:

/// <reference types="@linsight/react-scripts" />

【讨论】:

【参考方案2】:

我知道这是一个延迟的答案,但只是为了将来的搜索,步骤是:

    弹出 (yarn eject) 编辑paths.js,在appHtml的入口下添加第二个入口点html文件
appAdminHtml: resolveApp('public/admin.html'),
    更新webpack.config.js 中的条目,使每个条目点包含一个条目。
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)
,
    将生成的输出JS文件改成入口名(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',
,
    更新插件以使用注入的 js 脚本生成第二个文件(也在 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 insidewebpack.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' ,
  ]
,

由于 Prod 服务器设置可能完全不同,我会让你弄清楚。

This post 更详细地描述了所有内容。

【讨论】:

【参考方案3】:

为避免弹出您可能需要检查rescripts,您可以像这样添加要添加到 index.html 的入口点:

在项目主目录中创建 .rescriptsrc.js 文件:

module.exports = [
  config => 
      config.entry = 
         app: ["./src/index.js"],
         content: ["./src/content.js"],
      ;
  
];

【讨论】:

我有一些问题没有在条目中定义main,rescripts 给了我一个错误,但是将它定义为 dummy/stub 并稍微操纵了 webpack 配置,我设法得到了我正在寻找的结果为。 @Alex 可能想在他们的 github 上创建一个问题,开发人员非常有帮助 我要求提供一些使用多个条目的示例,但他们建议我在此处发布。我认为问题更多在于 CRA 基础架构,支持多个条目存在一个未解决的问题,但这需要时间。

以上是关于使用 create-react-app 的多个入口点的主要内容,如果未能解决你的问题,请参考以下文章

create-react-app修改入口文件

webpack+react多页面开发-终极架构

webpack4+react多页面架构

webpack4+react多页面架构

webpack4+react多页面架构

将 Create-React-App 部署到多个 URL