【发布时间】:2019-05-31 12:13:29
【问题描述】:
我有一个 preact SSR 应用程序并使用 Emotion JS 10 进行样式设置。
我想为此添加 RTL 支持,因此使用了 createEmotion 和 createEmotionServer 并使用生成的 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 在技术上是错误的。但它现在正在工作。
我不想改变css Fn 的导入方式,因为现在我可以使用这个自定义情感导入并在 webpack 中为其设置别名
【问题讨论】:
标签: javascript webpack preact emotion