Browse Source
* remove unused styles by diffing styles * update README * fix tests * use a polyfill for Object.entriesadd-plugins-support
Naoyuki Kanezawa
8 years ago
committed by
GitHub
12 changed files with 155 additions and 60 deletions
@ -1 +0,0 @@ |
|||
module.exports = require('./dist/inject') |
@ -1,32 +0,0 @@ |
|||
// Ours
|
|||
import memory from './memory' |
|||
|
|||
const isBrowser = typeof window !== 'undefined' |
|||
const tags = {} |
|||
|
|||
export default function inject(id, css) { |
|||
if (isBrowser) { |
|||
// if the tag is already present we ignore it!
|
|||
if (!tags[id]) { |
|||
const el = makeStyleTag(css) |
|||
|
|||
tags[id] = el |
|||
memory[id] = el |
|||
} |
|||
} else { |
|||
memory[id] = css |
|||
} |
|||
} |
|||
|
|||
function makeStyleTag(str) { |
|||
// based on implementation by glamor
|
|||
const tag = document.createElement('style') |
|||
|
|||
tag.type = 'text/css' |
|||
tag.appendChild(document.createTextNode(str)) |
|||
|
|||
const head = document.head || document.getElementsByTagName('head')[0] |
|||
head.appendChild(tag) |
|||
|
|||
return tag |
|||
} |
@ -0,0 +1,56 @@ |
|||
import entries from 'object.entries' |
|||
import memory from './memory' |
|||
|
|||
const {hasOwnProperty} = Object.prototype |
|||
const tags = {} |
|||
let prevStyles = {} |
|||
|
|||
export default typeof window === 'undefined' ? renderOnServer : renderOnClient |
|||
|
|||
function renderOnServer(components) { |
|||
for (const {props} of components) { |
|||
memory[props['data-jsx']] = props.css |
|||
} |
|||
} |
|||
|
|||
function renderOnClient(components) { |
|||
const styles = {} |
|||
for (const c of components) { |
|||
styles[c.props['data-jsx']] = c |
|||
} |
|||
|
|||
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)) |
|||
return [added, removed] |
|||
} |
|||
|
|||
function patch([added, removed]) { |
|||
for (const [id, c] of added) { |
|||
tags[id] = makeStyleTag(c.props.css) |
|||
} |
|||
|
|||
for (const [id] of removed) { |
|||
const t = tags[id] |
|||
delete tags[id] |
|||
t.parentNode.removeChild(t) |
|||
} |
|||
} |
|||
|
|||
function makeStyleTag(str) { |
|||
// based on implementation by glamor
|
|||
const tag = document.createElement('style') |
|||
|
|||
tag.type = 'text/css' |
|||
tag.appendChild(document.createTextNode(str)) |
|||
|
|||
const head = document.head || document.getElementsByTagName('head')[0] |
|||
head.appendChild(tag) |
|||
|
|||
return tag |
|||
} |
@ -0,0 +1,47 @@ |
|||
import {Component} from 'react' |
|||
import render from './render' |
|||
|
|||
export default class extends Component { |
|||
componentWillMount() { |
|||
mount(this) |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
unmount(this) |
|||
} |
|||
|
|||
render() { |
|||
return null |
|||
} |
|||
} |
|||
|
|||
const components = [] |
|||
const update = typeof window === 'undefined' ? doRender : updateOnClient |
|||
let requestId |
|||
|
|||
function mount(component) { |
|||
components.push(component) |
|||
update() |
|||
} |
|||
|
|||
function unmount(component) { |
|||
const i = components.indexOf(component) |
|||
if (i < 0) { |
|||
return |
|||
} |
|||
|
|||
components.splice(i, 1) |
|||
update() |
|||
} |
|||
|
|||
function updateOnClient() { |
|||
window.cancelAnimationFrame(requestId) |
|||
requestId = window.requestAnimationFrame(() => { |
|||
requestId = null |
|||
doRender() |
|||
}) |
|||
} |
|||
|
|||
function doRender() { |
|||
render(components) |
|||
} |
@ -0,0 +1 @@ |
|||
module.exports = require('./dist/style') |
Loading…
Reference in new issue