如何使 @emotion/react和 @情感/风格创建React应用程序

发布于 2025-01-31 22:05:56 字数 3948 浏览 4 评论 0原文

我有以下架构:

  • 主-Frontend

  • foo-frontend

  • bar-frontend

  • baz-frontend

main-frontendfoo-frontendbar-frontendbaz-frontend都是标准react使用创建create-react-app生成的应用程序。

MAIN-FRONTEND以包裹在Web组件中的React组件中,所有这些都将其UI发布。这些Web组件可以加载到main-Frontend中,将所有3个子额定值编织到一个超额外。

我面临的问题是,为了使这种工作方法,所有4个前端都必须外部化reactreact-domreact> react-router,以及使用的任何CSS-IN-JS框架。

我可以使用rewire软件包和几个脚本修改create-react-app生成的react应用程序的配置。我正在以下面的身份将其重现为面临类似问题的其他人。

中,foo-frontendbar-frontendbaz-frontend

package.json

  "dependencies": {
    ...
    "rewire": "^6.0.0"
    ...
  },
  "scripts": {
    "start": "node start.js",
    "build": "node build.js",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "webpackConfig": {
    "externals": {
      "react": "react",
      "react-dom": "react-dom",
      "@emotion/react": "@emotion/react",
      "@emotion/styled": "@emotion/styled"
    }
  }

build.js

const rewire = require('rewire');
const defaults = rewire('react-scripts/scripts/build.js');

const {
  webpackConfig: {
    externals
  }
} = require('./package.json');

const config = defaults.__get__('config');

config.externals = externals;

开始

const rewire = require('rewire');
const defaults = rewire('react-scripts/scripts/start.js');
const webpackConfig = require('react-scripts/config/webpack.config');

const {
  webpackConfig: {
    externals
  }
} = require('./package.json');

defaults.__set__('configFactory', (webpackEnv) => {
  const config = webpackConfig(webpackEnv);

  config.externals = externals;

  return config;
});

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@emotion/[email protected]/dist/emotion-react.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@emotion/[email protected]/dist/emotion-styled.umd.min.js"></script>
  </head>
  <body>
  ...
  </body>
</html>

>@情感/样式无法正确外部化。

Uncaught ReferenceError: emotion is not defined
    at Object.@emotion/react (external var "emotion":1:1)
    at Object.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Module../src/components/App/styles.tsx (index.tsx:25:1)
    at Module.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Module../src/components/App/index.tsx (logo.svg:34:1)
    at Module.options.factory (react refresh:6:1)

我该如何解决?

I have the following architecture:

  • main-frontend

  • foo-frontend

  • bar-frontend

  • baz-frontend

main-frontend, foo-frontend, bar-frontend and baz-frontend are all standard React apps generated using create-react-app.

All of them except main-frontend publish their UI as a React component, wrapped in a Web component. These Web components can be loaded into the main-frontend to weave all 3 sub-frontends into one super-frontend.

The problem I am facing is that in order for this approach to work, all 4 frontends have to externalize react, react-dom, react-router, and any CSS-in-JS frameworks being used.

I am able to modify Webpack configuration for create-react-app generated React apps, using the rewire package and a couple of scripts. I am reproducing these below for others facing a similar problem.

In each of foo-frontend, bar-frontend, and baz-frontend,

package.json

  "dependencies": {
    ...
    "rewire": "^6.0.0"
    ...
  },
  "scripts": {
    "start": "node start.js",
    "build": "node build.js",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "webpackConfig": {
    "externals": {
      "react": "react",
      "react-dom": "react-dom",
      "@emotion/react": "@emotion/react",
      "@emotion/styled": "@emotion/styled"
    }
  }

build.js

const rewire = require('rewire');
const defaults = rewire('react-scripts/scripts/build.js');

const {
  webpackConfig: {
    externals
  }
} = require('./package.json');

const config = defaults.__get__('config');

config.externals = externals;

start.js

const rewire = require('rewire');
const defaults = rewire('react-scripts/scripts/start.js');
const webpackConfig = require('react-scripts/config/webpack.config');

const {
  webpackConfig: {
    externals
  }
} = require('./package.json');

defaults.__set__('configFactory', (webpackEnv) => {
  const config = webpackConfig(webpackEnv);

  config.externals = externals;

  return config;
});

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@emotion/[email protected]/dist/emotion-react.umd.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@emotion/[email protected]/dist/emotion-styled.umd.min.js"></script>
  </head>
  <body>
  ...
  </body>
</html>

The problem I am getting is that @emotion/react and @emotion/styled aren't being externalized correctly.

Uncaught ReferenceError: emotion is not defined
    at Object.@emotion/react (external var "emotion":1:1)
    at Object.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Module../src/components/App/styles.tsx (index.tsx:25:1)
    at Module.options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at Module../src/components/App/index.tsx (logo.svg:34:1)
    at Module.options.factory (react refresh:6:1)

How do I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白馒头 2025-02-07 22:05:56

我设法解决了这个问题,而不是使用@情感/react@emotion/样式,而是使用stypled-components

公平地说,这是我对CSS-In-JS框架的最初偏爱。

在以前的尝试中,我一直在使用错误的版本的样式组件库。

这是我设法做到的:

package.json 在所有4个React应用程序中都应像这样修改。

{
  ...
  "dependencies": {
    ...
    "@types/styled-components": "^5.1.25",
    "rewire": "^6.0.0",
    "styled-components": "^5.3.5",
    ...
  },
  "scripts": {
    "start": "PORT=3004 node start.js",
    "build": "PORT=3004 node build.js",
    "test": "PORT=3004 react-scripts test",
    "eject": "PORT=3004 react-scripts eject"
  },
  "webpackConfig": {
    "externals": {
      "react": "React",
      "react-dom": "ReactDOM",
      "react-is": "ReactIS",
      "styled-components": "styled"
    }
  },
  ...
}

public/index.html 在3个子范围内应该像这样修改:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-is.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/styled-components.min.js"></script>
    ...
  </head>
  <body>
  ...
  </body>
</html>

public/index.html for Super-Frontend将是相似的,但也将包括脚本标签要导入子额外登出:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-is.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/styled-components.min.js"></script>
    <script src="http://localhost:3001/static/js/bundle.js"></script>
    <script src="http://localhost:3002/static/js/bundle.js"></script>
    <script src="http://localhost:3003/static/js/bundle.js"></script>
    ...
  </head>
  <body>
  ...
  </body>
</html>

tl; dr; dr; :请注意react-is-isstypled-components的外部词/code>和样式组件的版本通过CDN加载。

I managed to solve this, not with @emotion/react and @emotion/styled, but with styled-components.

To be fair, that was my initial preference for a CSS-in-JS framework.

In my previous attempts, I had been using the wrong version of the styled-components library.

Here's how I managed to do it:

package.json in all 4 React apps should be modified like so.

{
  ...
  "dependencies": {
    ...
    "@types/styled-components": "^5.1.25",
    "rewire": "^6.0.0",
    "styled-components": "^5.3.5",
    ...
  },
  "scripts": {
    "start": "PORT=3004 node start.js",
    "build": "PORT=3004 node build.js",
    "test": "PORT=3004 react-scripts test",
    "eject": "PORT=3004 react-scripts eject"
  },
  "webpackConfig": {
    "externals": {
      "react": "React",
      "react-dom": "ReactDOM",
      "react-is": "ReactIS",
      "styled-components": "styled"
    }
  },
  ...
}

public/index.html in the 3 sub-frontends should be modified like so:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-is.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/styled-components.min.js"></script>
    ...
  </head>
  <body>
  ...
  </body>
</html>

The public/index.html for the super-frontend will be similar, but will also include script tags to import the sub-frontends:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>Atlas Reviews</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-is.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/styled-components.min.js"></script>
    <script src="http://localhost:3001/static/js/bundle.js"></script>
    <script src="http://localhost:3002/static/js/bundle.js"></script>
    <script src="http://localhost:3003/static/js/bundle.js"></script>
    ...
  </head>
  <body>
  ...
  </body>
</html>

TL;DR;: Note the externals for react-is and styled-components and the version of the styled-components script being loaded via CDN.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文