Emotion.js с поддержкой Preact SSR и RTL - PullRequest
1 голос
/ 31 мая 2019

У меня есть приложение preact SSR, и я использовал Emotion JS 10 для стилизации.

Я хотел добавить поддержку RTL, поэтому использовал createEmotion и createEmotionServer и использовал renderStylesToString для визуализации приложения.

Однако при создании createEmotion требуется использование плагинов, для которых я добавил плагин stylis-rtl, но это всегда будет применять стили RTL, в то время как я хочу, чтобы стили RTL применялись на основе каждого запроса.

Я не смог найти способ сказать эмоции для применения и получить стили для RTL для каждого запроса. Они имеют прямую реализацию для React 16, в которой вы можете передавать несколько кэшей для каждого запроса в CacheProvider.

Но я не могу понять это для Preact.

Одним из решений может быть обслуживание различных сборок веб-пакетов для RTL, но это не потребует дополнительных затрат.

РЕДАКТИРОВАТЬ 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;

и для ССР:


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

я создаю 2 кеша и, основываясь на заголовках запросов, решаю, какой renderStylesToString использовать

Единственное, что меня беспокоит, это runForBoth технически неправильно. Но это работает на данный момент.

Я не хотел менять способ css Fn импортируется, так как теперь я могу просто использовать этот импорт пользовательских эмоций и псевдоним его в веб-пакете

1 Ответ

0 голосов
/ 02 июня 2019

Если вы хотите сделать это для каждого запроса, вы должны создать 2 экземпляра эмоций (один с плагином, а другой без него).Кроме того, вам придется использовать правильный экземпляр для каждого запроса - самый простой способ для этого будет, вероятно, с контекстом: поместить эмоции в контекст и использовать его оттуда вместо из оператора импорта.

...