创建React App V2-多个入口点 [英] Create React App V2 - Multiple entry points

查看:122
本文介绍了创建React App V2-多个入口点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个具有2个入口点的React应用程序,一个用于应用程序,一个用于管理面板.

I'm trying to build a React app with 2 entry points, one for the App and one for the Admin panel.

我从Create React App V2开始,并遵循此gitHub问题线程 https://github.com/facebook/create-react-app/issues/1084 和本教程

I'm starting with Create React App V2 and following this gitHub issue thread https://github.com/facebook/create-react-app/issues/1084 and this tutorial http://imshuai.com/create-react-app-multiple-entry-points/.

我正在尝试移植有关从CRA V1添加多个入口点的说明,以便在V2中工作,但是我认为我遗漏了一些东西.

I'm trying to port the instructions for adding multiple entry points from CRA V1 to work in V2 but I think I am missing something.

弹出CRA后,这些是我已更改/添加到path.js的路径:

After ejecting CRA, these are the paths I've changed/added to paths.js:

module.exports = {
    appBuild: resolveApp('build/app'),
    appPublic: resolveApp('public/app'),
    appHtml: resolveApp('public/app/index.html'),
    appIndexJs: resolveModule(resolveApp, 'src/app'),
    appSrc: resolveApp('src'),
    adminIndexJs: resolveModule(resolveApp, 'src/admin'),
    adminSrc: resolveApp('src'),
    adminPublic: resolveApp('public/admin'),
    adminHtml: resolveApp('public/admin/index.html'),
};

我已将以下入口点添加到webpack:

I've added these entry points to webpack:

    entry: {
        app: [
            isEnvDevelopment &&
                require.resolve('react-dev-utils/webpackHotDevClient'),
            paths.appIndexJs,
        ].filter(Boolean),
        admin: [
            isEnvDevelopment &&
                require.resolve('react-dev-utils/webpackHotDevClient'),
            paths.adminIndexJs,
        ].filter(Boolean)
    },
    output: {
      path: isEnvProduction ? paths.appBuild : undefined,
      pathinfo: isEnvDevelopment,
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',
      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, '/')),
    },

我已经像这样修改了HtmlWebpackPlugin:

I've modified HtmlWebpackPlugin like so:

  new HtmlWebpackPlugin(
    Object.assign(
      {},
      {
        inject: true,
        template: paths.appHtml,
        filename: paths.appPublic,
      },
      isEnvProduction
        ? {
            minify: {
              removeComments: true,
              collapseWhitespace: true,
              removeRedundantAttributes: true,
              useShortDoctype: true,
              removeEmptyAttributes: true,
              removeStyleLinkTypeAttributes: true,
              keepClosingSlash: true,
              minifyJS: true,
              minifyCSS: true,
              minifyURLs: true,
            },
          }
        : undefined
    )
  ),
  new HtmlWebpackPlugin(
    Object.assign(
      {},
      {
        inject: true,
        template: paths.adminHtml,
        filename: paths.adminPublic,
      },
      isEnvProduction
        ? {
            minify: {
              removeComments: true,
              collapseWhitespace: true,
              removeRedundantAttributes: true,
              useShortDoctype: true,
              removeEmptyAttributes: true,
              removeStyleLinkTypeAttributes: true,
              keepClosingSlash: true,
              minifyJS: true,
              minifyCSS: true,
              minifyURLs: true,
            },
          }
        : undefined
    )
  ),

并修改了webpack开发服务器:

And modified webpack Dev Server:

historyApiFallback: {
  disableDotRule: true,
  rewrites: [
    { from: /^\/admin.html/, to: '/build/admin/index.html' },
  ]
},

我的文件结构如下:

.
+-- _src
|   +-- app.js
|   +-- admin.js
|   +-- _app
|       +-- App.js
|   +-- _admin
|       +-- App.js
|   +-- _shared
|       +-- serviceWorker.js
+-- _public
|   +-- _app
|       +-- index.html
|       +-- manifest.json
|   +-- _admin
|       +-- index.html
|       +-- manifest.json

我希望我的构建文件夹包含一个应用程序文件夹和一个其中包含2个独立SPA的管理文件夹.

I would like my build folder to contain an app folder and an admin folder with the 2 separate SPA's in them.

当我运行 yarn start 时,它不会引发任何错误,并说 Compiled成功!,但是它仅部分编译了该应用程序,而不是管理应用程序,因此没有js已被编译或添加到应用中.

When I run yarn start it doesn't throw any errors and says Compiled successfully! however its only partially compiled the app and not the admin app, no js has been compiled or added to the app either.

yarn build 确实抛出错误,并且编译了一半的应用程序,没有管理应用程序.这是错误:

yarn build does throw an error and a half compiled app, no admin app. This is the error:

yarn run v1.12.3
$ node scripts/build.js
Creating an optimized production build...
Failed to compile.

