首页 > 解决方案 > 具有 Preact SSR 和 RTL 支持的 Emotion.js

问题描述

我有一个 preact SSR 应用程序并使用 Emotion JS 10 进行样式设置。

我想为此添加 RTL 支持,因此使用createEmotioncreateEmotionServer使用结果renderStylesToString来呈现应用程序。

但是,在创建createEmotion它时需要使用我添加插件的stylis-rtl插件,但这总是会应用 RTL 样式,而我希望根据每个请求应用 RTL 样式。

我找不到任何方法来告诉情感应用并在每个请求的基础上获取 RTL 样式。他们确实对 React 16 有直接的实现,您可以将每个请求的多个缓存传递给CacheProvider.

但我似乎无法为 Preact 解决这个问题。

一种解决方案可能是为 RTL 提供不同的 webpack 构建,但这将是不必要的开销。

编辑 1:对于希望实现类似功能的任何人,这是我的方法

客户端以及css服务器上的导入:

import stylisRTL from 'stylis-rtl';

import createEmotion from 'create-emotion';

const {
  cx: cxRTL,
  injectGlobal: injectGlobalRTL,
  css: cssRTL,
  cache: cacheRTL,
  keyframes: keyframesRTL
} = createEmotion({
  key: 'c',
  stylisPlugins: [stylisRTL]
});
const {
  cx: cxLTR,
  injectGlobal: injectGlobalLTR,
  css: cssLTR,
  cache: cacheLTR,
  keyframes: keyframesLTR
} = createEmotion({
  key: 'c',
  stylisPlugins: []
});

const runForBoth = (rtlFn, ltrFn) => (...args) => {
//this would be ur store sent in html to check whether it is in rtl or ltr mode
  const isRTL = typeof window !== 'undefined' && window.__PRELOADED_STATE__.shell.RTL;
  let result;
  if (__BROWSER__) {
    if (isRTL) {
      result = rtlFn(...args);
    } else {
      result = ltrFn(...args);
    }
  } else {
    result = ltrFn(...args);
    rtlFn(...args);
  }

  return result;
};

export const cx = runForBoth(cxRTL, cxLTR);
export const injectGlobal = runForBoth(injectGlobalRTL, injectGlobalLTR);
export const css = runForBoth(cssRTL, cssLTR);
export const keyframes = runForBoth(keyframesRTL, keyframesLTR);

export const cacheEmotionLTR = cacheLTR;
export const cacheEmotionRTL = cacheRTL;

对于 SSR:


const { renderStylesToString: renderStylesToStringLTR } = createEmotionServer(cacheEmotionLTR);
const { renderStylesToString: renderStylesToStringRTL } = createEmotionServer(cacheEmotionRTL);

我创建 2 个缓存并根据请求标头决定renderStylesToString使用哪个缓存

我担心的一个问题runForBoth是技术上的错误。但它现在正在工作。

我不想改变cssFn 的导入方式,因为现在我可以使用这个自定义情感导入并在 webpack 中为其命名

标签: javascriptwebpackpreactemotion

解决方案


如果您想根据请求进行此操作,那么您应该创建 2 个情感实例(一个带有插件,一个没有插件)。此外,您必须为每个请求使用正确的实例 - 最简单的方法可能是使用上下文:将情感放在上下文中并从那里使用它而不是从 import 语句。


推荐阅读