require 方法仅在开发中有效(因为所有 CSS 在构建时捆绑),import 方法根本不起作用(使用 CRA 版本 3.3)。
在我们的例子中,我们有多个主题,无法捆绑 - 所以我们使用 React.lazy 和 React.Suspense 解决了这个问题。
我们有ThemeSelector,它有条件地加载正确的css。
import React from 'react';
/**
* The theme components only imports it's theme CSS-file. These components are lazy
* loaded, to enable "code splitting" (in order to avoid the themes being bundled together)
*/
const Theme1 = React.lazy(() => import('./Theme1'));
const Theme2 = React.lazy(() => import('./Theme2'));
const ThemeSelector: React.FC = ({ children }) => (
<>
{/* Conditionally render theme, based on the current client context */}
<React.Suspense fallback={() => null}>
{shouldRenderTheme1 && <Theme1 />}
{shouldRenderTheme2 && <Theme2 />}
</React.Suspense>
{/* Render children immediately! */}
{children}
</>
);
export default ThemeSelector;
Theme 组件唯一的工作就是导入正确的 css 文件:
import * as React from 'react';
// ? Only important line - as this component should be lazy-loaded,
// to enable code - splitting for this CSS.
import 'theme1.css';
const Theme1: React.FC = () => <></>;
export default Theme1;
ThemeSelector 应将App 组件包装在src/index.tsx 中:
import React from 'react';
import ReactDOM from 'react-dom';
import ThemeSelector from 'themes/ThemeSelector';
ReactDOM.render(
<ThemeSelector>
<App />
</ThemeSelector>,
document.getElementById('root')
);
据我了解,这会强制将每个 Theme 拆分为单独的包(实际上也拆分 CSS)。
如 cmets 中所述,此解决方案没有提供切换主题运行时的简单方法。此解决方案侧重于将主题拆分为单独的包。
如果您已经将主题拆分为单独的 CSS 文件,并且想要交换主题运行时,您可能需要查看使用 ReactHelmet (illustrated by @Alexander Ladonin's answer below) 的解决方案