EISDIR: illegal operation on a directory, open 
'foo/bar/public/app'


error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

在构建文件夹中,它在退出之前已经创建了很多内容:

In the build folder it had created much this before it exit:

.
+-- _static
|   +-- _css
|   +-- _js
|   +-- _media
|       +-- logo.5d5d9eef.svg
+-- precache-manifest.a9c066d088142837bfe429bd3779ebfa.js
+-- service-worker.js
+-- asset-manifest.json
+-- manifest.json

有人知道我要正确完成这项工作所缺少的吗?

Does anyone know what I am missing out to make this work correctly?

推荐答案

我意识到将 HTMLWebpackPlugin 中的文件名设置为 appPublic adminPublic 不正确,应该为 app/index.html admin/index.html .

I realised that setting filename in HTMLWebpackPlugin to appPublic or adminPublic was incorrect and it should be app/index.html admin/index.html.

但是我想要在build文件夹中有2个单独的文件夹,一个用于应用程序,另一个用于管理应用程序,使用此方法需要更多的复杂性,因为webpack中没有可用于设置目标位置的输入变量小路.例如,我需要能够执行 [entry]/static/js/[name].[contenthash:8] .chunk.js 之类的操作.我认为实现此目的的一种方法是使用Webpack MultiCompiler.

However where I would like 2 separate folders in the build folder, one for the app and the other for the admin app, using this method requires more complexity because there is no entry variable in webpack that you can use to set the destination path. For example I would need to be able to do something like [entry]/static/js/[name].[contenthash:8].chunk.js. I think one way to do this would be to use Webpack MultiCompiler.

但是,我没有这样做,而是在package.json中将入口点作为环境变量传递了,像这样添加了 REACT_APP_ENTRY = :

However rather than doing this this I've passed the entry point as an environment variable in package.json, adding REACT_APP_ENTRY= like so:

  "scripts": {
    "start-app": "REACT_APP_ENTRY=app node scripts/start.js",
    "build-app": "REACT_APP_ENTRY=app node scripts/build.js",
    "start-admin": "REACT_APP_ENTRY=admin node scripts/start.js",
    "build-admin": "REACT_APP_ENTRY=admin node scripts/build.js",
    "test": "node scripts/test.js"
  },

在start.js中,我在顶部添加了 const isApp = process.env.REACT_APP_ENTRY ==='app'; :

In start.js I added const isApp = process.env.REACT_APP_ENTRY === 'app'; at the top:

'use strict';

process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';

const isApp = process.env.REACT_APP_ENTRY === 'app';

并更新了设置端口的位置,这样我可以同时运行两个开发服务器而不会发生冲突:

And updated where the port is being set, this is so I can run both development servers at the same time without a clash:

const DEFAULT_PORT = parseInt(process.env.PORT, 10) || (isApp ? 3000 : 3001);
const HOST = process.env.HOST || '0.0.0.0';

然后在path.js顶部添加 const isApp = process.env.REACT_APP_ENTRY ==='app'; :

Then at the top of paths.js add const isApp = process.env.REACT_APP_ENTRY === 'app';:

const envPublicUrl = process.env.PUBLIC_URL;
const isApp = process.env.REACT_APP_ENTRY === 'app';

最后根据env变量集更新路径:

And finally update the paths depending on the env variable set:

module.exports = {
  dotenv: resolveApp('.env'),
  appPath: resolveApp('.'),
  appBuild: isApp ? resolveApp('build/app') : resolveApp('build/admin'),
  appPublic: isApp ? resolveApp('public/app') : resolveApp('public/admin'),
  appHtml: isApp ? resolveApp('public/app/index.html') : resolveApp('public/admin/index.html'),
  appIndexJs: isApp ? resolveModule(resolveApp, 'src/app') : resolveModule(resolveApp, 'src/admin'),
  appPackageJson: resolveApp('package.json'),
  appSrc: resolveApp('src'),
  appTsConfig: resolveApp('tsconfig.json'),
  yarnLockFile: resolveApp('yarn.lock'),
  testsSetup: resolveModule(resolveApp, 'src/setupTests'),
  proxySetup: resolveApp('src/setupProxy.js'),
  appNodeModules: resolveApp('node_modules'),
  publicUrl: getPublicUrl(resolveApp('package.json')),
  servedPath: getServedPath(resolveApp('package.json')),
};

我认为这种方法以及简单得多的方法对于此用例而言是优越的,因为它允许灵活地仅编译应用程序或仅编译管理员,而不是在只更改一个时强制您编译两者.我可以同时运行 yarn start-app yarn start-admin ,并在不同端口上运行单独的应用程序.

I think this method as well as being far simpler is superior for this use case as it allows the flexibility to compile only the app or only the admin rather than forcing you to compile both when only one has been changed. I can run both yarn start-app and yarn start-admin at the same time with the separate apps running on different ports.

这篇关于创建React App V2-多个入口点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