Browse Source

Make rendering order deterministic (#187)

add-plugins-support
Roland Warmerdam 8 years ago
committed by Giuseppe
parent
commit
81ac6a36ba
  1. 1
      package.json
  2. 34
      src/render.js
  3. 14
      src/server.js
  4. 16
      src/style.js
  5. 67
      yarn.lock

1
package.json

@ -60,7 +60,6 @@
"babylon": "6.14.1",
"convert-source-map": "1.3.0",
"escape-string-regexp": "1.0.5",
"object.entries": "1.0.4",
"source-map": "0.5.6",
"string-hash": "1.1.1",
"stylis": "1.2.3"

34
src/render.js

@ -1,48 +1,40 @@
import entries from 'object.entries'
const {hasOwnProperty} = Object.prototype
const tags = {}
let prevStyles = {}
const tags = new Map()
let prevStyles = new Map()
export default typeof window === 'undefined' ? renderOnServer : renderOnClient
function renderOnServer() {}
function renderOnClient(components) {
const styles = {}
for (const c of components) {
styles[c.props.styleId] = c
}
function renderOnClient(styles) {
patch(diff(prevStyles, styles))
prevStyles = styles
}
function diff(a, b) {
const added = entries(b).filter(([k]) => !hasOwnProperty.call(a, k))
const removed = entries(a).filter(([k]) => !hasOwnProperty.call(b, k))
const added = Array.from(b.entries()).filter(([k]) => !a.has(k))
const removed = Array.from(a.entries()).filter(([k]) => !b.has(k))
return [added, removed]
}
const fromServer = {}
const fromServer = new Map()
function patch([added, removed]) {
for (const [id, c] of added) {
// avoid duplicates from server-rendered markup
if (undefined === fromServer[id]) {
fromServer[id] = document.getElementById(`__jsx-style-${id}`)
if (!fromServer.has(id)) {
fromServer.set(id, document.getElementById(`__jsx-style-${id}`))
}
tags[id] = fromServer[id] || makeStyleTag(c.props.css)
const tag = fromServer.get(id) || makeStyleTag(c.props.css)
tags.set(id, tag)
}
for (const [id] of removed) {
const t = tags[id]
delete tags[id]
const t = tags.get(id)
tags.delete(id)
t.parentNode.removeChild(t)
// avoid checking the DOM later on
fromServer[id] = null
fromServer.delete(id)
}
}

14
src/server.js

@ -1,33 +1,27 @@
import React from 'react'
import {flush} from './style'
const {hasOwnProperty} = Object.prototype
export default function flushToReact() {
const mem = flush()
const arr = []
for (const id in mem) {
if (hasOwnProperty.call(mem, id)) {
for (const [id, c] of mem) {
arr.push(React.createElement('style', {
id: `__jsx-style-${id}`,
// avoid warnings upon render with a key
key: `__jsx-style-${id}`,
dangerouslySetInnerHTML: {
__html: mem[id]
__html: c.props.css
}
}))
}
}
return arr
}
export function flushToHTML() {
const mem = flush()
let html = ''
for (const id in mem) {
if (hasOwnProperty.call(mem, id)) {
html += `<style id="__jsx-style-${id}">${mem[id]}</style>`
}
for (const [id, c] of mem) {
html += `<style id="__jsx-style-${id}">${c.props.css}</style>`
}
return html
}

16
src/style.js

@ -21,15 +21,17 @@ export default class extends Component {
}
}
export function flush() {
const ret = {}
for (const {props} of components) {
ret[props.styleId] = props.css
function componentMap() {
const ret = new Map()
for (const c of components) {
ret.set(c.props.styleId, c)
}
return ret
}
export function flush() {
const ret = componentMap()
components = []
return ret
}
@ -49,5 +51,5 @@ function unmount(component) {
}
function update() {
render(components)
render(componentMap())
}

67
yarn.lock

@ -1122,11 +1122,11 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.21.0, babel-types@^6.22
lodash "^4.2.0"
to-fast-properties "^1.0.1"
babylon@6.14.1, babylon@^6.11.0:
babylon@6.14.1, babylon@^6.1.0, babylon@^6.11.0:
version "6.14.1"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815"
babylon@^6.1.0, babylon@^6.15.0:
babylon@^6.15.0:
version "6.15.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
@ -1530,13 +1530,6 @@ defaults@^1.0.0:
dependencies:
clone "^1.0.2"
define-properties@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
dependencies:
foreach "^2.0.5"
object-keys "^1.0.8"
del@^2.0.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
@ -1639,23 +1632,6 @@ error-ex@^1.2.0:
dependencies:
is-arrayish "^0.2.1"
es-abstract@^1.6.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c"
dependencies:
es-to-primitive "^1.1.1"
function-bind "^1.1.0"
is-callable "^1.1.3"
is-regex "^1.0.3"
es-to-primitive@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
dependencies:
is-callable "^1.1.1"
is-date-object "^1.0.1"
is-symbol "^1.0.1"
es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7:
version "0.10.12"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047"
@ -2072,10 +2048,6 @@ for-own@^0.1.4:
dependencies:
for-in "^0.1.5"
foreach@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@ -2124,7 +2096,7 @@ fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10:
mkdirp ">=0.5 0"
rimraf "2"
function-bind@^1.0.2, function-bind@^1.1.0:
function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
@ -2605,20 +2577,12 @@ is-builtin-module@^1.0.0:
dependencies:
builtin-modules "^1.0.0"
is-callable@^1.1.1, is-callable@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
is-ci@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
dependencies:
ci-info "^1.0.0"
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
is-dotfile@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d"
@ -2763,10 +2727,6 @@ is-redirect@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
is-regex@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.3.tgz#0d55182bddf9f2fde278220aec3a75642c908637"
is-relative@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5"
@ -2787,10 +2747,6 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
is-symbol@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@ -3401,19 +3357,6 @@ object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
object-keys@^1.0.8:
version "1.0.11"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
object.entries@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f"
dependencies:
define-properties "^1.1.2"
es-abstract "^1.6.1"
function-bind "^1.1.0"
has "^1.0.1"
object.omit@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@ -4307,6 +4250,10 @@ strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
stylis@1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.2.3.tgz#57c97b2a71f835b00b92460d751b2aca4355b91b"
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"

Loading…
Cancel
Save