Стабильный реактив для визуализации на стороне сервера

При использовании React для рендеринга компонентов на сервере я замечаю, что атрибуты data-reactid являются случайными. Я понимаю, что это ожидалось. (https://groups.google.com/forum/#!topic/reactjs/ewTN-WOP1w8)

Однако немного удивительно, что эта функциональная структура, в противном случае, вводит такой детерминизм в представлении представления. Это означает, что последовательные визуализации представления с идентичным состоянием создадут другой HTML-код, не позволяя, например, механизму просмотра возвратить "304 Not Modified" или создать надежный ETag. (Я считаю, что такое кэширование можно было бы обрабатывать и на более высоком уровне инфраструктуры.)

Есть ли способ семени генерации идентификатора, чтобы реадиды были детерминированными? Или причина, по которой плохая идея объясняется где-то еще?

Ответ 1

В заключительном комментарии к группе Google Group Бен Алперт говорит:

Для рендеринга сервера важно, чтобы разные обработанные компоненты не имели встречных идентификаторов (даже если они отображаются на разных серверах, например), поэтому мы выбираем их наугад.

Ответ 2

Также недавно подумал об этом (только начал использовать reactjs),

Возможное решение довольно просто - для ETag не требуется генерировать из реального html... - он может быть создан из отображаемых данных.

Итак, вы можете создать его из виртуального dom - просто используйте React.renderComponentToStaticMarkup(…) и сгенерируйте ETag из него...

Или вы можете удалить все reactid из рендеринга html с regexp перед его хэшированием (скорее всего, быстрее, чем отдельный рендер)...

Если вы используете экспресс, это будет примерно так:

var virtualDom = React.createFactory(Handler)({});
var html = React.renderToString(virtualDom);

var etag = app.get('etag fn');
if (etag) {
  etag = etag(React.renderComponentToStaticMarkup(virtualDom), 'utf8');
  etag && res.set('ETag', etag);
}

res.render( ... );

Ответ 3

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

Это можно переопределить в React 0.14.x, если вы готовы мириться со следующим взломом. В своем серверном файле, где вы вызываете ReactDOM.renderToString, поместите это вверху:

// Override the ServerReactRootIndex.createReactRootIndex function
var ServerReactRootIndex = require('react/lib/ServerReactRootIndex');
ServerReactRootIndex.createReactRootIndex = function(){
    return "x"; // Results in an attribute like data-reactid=".x"
};

// Use React as usual
// NB: require('react') must come AFTER overriding ServerReactRootIndex.createReactRootIndex
var React = require('react');

Это не является частью React API, поэтому это может сломаться в ближайшем будущем. Однако сейчас это работает, если вам это абсолютно необходимо. Он также делает атрибут data-react-checksum стабильным для той же рендеринговой DOM.

Если на одной странице несколько компонентов Red React, они ДОЛЖНЫ иметь разные корневые идентификаторы, поэтому вам нужно будет изменить эту функцию для учетной записи для этого.