mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-03-26 09:14:15 +08:00
Rewrite benchmarks app
Reorganizes and rewrites the benchmarks. Each implementation is now self-contained and the benchmarks can be run using a GUI. The benchmarks themselves have been changed so that individual tests render over a shorter time frame and more samples are taken.
This commit is contained in:
@@ -4,48 +4,55 @@ To run these benchmarks:
|
||||
|
||||
```
|
||||
yarn benchmark
|
||||
open ./packages/benchmarks/index.html
|
||||
```
|
||||
|
||||
To run benchmarks for individual implementations append `?<name>,<name>` to the
|
||||
URL, e.g., `?css-modules,react-native-web`.
|
||||
Develop against these benchmarks:
|
||||
|
||||
```
|
||||
yarn compile --watch
|
||||
yarn benchmark --watch
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
These benchmarks are crude approximations of extreme cases that libraries may
|
||||
These benchmarks are approximations of extreme cases that libraries may
|
||||
encounter. The deep and wide tree cases look at the performance of mounting and
|
||||
rendering large trees of styled elements. The Triangle case looks at the
|
||||
rendering large trees of styled elements. The dynamic case looks at the
|
||||
performance of repeated style updates to a large mounted tree. Some libraries
|
||||
must inject new styles for each "dynamic style", whereas others may not.
|
||||
Libraries without support for dynamic styles (i.e., they rely on user-authored
|
||||
inline styles) do not include the `SierpinskiTriangle` benchmark.
|
||||
inline styles) do not include a corresponding benchmark.
|
||||
|
||||
The components used in the render benchmarks are simple enough to be
|
||||
implemented by multiple UI or style libraries. The benchmark implementations
|
||||
and the features of the style libraries are _only approximately equivalent in
|
||||
functionality_.
|
||||
|
||||
No benchmark will run for more than 20 seconds.
|
||||
|
||||
## Results
|
||||
|
||||
Typical render timings*: mean ± two standard deviations.
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) | Triangle (ms) |
|
||||
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Update tree (ms) |
|
||||
| :--- | ---: | ---: | ---: |
|
||||
| `react-native-web@0.2.2` | `89.67` `±28.51` | `167.46` `±27.03` | `65.40` `±19.50` |
|
||||
| `css-modules` | `77.42` `±45.50` | `141.44` `±33.96` | - |
|
||||
| `inline-styles` | `236.25` `±95.57` | `477.01` `±88.30` | `40.95` `±23.53` |
|
||||
| `css-modules` | `15.23` `±04.31` | `21.27` `±07.03` | - |
|
||||
| `react-native-web@0.3.1` | `17.52` `±04.44` | `24.14` `±04.39` | `15.03` `±02.22` |
|
||||
| `inline-styles` | `50.06` `±06.70` | `76.38` `±09.58` | `06.43` `±02.02` |
|
||||
|
||||
Other libraries
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) | Triangle (ms) |
|
||||
| Implementation | Mount deep tree (ms) | Mount wide tree (ms) | Update tree (ms) |
|
||||
| :--- | ---: | ---: | ---: |
|
||||
| `styletron@3.0.0-rc.5` | `83.53` `±33.55` | `153.12` `±39.13` | `56.47` `±24.22` |
|
||||
| `aphrodite@1.2.5` | `88.23` `±31.22` | `164.03` `±34.70` | - |
|
||||
| `glamor@2.20.40` | `110.09` `±34.20` | `182.06` `±50.39` | ‡ |
|
||||
| `emotion@8.0.12` | `103.44` `±32.12` | `204.45` `±41.00` | `110.28` `±26.94` |
|
||||
| `react-jss@8.2.0` | `136.17` `±59.23` | `270.51` `±69.20` | - |
|
||||
| `styled-components@2.3.2` | `217.57` `±51.90` | `437.57` `±65.74` | `76.99` `±41.79` |
|
||||
| `reactxp@0.46.6` | `240.88` `±79.82` | `467.32` `±74.42` | `70.95` `±32.90`|
|
||||
| `radium@0.19.6` | `400.19` `±94.58` | `816.59` `±91.10` | `71.13` `±27.22` |
|
||||
| `aphrodite@1.2.5` | `17.27` `±05.96` | `24.89` `±08.36` | - |
|
||||
| `glamor@2.20.40` | `21.59` `±05.38` | `27.93` `±07.56` | ‡ |
|
||||
| `emotion@8.0.12` | `21.07` `±04.16` | `31.40` `±09.40` | ‡ `19.80` `±13.56` |
|
||||
| `styletron-react@3.0.3` | `23.55` `±05.14` | `34.26` `±07.58` | `10.39` `±02.94` |
|
||||
| `react-jss@8.2.1` | `27.31` `±07.87` | `40.74` `±10.67` | - |
|
||||
| `styled-components@2.4.0` | `43.89` `±06.99` | `63.26` `±09.02` | `16.17` `±03.71` |
|
||||
| `reactxp@0.51.0-alpha.9` | `51.86` `±07.21` | `78.80` `±11.85` | `15.04` `±03.92` |
|
||||
| `radium@0.21.0` | `101.06` `±13.00` | `144.46` `±16.94` | `17.44` `±03.59` |
|
||||
|
||||
These results indicate that render times when using `react-native-web`,
|
||||
`css-modules`, `aphrodite`, and `styletron` are roughly equivalent and
|
||||
@@ -53,4 +60,4 @@ significantly faster than alternatives.
|
||||
|
||||
*MacBook Pro (13-inch, Early 2011); 2.3 GHz Intel Core i5; 8 GB 1333 MHz DDR3. Google Chrome 62.
|
||||
|
||||
‡Glamor essentially crashes the browser tab.
|
||||
‡Glamor essentially crashes the browser tab. Emotion gets slower every iteration.
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Performance tests</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<style>
|
||||
html, body { height: 100%; width: 100%; overflow: hidden; }
|
||||
.root { height: 100%; overflow: hidden; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="root"></div>
|
||||
|
||||
@@ -3,31 +3,30 @@
|
||||
"name": "benchmarks",
|
||||
"version": "0.3.1",
|
||||
"scripts": {
|
||||
"benchmark": "webpack --config ./webpack.config.js && open index.html"
|
||||
"benchmark": "webpack --config ./webpack.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"aphrodite": "^1.2.5",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"aphrodite": "1.2.5",
|
||||
"classnames": "^2.2.5",
|
||||
"d3-scale-chromatic": "^1.1.1",
|
||||
"emotion": "^8.0.12",
|
||||
"glamor": "^2.20.40",
|
||||
"marky": "^1.2.0",
|
||||
"radium": "^0.19.6",
|
||||
"emotion": "8.0.12",
|
||||
"glamor": "2.20.40",
|
||||
"radium": "0.21.0",
|
||||
"react": "^16.2.0",
|
||||
"react-component-benchmark": "^0.0.4",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-jss": "^8.2.0",
|
||||
"react-native-web": "^0.3.1",
|
||||
"reactxp": "^0.46.6",
|
||||
"styled-components": "^2.3.2",
|
||||
"styletron-client": "^3.0.0-rc.5",
|
||||
"styletron-utils": "^3.0.0-rc.3"
|
||||
"react-jss": "8.2.1",
|
||||
"react-native-web": "0.3.1",
|
||||
"reactxp": "0.51.0-alpha.9",
|
||||
"styled-components": "2.4.0",
|
||||
"styletron-client": "3.0.2",
|
||||
"styletron-react": "3.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-react-native-web": "^0.3.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"css-loader": "^0.28.9",
|
||||
"style-loader": "^0.19.1",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-bundle-analyzer": "^2.9.1"
|
||||
"webpack-bundle-analyzer": "^2.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
293
packages/benchmarks/src/app/App.js
Normal file
293
packages/benchmarks/src/app/App.js
Normal file
@@ -0,0 +1,293 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
import Benchmark from './Benchmark';
|
||||
import { Picker, StyleSheet, ScrollView, TouchableOpacity, View } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
import Button from './Button';
|
||||
import { IconClear, IconEye } from './Icons';
|
||||
import ReportCard from './ReportCard';
|
||||
import Text from './Text';
|
||||
import Layout from './Layout';
|
||||
import { colors } from './theme';
|
||||
|
||||
const Overlay = () => <View style={[StyleSheet.absoluteFill, { zIndex: 2 }]} />;
|
||||
|
||||
export default class App extends Component {
|
||||
static displayName = '@app/App';
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
const currentBenchmarkName = Object.keys(props.tests)[0];
|
||||
this.state = {
|
||||
currentBenchmarkName,
|
||||
currentLibraryName: 'react-native-web',
|
||||
status: 'idle',
|
||||
results: []
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { tests } = this.props;
|
||||
const { currentBenchmarkName, status, currentLibraryName, results } = this.state;
|
||||
const currentImplementation = tests[currentBenchmarkName][currentLibraryName];
|
||||
const { Component, Provider, getComponentProps, sampleCount } = currentImplementation;
|
||||
|
||||
return (
|
||||
<Layout
|
||||
actionPanel={
|
||||
<View>
|
||||
<View style={styles.pickers}>
|
||||
<View style={styles.pickerContainer}>
|
||||
<Text style={styles.pickerTitle}>Library</Text>
|
||||
<Text style={{ fontWeight: 'bold' }}>{currentLibraryName}</Text>
|
||||
|
||||
<Picker
|
||||
enabled={status !== 'running'}
|
||||
onValueChange={this._handleChangeLibrary}
|
||||
selectedValue={currentLibraryName}
|
||||
style={styles.picker}
|
||||
>
|
||||
{Object.keys(tests[currentBenchmarkName]).map(libraryName => (
|
||||
<Picker.Item key={libraryName} label={libraryName} value={libraryName} />
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
<View style={{ width: 1, backgroundColor: colors.fadedGray }} />
|
||||
<View style={styles.pickerContainer}>
|
||||
<Text style={styles.pickerTitle}>Benchmark</Text>
|
||||
<Text>{currentBenchmarkName}</Text>
|
||||
<Picker
|
||||
enabled={status !== 'running'}
|
||||
onValueChange={this._handleChangeBenchmark}
|
||||
selectedValue={currentBenchmarkName}
|
||||
style={styles.picker}
|
||||
>
|
||||
{Object.keys(tests).map(test => (
|
||||
<Picker.Item key={test} label={test} value={test} />
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={{ flexDirection: 'row', height: 50 }}>
|
||||
<View style={styles.grow}>
|
||||
<Button
|
||||
onPress={this._handleStart}
|
||||
style={styles.button}
|
||||
title={status === 'running' ? 'Running…' : 'Run'}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{status === 'running' ? <Overlay /> : null}
|
||||
</View>
|
||||
}
|
||||
listPanel={
|
||||
<View style={styles.listPanel}>
|
||||
<View style={styles.grow}>
|
||||
<View style={styles.listBar}>
|
||||
<View style={styles.iconClearContainer}>
|
||||
<TouchableOpacity onPress={this._handleClear}>
|
||||
<IconClear />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
<ScrollView ref={this._setScrollRef} style={styles.grow}>
|
||||
{results.map((r, i) => (
|
||||
<ReportCard
|
||||
benchmarkName={r.benchmarkName}
|
||||
key={i}
|
||||
libraryName={r.libraryName}
|
||||
libraryVersion={r.libraryVersion}
|
||||
mean={r.mean}
|
||||
sampleCount={r.sampleCount}
|
||||
stdDev={r.stdDev}
|
||||
/>
|
||||
))}
|
||||
{status === 'running' ? (
|
||||
<ReportCard
|
||||
benchmarkName={currentBenchmarkName}
|
||||
libraryName={currentLibraryName}
|
||||
/>
|
||||
) : null}
|
||||
</ScrollView>
|
||||
</View>
|
||||
{status === 'running' ? <Overlay /> : null}
|
||||
</View>
|
||||
}
|
||||
viewPanel={
|
||||
<View style={styles.viewPanel}>
|
||||
<View style={styles.iconEyeContainer}>
|
||||
<TouchableOpacity onPress={this._handleVisuallyHideBenchmark}>
|
||||
<IconEye style={styles.iconEye} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Provider>
|
||||
{status === 'running' ? (
|
||||
<React.Fragment>
|
||||
<View ref={this._setBenchWrapperRef}>
|
||||
<Benchmark
|
||||
component={Component}
|
||||
getComponentProps={getComponentProps}
|
||||
onComplete={this._createHandleComplete({
|
||||
sampleCount,
|
||||
benchmarkName: currentBenchmarkName,
|
||||
libraryName: currentLibraryName
|
||||
})}
|
||||
ref={this._setBenchRef}
|
||||
sampleCount={sampleCount}
|
||||
timeout={20000}
|
||||
type={Component.benchmarkType}
|
||||
/>
|
||||
</View>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<Component {...getComponentProps({ cycle: 10 })} />
|
||||
)}
|
||||
</Provider>
|
||||
|
||||
{status === 'running' ? <Overlay /> : null}
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_handleChangeBenchmark = value => {
|
||||
this.setState(() => ({ currentBenchmarkName: value }));
|
||||
};
|
||||
|
||||
_handleChangeLibrary = value => {
|
||||
this.setState(() => ({ currentLibraryName: value }));
|
||||
};
|
||||
|
||||
_handleStart = () => {
|
||||
this.setState(
|
||||
() => ({ status: 'running' }),
|
||||
() => {
|
||||
if (this._shouldHideBenchmark && this._benchWrapperRef) {
|
||||
this._benchWrapperRef.setNativeProps({ style: { opacity: 0 } });
|
||||
}
|
||||
this._benchmarkRef.start();
|
||||
this._scrollToEnd();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// hide the benchmark as it is performed (no flashing on screen)
|
||||
_handleVisuallyHideBenchmark = () => {
|
||||
this._shouldHideBenchmark = !this._shouldHideBenchmark;
|
||||
if (this._benchWrapperRef) {
|
||||
this._benchWrapperRef.setNativeProps({
|
||||
style: { opacity: this._shouldHideBenchmark ? 0 : 1 }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_createHandleComplete = ({ benchmarkName, libraryName, sampleCount }) => results => {
|
||||
this.setState(
|
||||
state => ({
|
||||
results: state.results.concat([
|
||||
{
|
||||
...results,
|
||||
benchmarkName,
|
||||
libraryName,
|
||||
libraryVersion: this.props.tests[benchmarkName][libraryName].version
|
||||
}
|
||||
]),
|
||||
status: 'complete'
|
||||
}),
|
||||
this._scrollToEnd
|
||||
);
|
||||
// console.log(results);
|
||||
// console.log(results.samples.map(sample => sample.elapsed.toFixed(1)).join('\n'));
|
||||
};
|
||||
|
||||
_handleClear = () => {
|
||||
this.setState(() => ({ results: [] }));
|
||||
};
|
||||
|
||||
_setBenchRef = ref => {
|
||||
this._benchmarkRef = ref;
|
||||
};
|
||||
|
||||
_setBenchWrapperRef = ref => {
|
||||
this._benchWrapperRef = ref;
|
||||
};
|
||||
|
||||
_setScrollRef = ref => {
|
||||
this._scrollRef = ref;
|
||||
};
|
||||
|
||||
// scroll the most recent result into view
|
||||
_scrollToEnd = () => {
|
||||
window.requestAnimationFrame(() => {
|
||||
if (this._scrollRef) {
|
||||
this._scrollRef.scrollToEnd();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
viewPanel: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'black'
|
||||
},
|
||||
iconEye: {
|
||||
color: 'white',
|
||||
height: 32
|
||||
},
|
||||
iconEyeContainer: {
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
zIndex: 1
|
||||
},
|
||||
iconClearContainer: {
|
||||
height: '100%',
|
||||
marginLeft: 5
|
||||
},
|
||||
grow: {
|
||||
flex: 1
|
||||
},
|
||||
listPanel: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
marginHorizontal: 'auto'
|
||||
},
|
||||
listBar: {
|
||||
padding: 5,
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
backgroundColor: colors.fadedGray,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.mediumGray,
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
pickers: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
pickerContainer: {
|
||||
flex: 1,
|
||||
padding: 5
|
||||
},
|
||||
pickerTitle: {
|
||||
fontSize: 12,
|
||||
color: colors.deepGray
|
||||
},
|
||||
picker: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
opacity: 0,
|
||||
width: '100%'
|
||||
},
|
||||
button: {
|
||||
borderRadius: 0,
|
||||
fontSize: 32,
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
221
packages/benchmarks/src/app/Benchmark/index.js
Normal file
221
packages/benchmarks/src/app/Benchmark/index.js
Normal file
@@ -0,0 +1,221 @@
|
||||
// @flow
|
||||
/* global $Values */
|
||||
import * as Timing from './timing';
|
||||
import React, { Component } from 'react';
|
||||
import { getMean, getMedian, getStdDev } from './math';
|
||||
|
||||
import type { BenchResultsType, FullSampleTimingType, SampleTimingType } from './types';
|
||||
|
||||
export const BenchmarkType = {
|
||||
MOUNT: 'mount',
|
||||
UPDATE: 'update',
|
||||
UNMOUNT: 'unmount'
|
||||
};
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const shouldRender = (cycle: number, type: $Values<typeof BenchmarkType>): boolean => {
|
||||
switch (type) {
|
||||
// Render every odd iteration (first, third, etc)
|
||||
// Mounts and unmounts the component
|
||||
case BenchmarkType.MOUNT:
|
||||
case BenchmarkType.UNMOUNT:
|
||||
return !((cycle + 1) % 2);
|
||||
// Render every iteration (updates previously rendered module)
|
||||
case BenchmarkType.UPDATE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const shouldRecord = (cycle: number, type: $Values<typeof BenchmarkType>): boolean => {
|
||||
switch (type) {
|
||||
// Record every odd iteration (when mounted: first, third, etc)
|
||||
case BenchmarkType.MOUNT:
|
||||
return !((cycle + 1) % 2);
|
||||
// Record every iteration
|
||||
case BenchmarkType.UPDATE:
|
||||
return true;
|
||||
// Record every even iteration (when unmounted)
|
||||
case BenchmarkType.UNMOUNT:
|
||||
return !(cycle % 2);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const isDone = (
|
||||
cycle: number,
|
||||
sampleCount: number,
|
||||
type: $Values<typeof BenchmarkType>
|
||||
): boolean => {
|
||||
switch (type) {
|
||||
case BenchmarkType.MOUNT:
|
||||
return cycle >= sampleCount * 2 - 1;
|
||||
case BenchmarkType.UPDATE:
|
||||
return cycle >= sampleCount - 1;
|
||||
case BenchmarkType.UNMOUNT:
|
||||
return cycle >= sampleCount * 2;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const sortNumbers = (a: number, b: number): number => a - b;
|
||||
|
||||
type BenchmarkPropsType = {
|
||||
component: typeof React.Component,
|
||||
getComponentProps?: Function,
|
||||
onComplete: (x: BenchResultsType) => void,
|
||||
sampleCount: number,
|
||||
timeout: number,
|
||||
type: $Values<typeof BenchmarkType>
|
||||
};
|
||||
|
||||
type BenchmarkStateType = {
|
||||
getComponentProps: Function,
|
||||
cycle: number,
|
||||
running: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Benchmark
|
||||
* TODO: documentation
|
||||
*/
|
||||
export default class Benchmark extends Component<BenchmarkPropsType, BenchmarkStateType> {
|
||||
_startTime: number;
|
||||
_samples: Array<SampleTimingType>;
|
||||
|
||||
static displayName = 'Benchmark';
|
||||
|
||||
static defaultProps = {
|
||||
getComponentProps: () => emptyObject,
|
||||
sampleCount: 50,
|
||||
timeout: 10000, // 10 seconds
|
||||
type: BenchmarkType.MOUNT
|
||||
};
|
||||
|
||||
static Type = BenchmarkType;
|
||||
|
||||
constructor(props: BenchmarkPropsType, context?: {}) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
getComponentProps: props.getComponentProps,
|
||||
cycle: 0,
|
||||
running: false
|
||||
};
|
||||
this._startTime = 0;
|
||||
this._samples = [];
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: BenchmarkPropsType) {
|
||||
this.setState(state => ({ getComponentProps: nextProps.getComponentProps }));
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps: BenchmarkPropsType, nextState: BenchmarkStateType) {
|
||||
if (nextState.running && !this.state.running) {
|
||||
this._startTime = Timing.now();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { sampleCount, timeout, type } = this.props;
|
||||
const { cycle, running } = this.state;
|
||||
|
||||
if (running && shouldRecord(cycle, type)) {
|
||||
this._samples[cycle].end = Timing.now();
|
||||
}
|
||||
|
||||
if (running) {
|
||||
const now = Timing.now();
|
||||
if (!isDone(cycle, sampleCount, type) && now - this._startTime < timeout) {
|
||||
this._handleCycleComplete();
|
||||
} else {
|
||||
this._handleComplete(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.raf) {
|
||||
window.cancelAnimationFrame(this.raf);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { component: Component, type } = this.props;
|
||||
const { getComponentProps, cycle, running } = this.state;
|
||||
if (running && shouldRecord(cycle, type)) {
|
||||
this._samples[cycle] = { start: Timing.now() };
|
||||
}
|
||||
return running && shouldRender(cycle, type) ? (
|
||||
<Component {...getComponentProps({ cycle })} />
|
||||
) : null;
|
||||
}
|
||||
|
||||
start() {
|
||||
this._samples = [];
|
||||
this.setState(() => ({ running: true, cycle: 0 }));
|
||||
}
|
||||
|
||||
_handleCycleComplete() {
|
||||
const { getComponentProps, type } = this.props;
|
||||
const { cycle } = this.state;
|
||||
|
||||
// Calculate the component props outside of the time recording (render)
|
||||
// so that it doesn't skew results
|
||||
const getNextProps =
|
||||
type === BenchmarkType.UPDATE
|
||||
? obj => ({ ...getComponentProps(obj), 'data-test': cycle })
|
||||
: getComponentProps;
|
||||
|
||||
this.raf = window.requestAnimationFrame(() => {
|
||||
this.setState((state: BenchmarkStateType) => ({
|
||||
getComponentProps: getNextProps,
|
||||
cycle: state.cycle + 1
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
getSamples(): Array<FullSampleTimingType> {
|
||||
return this._samples.reduce(
|
||||
(
|
||||
memo: Array<FullSampleTimingType>,
|
||||
{ start, end: endTime }: SampleTimingType
|
||||
): Array<FullSampleTimingType> => {
|
||||
const end = endTime || 0;
|
||||
memo.push({ start, end, elapsed: end - start });
|
||||
return memo;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
_handleComplete(endTime: number) {
|
||||
const { onComplete } = this.props;
|
||||
const samples = this.getSamples();
|
||||
|
||||
this.setState(() => ({ running: false, cycle: 0 }));
|
||||
|
||||
const runTime = endTime - this._startTime;
|
||||
const sortedElapsedTimes = samples
|
||||
.map(({ elapsed }: { elapsed: number }): number => elapsed)
|
||||
.sort(sortNumbers);
|
||||
const mean = getMean(sortedElapsedTimes);
|
||||
const stdDev = getStdDev(sortedElapsedTimes);
|
||||
|
||||
onComplete({
|
||||
startTime: this._startTime,
|
||||
endTime,
|
||||
runTime,
|
||||
sampleCount: samples.length,
|
||||
samples: samples,
|
||||
max: sortedElapsedTimes[sortedElapsedTimes.length - 1],
|
||||
min: sortedElapsedTimes[0],
|
||||
median: getMedian(sortedElapsedTimes),
|
||||
mean,
|
||||
stdDev
|
||||
});
|
||||
}
|
||||
}
|
||||
27
packages/benchmarks/src/app/Benchmark/math.js
Normal file
27
packages/benchmarks/src/app/Benchmark/math.js
Normal file
@@ -0,0 +1,27 @@
|
||||
// @flow
|
||||
type ValuesType = Array<number>;
|
||||
|
||||
export const getStdDev = (values: ValuesType): number => {
|
||||
const avg = getMean(values);
|
||||
|
||||
const squareDiffs = values.map((value: number) => {
|
||||
const diff = value - avg;
|
||||
return diff * diff;
|
||||
});
|
||||
|
||||
return Math.sqrt(getMean(squareDiffs));
|
||||
};
|
||||
|
||||
export const getMean = (values: ValuesType): number => {
|
||||
const sum = values.reduce((sum: number, value: number) => sum + value, 0);
|
||||
return sum / values.length;
|
||||
};
|
||||
|
||||
export const getMedian = (values: ValuesType): number => {
|
||||
if (values.length === 1) {
|
||||
return values[0];
|
||||
}
|
||||
|
||||
const numbers = values.sort((a: number, b: number) => a - b);
|
||||
return (numbers[(numbers.length - 1) >> 1] + numbers[numbers.length >> 1]) / 2;
|
||||
};
|
||||
18
packages/benchmarks/src/app/Benchmark/timing.js
Normal file
18
packages/benchmarks/src/app/Benchmark/timing.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// @flow
|
||||
|
||||
const NS_PER_MS = 1e6;
|
||||
const MS_PER_S = 1e3;
|
||||
|
||||
// Returns a high resolution time (if possible) in milliseconds
|
||||
export function now(): number {
|
||||
if (window && window.performance) {
|
||||
return window.performance.now();
|
||||
} else if (process && process.hrtime) {
|
||||
const [seconds, nanoseconds] = process.hrtime();
|
||||
const secInMS = seconds * MS_PER_S;
|
||||
const nSecInMS = nanoseconds / NS_PER_MS;
|
||||
return secInMS + nSecInMS;
|
||||
} else {
|
||||
return Date.now();
|
||||
}
|
||||
}
|
||||
28
packages/benchmarks/src/app/Benchmark/types.js
Normal file
28
packages/benchmarks/src/app/Benchmark/types.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// @flow
|
||||
export type BenchResultsType = {
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
runTime: number,
|
||||
sampleCount: number,
|
||||
samples: Array<FullSampleTimingType>,
|
||||
max: number,
|
||||
min: number,
|
||||
median: number,
|
||||
mean: number,
|
||||
stdDev: number,
|
||||
p70: number,
|
||||
p95: number,
|
||||
p99: number
|
||||
};
|
||||
|
||||
export type SampleTimingType = {
|
||||
start: number,
|
||||
end?: number,
|
||||
elapsed?: number
|
||||
};
|
||||
|
||||
export type FullSampleTimingType = {
|
||||
start: number,
|
||||
end: number,
|
||||
elapsed: number
|
||||
};
|
||||
70
packages/benchmarks/src/app/Button.js
Normal file
70
packages/benchmarks/src/app/Button.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import { ColorPropType, StyleSheet, TouchableHighlight, Text } from 'react-native';
|
||||
import React, { Component } from 'react';
|
||||
import { bool, func, string } from 'prop-types';
|
||||
|
||||
export default class Button extends Component<*> {
|
||||
static displayName = '@app/Button';
|
||||
|
||||
static propTypes = {
|
||||
accessibilityLabel: string,
|
||||
color: ColorPropType,
|
||||
disabled: bool,
|
||||
onPress: func.isRequired,
|
||||
style: TouchableHighlight.propTypes.style,
|
||||
testID: string,
|
||||
textStyle: Text.propTypes.style,
|
||||
title: string.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
accessibilityLabel,
|
||||
color,
|
||||
disabled,
|
||||
onPress,
|
||||
style,
|
||||
textStyle,
|
||||
testID,
|
||||
title
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<TouchableHighlight
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole="button"
|
||||
disabled={disabled}
|
||||
onPress={onPress}
|
||||
style={[
|
||||
styles.button,
|
||||
style,
|
||||
color && { backgroundColor: color },
|
||||
disabled && styles.buttonDisabled
|
||||
]}
|
||||
testID={testID}
|
||||
>
|
||||
<Text style={[styles.text, textStyle, disabled && styles.textDisabled]}>{title}</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
backgroundColor: '#2196F3',
|
||||
borderRadius: 0,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
text: {
|
||||
color: '#fff',
|
||||
fontWeight: '500',
|
||||
padding: 8,
|
||||
textAlign: 'center',
|
||||
textTransform: 'uppercase'
|
||||
},
|
||||
buttonDisabled: {
|
||||
backgroundColor: '#dfdfdf'
|
||||
},
|
||||
textDisabled: {
|
||||
color: '#a1a1a1'
|
||||
}
|
||||
});
|
||||
55
packages/benchmarks/src/app/Icons.js
Normal file
55
packages/benchmarks/src/app/Icons.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { createElement, StyleSheet, Text } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
display: 'inline-block',
|
||||
fill: 'currentcolor',
|
||||
height: '1.25em',
|
||||
maxWidth: '100%',
|
||||
position: 'relative',
|
||||
userSelect: 'none',
|
||||
textAlignVertical: 'text-bottom'
|
||||
}
|
||||
});
|
||||
|
||||
const createIcon = children => {
|
||||
const Icon = props =>
|
||||
createElement(
|
||||
'svg',
|
||||
{
|
||||
style: StyleSheet.compose(styles.root, props.style),
|
||||
width: 24,
|
||||
height: 24,
|
||||
viewBox: '0 0 24 24'
|
||||
},
|
||||
children
|
||||
);
|
||||
Icon.propTypes = {
|
||||
style: Text.propTypes.style
|
||||
};
|
||||
return Icon;
|
||||
};
|
||||
|
||||
export const IconClear = createIcon(
|
||||
<Fragment>
|
||||
<path d="M0 0h24v24H0z" id="bounds" opacity="0" />
|
||||
<path d="M12 1.25C6.072 1.25 1.25 6.072 1.25 12S6.072 22.75 12 22.75 22.75 17.928 22.75 12 17.928 1.25 12 1.25zm0 1.5c2.28 0 4.368.834 5.982 2.207L4.957 17.982C3.584 16.368 2.75 14.282 2.75 12c0-5.1 4.15-9.25 9.25-9.25zm0 18.5c-2.28 0-4.368-.834-5.982-2.207L19.043 6.018c1.373 1.614 2.207 3.7 2.207 5.982 0 5.1-4.15 9.25-9.25 9.25z" />
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export const IconEye = createIcon(
|
||||
<Fragment>
|
||||
<path d="M0 0h24v24H0z" id="bounds" opacity="0" />
|
||||
<path d="M14.548 11.634c-1.207 0-2.188-.98-2.188-2.188 0-.664.302-1.25.77-1.653-.363-.097-.736-.165-1.13-.165-2.416 0-4.375 1.96-4.375 4.376S9.585 16.38 12 16.38c2.418 0 4.377-1.96 4.377-4.376 0-.4-.07-.78-.17-1.146-.402.47-.992.776-1.66.776z" />
|
||||
<path d="M12 19.79c-7.228 0-10.12-6.724-10.24-7.01-.254-.466-.254-1.105.035-1.642C1.88 10.923 4.772 4.2 12 4.2s10.12 6.723 10.24 7.01c.254.465.254 1.104-.035 1.64-.085.216-2.977 6.94-10.205 6.94zm0-14c-6.154 0-8.668 5.787-8.772 6.033-.068.135-.068.208-.033.273.137.316 2.65 6.104 8.805 6.104 6.18 0 8.747-5.973 8.772-6.033.07-.136.07-.21.034-.274-.138-.316-2.652-6.103-8.806-6.103z" />
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export const IconCopy = createIcon(
|
||||
<Fragment>
|
||||
<path d="M0 0h24v24H0z" id="bounds" opacity="0" />
|
||||
<path d="M11.47 14.53c.146.146.338.22.53.22s.384-.073.53-.22l5-5c.293-.293.293-.768 0-1.06s-.768-.294-1.06 0l-3.72 3.72V2c0-.414-.337-.75-.75-.75s-.75.336-.75.75v10.19L7.53 8.47c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l5 5z" />
|
||||
<path d="M21.25 13.25c-.414 0-.75.336-.75.75v5.652c0 .437-.355.792-.792.792H4.292c-.437 0-.792-.355-.792-.792V14c0-.414-.336-.75-.75-.75S2 13.586 2 14v5.652c0 1.264 1.028 2.292 2.292 2.292h15.416c1.264 0 2.292-1.028 2.292-2.292V14c0-.414-.336-.75-.75-.75z" />
|
||||
</Fragment>
|
||||
);
|
||||
63
packages/benchmarks/src/app/Layout.js
Normal file
63
packages/benchmarks/src/app/Layout.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { colors } from './theme';
|
||||
import { element } from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
|
||||
export default class Layout extends Component {
|
||||
static propTypes = {
|
||||
actionPanel: element,
|
||||
listPanel: element,
|
||||
viewPanel: element
|
||||
};
|
||||
|
||||
state = {
|
||||
widescreen: false
|
||||
};
|
||||
|
||||
render() {
|
||||
const { viewPanel, actionPanel, listPanel } = this.props;
|
||||
const { widescreen } = this.state;
|
||||
return (
|
||||
<View onLayout={this._handleLayout} style={[styles.root, widescreen && styles.row]}>
|
||||
<View style={widescreen ? styles.grow : styles.stackPanel}>{viewPanel}</View>
|
||||
<View style={styles.grow}>
|
||||
<View style={styles.grow}>{listPanel}</View>
|
||||
<View style={styles.divider} />
|
||||
<View>{actionPanel}</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleLayout = ({ nativeEvent }) => {
|
||||
const { layout } = nativeEvent;
|
||||
const { width } = layout;
|
||||
if (width >= 740) {
|
||||
this.setState(() => ({ widescreen: true }));
|
||||
} else {
|
||||
this.setState(() => ({ widescreen: false }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
height: '100%'
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
divider: {
|
||||
height: 10,
|
||||
backgroundColor: colors.fadedGray,
|
||||
borderBottomWidth: 1,
|
||||
borderTopWidth: 1,
|
||||
borderColor: colors.mediumGray
|
||||
},
|
||||
grow: {
|
||||
flex: 1
|
||||
},
|
||||
stackPanel: {
|
||||
height: '33.33%'
|
||||
}
|
||||
});
|
||||
71
packages/benchmarks/src/app/ReportCard.js
Normal file
71
packages/benchmarks/src/app/ReportCard.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import Text from './Text';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
const fmt = (time: number) => {
|
||||
const i = Number(Math.round(time + 'e2') + 'e-2').toFixed(2);
|
||||
return 10 / i > 1 ? `0${i}` : i;
|
||||
};
|
||||
|
||||
const ReportCard = ({ benchmarkName, libraryName, sampleCount, mean, stdDev, libraryVersion }) => {
|
||||
const sampleCountText = sampleCount != null ? `(${sampleCount})` : '';
|
||||
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<View style={styles.left}>
|
||||
<Text numberOfLines={1} style={styles.bold}>
|
||||
{`${libraryName}${libraryVersion ? '@' + libraryVersion : ''}`}
|
||||
</Text>
|
||||
<Text numberOfLines={1}>
|
||||
{benchmarkName} {sampleCountText}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.right}>
|
||||
{mean ? (
|
||||
<Fragment>
|
||||
<Text style={[styles.bold, styles.monoFont]}>
|
||||
{fmt(mean)} ±{fmt(stdDev)} ms
|
||||
</Text>
|
||||
<Text style={[styles.monoFont, styles.centerText]}>
|
||||
<Text style={styles.smallText}>Σ = </Text>
|
||||
<Text>{Math.round(mean * sampleCount)} ms</Text>
|
||||
</Text>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Text style={styles.bold}>In progress…</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: 5,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#eee'
|
||||
},
|
||||
bold: {
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
smallText: { fontSize: 12 },
|
||||
monoFont: {
|
||||
fontFamily: 'monospace'
|
||||
},
|
||||
centerText: {
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
left: {
|
||||
width: '50%'
|
||||
},
|
||||
right: {
|
||||
flex: 1,
|
||||
alignItems: 'flex-end'
|
||||
}
|
||||
});
|
||||
|
||||
export default ReportCard;
|
||||
34
packages/benchmarks/src/app/Text.js
Normal file
34
packages/benchmarks/src/app/Text.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { bool } from 'prop-types';
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text } from 'react-native';
|
||||
import { colors } from './theme';
|
||||
|
||||
class AppText extends React.Component {
|
||||
static displayName = '@app/Text';
|
||||
|
||||
static contextTypes = {
|
||||
isInAParentText: bool
|
||||
};
|
||||
|
||||
render() {
|
||||
const { style, ...rest } = this.props;
|
||||
const { isInAParentText } = this.context;
|
||||
return <Text {...rest} style={[!isInAParentText && styles.baseText, style]} />;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
baseText: {
|
||||
color: colors.textBlack,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.3125em'
|
||||
}
|
||||
});
|
||||
|
||||
export default AppText;
|
||||
101
packages/benchmarks/src/app/theme.js
Normal file
101
packages/benchmarks/src/app/theme.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import { Dimensions, Platform } from 'react-native';
|
||||
|
||||
const baseFontSize = 14;
|
||||
const baseUnit = 1.3125;
|
||||
|
||||
const createPlatformLength = multiplier =>
|
||||
Platform.select({ web: `${multiplier}rem`, default: multiplier * baseFontSize });
|
||||
|
||||
/**
|
||||
* Exported variables
|
||||
*/
|
||||
|
||||
export const borderRadii = {
|
||||
normal: Platform.select({ web: '0.35rem', default: 5 }),
|
||||
infinite: '9999px'
|
||||
};
|
||||
|
||||
export const breakpoints = {
|
||||
small: 360,
|
||||
medium: 600,
|
||||
large: 800,
|
||||
xLarge: 1100
|
||||
};
|
||||
|
||||
/**
|
||||
* Color palette
|
||||
* DO NOT add new colors unless they are part of @design's color palette.
|
||||
* DO NOT use colors that are not specified here.
|
||||
* source: go/uicolors
|
||||
*/
|
||||
export const colors = {
|
||||
// Primary
|
||||
blue: '#1DA1F2',
|
||||
purple: '#794BC4',
|
||||
green: '#17BF63',
|
||||
yellow: '#FFAD1F',
|
||||
orange: '#F45D22',
|
||||
red: '#E0245E',
|
||||
// Text and interface grays
|
||||
textBlack: '#14171A',
|
||||
deepGray: '#657786',
|
||||
mediumGray: '#AAB8C2',
|
||||
lightGray: '#CCD6DD',
|
||||
fadedGray: '#E6ECF0',
|
||||
faintGray: '#F5F8FA',
|
||||
white: '#FFF',
|
||||
textBlue: '#1B95E0'
|
||||
};
|
||||
|
||||
export const fontFamilies = {
|
||||
normal: 'System',
|
||||
japan: Platform.select({
|
||||
web:
|
||||
'Arial, "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", Meiryo, "MS Pゴシック", "MS PGothic", sans-serif',
|
||||
default: 'System'
|
||||
}),
|
||||
rtl: Platform.select({ web: 'Tahoma, Arial, sans-serif', default: 'System' })
|
||||
};
|
||||
|
||||
export const fontSizes = {
|
||||
// font scale
|
||||
small: createPlatformLength(0.85),
|
||||
normal: createPlatformLength(1),
|
||||
large: createPlatformLength(1.25),
|
||||
xLarge: createPlatformLength(1.5),
|
||||
jumbo: createPlatformLength(2)
|
||||
};
|
||||
|
||||
export const lineHeight = Platform.select({ web: `${baseUnit}` });
|
||||
|
||||
export const spaces = {
|
||||
// This set of space variables should be used for margin, padding
|
||||
micro: createPlatformLength(baseUnit * 0.125),
|
||||
xxSmall: createPlatformLength(baseUnit * 0.25),
|
||||
xSmall: createPlatformLength(baseUnit * 0.5),
|
||||
small: createPlatformLength(baseUnit * 0.75),
|
||||
medium: createPlatformLength(baseUnit),
|
||||
large: createPlatformLength(baseUnit * 1.5),
|
||||
xLarge: createPlatformLength(baseUnit * 2),
|
||||
xxLarge: createPlatformLength(baseUnit * 2.5),
|
||||
jumbo: createPlatformLength(baseUnit * 3)
|
||||
};
|
||||
|
||||
// On web, change the root font-size at specific breakpoints to scale the UI
|
||||
// for larger viewports.
|
||||
if (Platform.OS === 'web' && canUseDOM) {
|
||||
const { medium, large } = breakpoints;
|
||||
const htmlElement = document.documentElement;
|
||||
const setFontSize = width => {
|
||||
const fontSize = width > medium ? (width > large ? '18px' : '17px') : '16px';
|
||||
if (htmlElement) {
|
||||
htmlElement.style.fontSize = fontSize;
|
||||
}
|
||||
};
|
||||
|
||||
setFontSize(Dimensions.get('window').width);
|
||||
Dimensions.addEventListener('change', dimensions => {
|
||||
setFontSize(dimensions.window.width);
|
||||
});
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import * as marky from 'marky';
|
||||
|
||||
const fmt = time => `${Math.round(time * 100) / 100}ms`;
|
||||
|
||||
const measure = (name, fn) => {
|
||||
marky.mark(name);
|
||||
fn();
|
||||
const performanceMeasure = marky.stop(name);
|
||||
return performanceMeasure.duration;
|
||||
};
|
||||
|
||||
const mean = values => {
|
||||
const sum = values.reduce((sum, value) => sum + value, 0);
|
||||
return sum / values.length;
|
||||
};
|
||||
|
||||
const median = values => {
|
||||
if (!Array.isArray(values)) {
|
||||
return 0;
|
||||
}
|
||||
if (values.length === 1) {
|
||||
return values[0];
|
||||
}
|
||||
|
||||
const numbers = [...values].sort((a, b) => a - b);
|
||||
return (numbers[(numbers.length - 1) >> 1] + numbers[numbers.length >> 1]) / 2;
|
||||
};
|
||||
|
||||
const standardDeviation = values => {
|
||||
const avg = mean(values);
|
||||
|
||||
const squareDiffs = values.map(value => {
|
||||
const diff = value - avg;
|
||||
return diff * diff;
|
||||
});
|
||||
|
||||
const meanSquareDiff = mean(squareDiffs);
|
||||
return Math.sqrt(meanSquareDiff);
|
||||
};
|
||||
|
||||
export const log = (name, description, durations) => {
|
||||
const stdDev = standardDeviation(durations);
|
||||
const formattedMean = fmt(mean(durations));
|
||||
const formattedMedian = fmt(median(durations));
|
||||
const formattedStdDev = fmt(stdDev);
|
||||
|
||||
console.groupCollapsed(`${name}\n${formattedMean} ±${fmt(2 * stdDev)}`);
|
||||
description && console.log(description);
|
||||
console.log(`Median: ${formattedMedian}`);
|
||||
console.log(`Mean: ${formattedMean}`);
|
||||
console.log(`Standard deviation: ${formattedStdDev}`);
|
||||
console.log(durations);
|
||||
console.groupEnd();
|
||||
};
|
||||
|
||||
const benchmark = ({ name, description, setup, teardown, task, runs }) => {
|
||||
return new Promise(resolve => {
|
||||
const durations = [];
|
||||
let i = 0;
|
||||
|
||||
setup();
|
||||
teardown();
|
||||
|
||||
const done = () => {
|
||||
log(name, description, durations);
|
||||
resolve();
|
||||
};
|
||||
|
||||
const a = () => {
|
||||
setup();
|
||||
window.requestAnimationFrame(b);
|
||||
};
|
||||
|
||||
const b = () => {
|
||||
const duration = measure('mean', task);
|
||||
durations.push(duration);
|
||||
window.requestAnimationFrame(c);
|
||||
};
|
||||
|
||||
const c = () => {
|
||||
teardown();
|
||||
window.requestAnimationFrame(d);
|
||||
};
|
||||
|
||||
const d = () => {
|
||||
i += 1;
|
||||
if (i < runs) {
|
||||
window.requestAnimationFrame(a);
|
||||
} else {
|
||||
window.requestAnimationFrame(done);
|
||||
}
|
||||
};
|
||||
|
||||
window.requestAnimationFrame(a);
|
||||
});
|
||||
};
|
||||
|
||||
export default benchmark;
|
||||
@@ -1,58 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class DeepTree extends Component {
|
||||
static propTypes = {
|
||||
breadth: PropTypes.number.isRequired,
|
||||
components: PropTypes.object,
|
||||
depth: PropTypes.number.isRequired,
|
||||
id: PropTypes.number.isRequired,
|
||||
wrap: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
/* necessary for reactxp to work without errors */
|
||||
static childContextTypes = {
|
||||
focusManager: PropTypes.object
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
focusManager: {
|
||||
addFocusableComponent() {},
|
||||
removeFocusableComponent() {},
|
||||
restrictFocusWithin() {},
|
||||
removeFocusRestriction() {},
|
||||
limitFocusWithin() {},
|
||||
removeFocusLimitation() {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { breadth, components, depth, id, wrap } = this.props;
|
||||
const { Box } = components;
|
||||
|
||||
let result = (
|
||||
<Box color={id % 3} components={components} layout={depth % 2 === 0 ? 'column' : 'row'} outer>
|
||||
{depth === 0 && <Box color={id % 3 + 3} components={components} fixed />}
|
||||
{depth !== 0 &&
|
||||
Array.from({ length: breadth }).map((el, i) => (
|
||||
<DeepTree
|
||||
breadth={breadth}
|
||||
components={components}
|
||||
depth={depth - 1}
|
||||
id={i}
|
||||
key={i}
|
||||
wrap={wrap}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
for (let i = 0; i < wrap; i++) {
|
||||
result = <Box components={components}>{result}</Box>;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export default DeepTree;
|
||||
@@ -1,17 +1,22 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { BenchmarkType } from 'react-component-benchmark';
|
||||
import { number, object } from 'prop-types';
|
||||
import React from 'react';
|
||||
import { interpolatePurples, interpolateBuPu, interpolateRdPu } from 'd3-scale-chromatic';
|
||||
|
||||
const targetSize = 25;
|
||||
const targetSize = 10;
|
||||
|
||||
class SierpinskiTriangle extends React.Component {
|
||||
static displayName = 'SierpinskiTriangle';
|
||||
|
||||
static benchmarkType = BenchmarkType.UPDATE;
|
||||
|
||||
static propTypes = {
|
||||
Dot: PropTypes.node,
|
||||
depth: PropTypes.number,
|
||||
renderCount: PropTypes.number,
|
||||
s: PropTypes.number,
|
||||
x: PropTypes.number,
|
||||
y: PropTypes.number
|
||||
components: object,
|
||||
depth: number,
|
||||
renderCount: number,
|
||||
s: number,
|
||||
x: number,
|
||||
y: number
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@@ -20,64 +25,66 @@ class SierpinskiTriangle extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { x, y, depth, renderCount, Dot } = this.props;
|
||||
const { components, x, y, depth, renderCount } = this.props;
|
||||
let { s } = this.props;
|
||||
const { Dot } = components;
|
||||
|
||||
if (s <= targetSize) {
|
||||
let fn;
|
||||
switch (depth) {
|
||||
case 1:
|
||||
fn = interpolatePurples;
|
||||
break;
|
||||
case 2:
|
||||
fn = interpolateBuPu;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
fn = interpolateRdPu;
|
||||
if (Dot) {
|
||||
if (s <= targetSize) {
|
||||
let fn;
|
||||
switch (depth) {
|
||||
case 1:
|
||||
fn = interpolatePurples;
|
||||
break;
|
||||
case 2:
|
||||
fn = interpolateBuPu;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
fn = interpolateRdPu;
|
||||
}
|
||||
|
||||
// introduce randomness to ensure that repeated runs don't produce the same colors
|
||||
const color = fn(renderCount * Math.random() / 20);
|
||||
return (
|
||||
<Dot color={color} size={targetSize} x={x - targetSize / 2} y={y - targetSize / 2} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Dot
|
||||
color={fn(renderCount / 20)}
|
||||
size={targetSize}
|
||||
x={x - targetSize / 2}
|
||||
y={y - targetSize / 2}
|
||||
s /= 2;
|
||||
|
||||
return [
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={1}
|
||||
key={1}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x}
|
||||
y={y - s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={2}
|
||||
key={2}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x - s}
|
||||
y={y + s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
components={components}
|
||||
depth={3}
|
||||
key={3}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x + s}
|
||||
y={y + s / 2}
|
||||
/>
|
||||
);
|
||||
];
|
||||
} else {
|
||||
return <span style={{ color: 'white' }}>No implementation available</span>;
|
||||
}
|
||||
|
||||
s /= 2;
|
||||
|
||||
return [
|
||||
<SierpinskiTriangle
|
||||
Dot={Dot}
|
||||
depth={1}
|
||||
key={1}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x}
|
||||
y={y - s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
Dot={Dot}
|
||||
depth={2}
|
||||
key={2}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x - s}
|
||||
y={y + s / 2}
|
||||
/>,
|
||||
<SierpinskiTriangle
|
||||
Dot={Dot}
|
||||
depth={3}
|
||||
key={3}
|
||||
renderCount={renderCount}
|
||||
s={s}
|
||||
x={x + s}
|
||||
y={y + s / 2}
|
||||
/>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
45
packages/benchmarks/src/cases/Tree.js
Normal file
45
packages/benchmarks/src/cases/Tree.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { BenchmarkType } from 'react-component-benchmark';
|
||||
import { number, object } from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class Tree extends Component {
|
||||
static displayName = 'Tree';
|
||||
|
||||
static benchmarkType = BenchmarkType.MOUNT;
|
||||
|
||||
static propTypes = {
|
||||
breadth: number.isRequired,
|
||||
components: object,
|
||||
depth: number.isRequired,
|
||||
id: number.isRequired,
|
||||
wrap: number.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
const { breadth, components, depth, id, wrap } = this.props;
|
||||
const { Box } = components;
|
||||
|
||||
let result = (
|
||||
<Box color={id % 3} layout={depth % 2 === 0 ? 'column' : 'row'} outer>
|
||||
{depth === 0 && <Box color={id % 3 + 3} fixed />}
|
||||
{depth !== 0 &&
|
||||
Array.from({ length: breadth }).map((el, i) => (
|
||||
<Tree
|
||||
breadth={breadth}
|
||||
components={components}
|
||||
depth={depth - 1}
|
||||
id={i}
|
||||
key={i}
|
||||
wrap={wrap}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
for (let i = 0; i < wrap; i++) {
|
||||
result = <Box>{result}</Box>;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export default Tree;
|
||||
@@ -1,14 +0,0 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import NestedTree from './NestedTree';
|
||||
import React from 'react';
|
||||
|
||||
const renderDeepTree = (label, components) =>
|
||||
createRenderBenchmark({
|
||||
name: `[${label}] Deep tree`,
|
||||
runs: 20,
|
||||
getElement() {
|
||||
return <NestedTree breadth={3} components={components} depth={6} id={0} wrap={1} />;
|
||||
}
|
||||
});
|
||||
|
||||
export default renderDeepTree;
|
||||
@@ -1,112 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import SierpinskiTriangle from './SierpinskiTriangle';
|
||||
import { log } from '../benchmark';
|
||||
|
||||
const node = document.querySelector('.root');
|
||||
|
||||
let runs = 20;
|
||||
|
||||
class Speedometer extends React.Component {
|
||||
/* necessary for reactxp to work without errors */
|
||||
static childContextTypes = {
|
||||
focusManager: PropTypes.object
|
||||
};
|
||||
getChildContext() {
|
||||
return {
|
||||
focusManager: {
|
||||
addFocusableComponent() {},
|
||||
removeFocusableComponent() {},
|
||||
restrictFocusWithin() {},
|
||||
removeFocusRestriction() {},
|
||||
limitFocusWithin() {},
|
||||
removeFocusLimitation() {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
Dot: PropTypes.node.isRequired,
|
||||
description: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
onComplete: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
state = { renderCount: -1 };
|
||||
|
||||
async componentDidMount() {
|
||||
const durations = [];
|
||||
|
||||
while ((runs -= 1)) {
|
||||
const prev = window.performance.now();
|
||||
await new Promise(resolve => {
|
||||
this.raf = window.requestAnimationFrame(() => {
|
||||
this.setState({ renderCount: this.state.renderCount + 1 }, () => {
|
||||
const now = window.performance.now();
|
||||
durations.push(now - prev);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const { description, name } = this.props;
|
||||
log(name, description, durations);
|
||||
|
||||
runs = 20;
|
||||
this.props.onComplete();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.cancelAnimationFrame(this.raf);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={styles.wrapper}>
|
||||
<SierpinskiTriangle
|
||||
Dot={this.props.Dot}
|
||||
renderCount={this.state.renderCount}
|
||||
s={1000}
|
||||
x={0}
|
||||
y={0}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = {
|
||||
wrapper: {
|
||||
position: 'absolute',
|
||||
transformOrigin: '0 0',
|
||||
left: '50%',
|
||||
top: '50%',
|
||||
width: '10px',
|
||||
height: '10px',
|
||||
backgroundColor: '#eee',
|
||||
transform: 'scale(0.33)'
|
||||
}
|
||||
};
|
||||
|
||||
const renderSierpinskiTriangle = (name, { Dot }) => () => {
|
||||
return new Promise(resolve => {
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
ReactDOM.render(
|
||||
<Speedometer
|
||||
Dot={Dot}
|
||||
description="Dynamic styles"
|
||||
name={`[${name}] Triangle`}
|
||||
onComplete={() => {
|
||||
ReactDOM.unmountComponentAtNode(node);
|
||||
resolve();
|
||||
}}
|
||||
/>,
|
||||
node
|
||||
);
|
||||
/* eslint-enable react/jsx-no-bind */
|
||||
});
|
||||
};
|
||||
|
||||
export default renderSierpinskiTriangle;
|
||||
@@ -1,112 +0,0 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import React from 'react';
|
||||
|
||||
const tweet1 = {
|
||||
favorite_count: 30,
|
||||
favorited: true,
|
||||
id: '834889712556875776',
|
||||
lang: 'en',
|
||||
retweet_count: 6,
|
||||
retweeted: false,
|
||||
textParts: [
|
||||
{
|
||||
prefix: '',
|
||||
text: 'Living burrito to burrito '
|
||||
},
|
||||
{
|
||||
emoji: 'https://abs-0.twimg.com/emoji/v2/svg/1f32f.svg',
|
||||
isEmoji: true,
|
||||
prefix: '',
|
||||
text: '🌯'
|
||||
},
|
||||
{
|
||||
emoji: 'https://abs-0.twimg.com/emoji/v2/svg/1f32f.svg',
|
||||
isEmoji: true,
|
||||
prefix: '',
|
||||
text: '🌯'
|
||||
},
|
||||
{
|
||||
emoji: 'https://abs-0.twimg.com/emoji/v2/svg/1f32f.svg',
|
||||
isEmoji: true,
|
||||
prefix: '',
|
||||
text: '🌯'
|
||||
}
|
||||
],
|
||||
timestamp: 'Feb 23',
|
||||
user: {
|
||||
fullName: 'Nicolas',
|
||||
screenName: 'necolas',
|
||||
profileImageUrl: 'https://pbs.twimg.com/profile_images/804365942360719360/dQnPejph_normal.jpg'
|
||||
}
|
||||
};
|
||||
|
||||
const tweet2 = {
|
||||
favorite_count: 84,
|
||||
favorited: false,
|
||||
id: '730896800060579840',
|
||||
lang: 'en',
|
||||
media: {
|
||||
source: {
|
||||
uri: 'https://pbs.twimg.com/media/CiSqvsJVEAAtLZ1.jpg',
|
||||
width: 600,
|
||||
height: 338
|
||||
}
|
||||
},
|
||||
retweet_count: 4,
|
||||
retweeted: true,
|
||||
textParts: [
|
||||
{
|
||||
prefix: '',
|
||||
text: 'Presenting '
|
||||
},
|
||||
{
|
||||
displayUrl: 'mobile.twitter.com',
|
||||
expandedUrl: 'https://mobile.twitter.com',
|
||||
isEntity: true,
|
||||
isUrl: true,
|
||||
linkRelation: 'nofollow',
|
||||
prefix: '',
|
||||
text: '',
|
||||
textDirection: 'ltr',
|
||||
url: 'https://t.co/4hRCAxiUUG'
|
||||
},
|
||||
{
|
||||
prefix: '',
|
||||
text: ' with '
|
||||
},
|
||||
{
|
||||
isEntity: true,
|
||||
isMention: true,
|
||||
prefix: '@',
|
||||
text: 'davidbellona',
|
||||
textDirection: 'ltr',
|
||||
url: '/davidbellona'
|
||||
},
|
||||
{
|
||||
prefix: '',
|
||||
text: " at Twitter's all hands meeting "
|
||||
}
|
||||
],
|
||||
timestamp: 'May 12',
|
||||
user: {
|
||||
fullName: 'Nicolas',
|
||||
screenName: 'necolas',
|
||||
profileImageUrl: 'https://pbs.twimg.com/profile_images/804365942360719360/dQnPejph_normal.jpg'
|
||||
}
|
||||
};
|
||||
|
||||
const renderTweet = (label, { Tweet }) =>
|
||||
createRenderBenchmark({
|
||||
name: `[${label}] Tweet`,
|
||||
runs: 10,
|
||||
getElement() {
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Tweet tweet={tweet1} />
|
||||
<Tweet tweet={tweet2} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default renderTweet;
|
||||
@@ -1,14 +0,0 @@
|
||||
import createRenderBenchmark from '../createRenderBenchmark';
|
||||
import NestedTree from './NestedTree';
|
||||
import React from 'react';
|
||||
|
||||
const renderWideTree = (label, components) =>
|
||||
createRenderBenchmark({
|
||||
name: `[${label}] Wide tree`,
|
||||
runs: 20,
|
||||
getElement() {
|
||||
return <NestedTree breadth={10} components={components} depth={3} id={0} wrap={4} />;
|
||||
}
|
||||
});
|
||||
|
||||
export default renderWideTree;
|
||||
@@ -1,24 +0,0 @@
|
||||
import benchmark from './benchmark';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
const node = document.querySelector('.root');
|
||||
|
||||
const createRenderBenchmark = ({ description, getElement, name, runs }) => () => {
|
||||
const setup = () => {};
|
||||
const teardown = () => {
|
||||
ReactDOM.unmountComponentAtNode(node);
|
||||
};
|
||||
|
||||
return benchmark({
|
||||
name,
|
||||
description,
|
||||
runs,
|
||||
setup,
|
||||
teardown,
|
||||
task: () => {
|
||||
ReactDOM.render(getElement(), node);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default createRenderBenchmark;
|
||||
38
packages/benchmarks/src/impl.js
Normal file
38
packages/benchmarks/src/impl.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* @flow */
|
||||
|
||||
import { type Component } from 'react';
|
||||
import packageJson from '../package.json';
|
||||
|
||||
const context = require.context('./implementations/', true, /index\.js$/);
|
||||
const { dependencies } = packageJson;
|
||||
|
||||
type ComponentsType = {
|
||||
Box: Component,
|
||||
Dot: Component,
|
||||
Provider: Component,
|
||||
View: Component
|
||||
};
|
||||
|
||||
type ImplementationType = {
|
||||
components: ComponentsType,
|
||||
name: string,
|
||||
version: string
|
||||
};
|
||||
|
||||
const toImplementations = (context: Object): Array<ImplementationType> =>
|
||||
context.keys().map(path => {
|
||||
const components = context(path).default;
|
||||
const name = path.split('/')[1];
|
||||
const version = dependencies[name] || '';
|
||||
return { components, name, version };
|
||||
});
|
||||
|
||||
const toObject = (impls: Array<ImplementationType>): Object =>
|
||||
impls.reduce((acc, impl) => {
|
||||
acc[impl.name] = impl;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const map = toObject(toImplementations(context));
|
||||
|
||||
export default map;
|
||||
@@ -17,32 +17,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,7 +1,9 @@
|
||||
import Box from './Box';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,4 +1,5 @@
|
||||
.outer {
|
||||
align-self: flex-start;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
@@ -7,30 +8,30 @@
|
||||
}
|
||||
|
||||
.color0 {
|
||||
background-color: #222;
|
||||
background-color: #14171A;
|
||||
}
|
||||
|
||||
.color1 {
|
||||
background-color: #666;
|
||||
background-color: #AAB8C2;
|
||||
}
|
||||
|
||||
.color2 {
|
||||
background-color: #999;
|
||||
background-color: #E6ECF0;
|
||||
}
|
||||
|
||||
.color3 {
|
||||
background-color: blue;
|
||||
background-color: #FFAD1F;
|
||||
}
|
||||
|
||||
.color4 {
|
||||
background-color: orange;
|
||||
background-color: #F45D22;
|
||||
}
|
||||
|
||||
.color5 {
|
||||
background-color: red;
|
||||
background-color: #E0245E;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import Box from './Box';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -16,32 +16,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ const Dot = ({ size, x, y, children, color }) => (
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
@@ -25,7 +25,8 @@ const styles = {
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -16,32 +16,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ const Dot = ({ size, x, y, children, color }) => (
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
@@ -25,7 +25,8 @@ const styles = {
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -16,32 +16,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ const Dot = ({ size, x, y, children, color }) => (
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -27,7 +27,8 @@ const styles = {
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -17,32 +17,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ const Dot = ({ size, x, y, children, color }) => (
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
}
|
||||
]}
|
||||
>
|
||||
@@ -28,7 +28,8 @@ const styles = {
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -18,32 +18,33 @@ const Box = ({ classes, color, fixed = false, layout = 'column', outer = false,
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
};
|
||||
|
||||
2
packages/benchmarks/src/implementations/react-jss/Provider.js
vendored
Normal file
2
packages/benchmarks/src/implementations/react-jss/Provider.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,7 +1,9 @@
|
||||
import Box from './Box';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
@@ -16,32 +16,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ const Dot = ({ size, x, y, children, color }) =>
|
||||
borderRightWidth: size / 2,
|
||||
borderBottomWidth: size / 2,
|
||||
borderLeftWidth: size / 2,
|
||||
left: x,
|
||||
top: y
|
||||
marginLeft: x,
|
||||
marginTop: y
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -25,7 +25,8 @@ const styles = StyleSheet.create({
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: [{ translateX: '50%' }, { translateY: '50%' }]
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
2
packages/benchmarks/src/implementations/react-native-web/Provider.js
vendored
Normal file
2
packages/benchmarks/src/implementations/react-native-web/Provider.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { View } from 'react-native';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import { View } from 'react-native';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -16,32 +16,33 @@ const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other
|
||||
|
||||
const styles = {
|
||||
outer: Styles.createViewStyle({
|
||||
alignSelf: 'flex-start',
|
||||
padding: 4
|
||||
}),
|
||||
row: Styles.createViewStyle({
|
||||
flexDirection: 'row'
|
||||
}),
|
||||
color0: Styles.createViewStyle({
|
||||
backgroundColor: '#222'
|
||||
backgroundColor: '#14171A'
|
||||
}),
|
||||
color1: Styles.createViewStyle({
|
||||
backgroundColor: '#666'
|
||||
backgroundColor: '#AAB8C2'
|
||||
}),
|
||||
color2: Styles.createViewStyle({
|
||||
backgroundColor: '#999'
|
||||
backgroundColor: '#E6ECF0'
|
||||
}),
|
||||
color3: Styles.createViewStyle({
|
||||
backgroundColor: 'blue'
|
||||
backgroundColor: '#FFAD1F'
|
||||
}),
|
||||
color4: Styles.createViewStyle({
|
||||
backgroundColor: 'orange'
|
||||
backgroundColor: '#F45D22'
|
||||
}),
|
||||
color5: Styles.createViewStyle({
|
||||
backgroundColor: 'red'
|
||||
backgroundColor: '#E0245E'
|
||||
}),
|
||||
fixed: Styles.createViewStyle({
|
||||
width: 20,
|
||||
height: 20
|
||||
width: 6,
|
||||
height: 6
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ const Dot = ({ size, x, y, children, color }) => (
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
}
|
||||
]}
|
||||
/>
|
||||
@@ -27,7 +27,8 @@ const styles = {
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
31
packages/benchmarks/src/implementations/reactxp/Provider.js
Normal file
31
packages/benchmarks/src/implementations/reactxp/Provider.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import { object } from 'prop-types';
|
||||
import { View } from 'reactxp';
|
||||
|
||||
class Provider extends React.Component {
|
||||
/* this mock context is necessary for reactxp to work without errors… ¯\_(ツ)_/¯ */
|
||||
|
||||
static childContextTypes = {
|
||||
focusManager: object
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
focusManager: {
|
||||
addFocusableComponent() {},
|
||||
removeFocusableComponent() {},
|
||||
restrictFocusWithin() {},
|
||||
removeFocusRestriction() {},
|
||||
limitFocusWithin() {},
|
||||
removeFocusLimitation() {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <View style={{ overflow: 'visible' }}>{this.props.children}</View>;
|
||||
}
|
||||
}
|
||||
|
||||
export default Provider;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import { View } from 'reactxp';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -4,28 +4,28 @@ import View from './View';
|
||||
const getColor = color => {
|
||||
switch (color) {
|
||||
case 0:
|
||||
return '#222';
|
||||
return '#14171A';
|
||||
case 1:
|
||||
return '#666';
|
||||
return '#AAB8C2';
|
||||
case 2:
|
||||
return '#999';
|
||||
return '#E6ECF0';
|
||||
case 3:
|
||||
return 'blue';
|
||||
return '#FFAD1F';
|
||||
case 4:
|
||||
return 'orange';
|
||||
return '#F45D22';
|
||||
case 5:
|
||||
return 'red';
|
||||
return '#E0245E';
|
||||
default:
|
||||
return 'transparent';
|
||||
}
|
||||
};
|
||||
|
||||
const Box = styled(View)`
|
||||
align-self: flex-start;
|
||||
flex-direction: ${props => (props.layout === 'column' ? 'column' : 'row')};
|
||||
padding: ${props => (props.outer ? '4px' : '0')};
|
||||
height: ${props => (props.fixed ? '20px' : 'auto')};
|
||||
width: ${props => (props.fixed ? '20px' : 'auto')};
|
||||
background-color: ${props => getColor(props.color)};
|
||||
${props => props.fixed && 'height:6px;'} ${props =>
|
||||
props.fixed && 'width:6px;'} background-color: ${props => getColor(props.color)};
|
||||
`;
|
||||
|
||||
export default Box;
|
||||
|
||||
@@ -4,8 +4,8 @@ import View from './View';
|
||||
|
||||
const Dot = styled(View).attrs({
|
||||
style: props => ({
|
||||
left: `${props.x}px`,
|
||||
top: `${props.y}px`,
|
||||
marginLeft: `${props.x}px`,
|
||||
marginTop: `${props.y}px`,
|
||||
borderRightWidth: `${props.size / 2}px`,
|
||||
borderBottomWidth: `${props.size / 2}px`,
|
||||
borderLeftWidth: `${props.size / 2}px`,
|
||||
@@ -19,6 +19,7 @@ const Dot = styled(View).attrs({
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-top-width: 0;
|
||||
transform: translate(50%, 50%);
|
||||
`;
|
||||
|
||||
export default Dot;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
import View from './View';
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { styled } from 'styletron-react';
|
||||
import View from './View';
|
||||
|
||||
const Box = styled(
|
||||
View,
|
||||
({ color, fixed = false, layout = 'column', outer = false, ...other }) => ({
|
||||
...styles[`color${color}`],
|
||||
...(fixed && styles.fixed),
|
||||
...(layout === 'row' && styles.row),
|
||||
...(outer && styles.outer)
|
||||
})
|
||||
);
|
||||
|
||||
const styles = {
|
||||
outer: {
|
||||
alignSelf: 'flex-start',
|
||||
padding: '4px'
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
color0: {
|
||||
backgroundColor: '#14171A'
|
||||
},
|
||||
color1: {
|
||||
backgroundColor: '#AAB8C2'
|
||||
},
|
||||
color2: {
|
||||
backgroundColor: '#E6ECF0'
|
||||
},
|
||||
color3: {
|
||||
backgroundColor: '#FFAD1F'
|
||||
},
|
||||
color4: {
|
||||
backgroundColor: '#F45D22'
|
||||
},
|
||||
color5: {
|
||||
backgroundColor: '#E0245E'
|
||||
},
|
||||
fixed: {
|
||||
width: '6px',
|
||||
height: '6px'
|
||||
}
|
||||
};
|
||||
|
||||
export default Box;
|
||||
@@ -0,0 +1,25 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { styled } from 'styletron-react';
|
||||
|
||||
const Dot = styled('div', ({ size, x, y, children, color }) => ({
|
||||
...staticStyle,
|
||||
borderBottomColor: color,
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
marginLeft: `${x}px`,
|
||||
marginTop: `${y}px`
|
||||
}));
|
||||
|
||||
const staticStyle = {
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
width: 0,
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0,
|
||||
transform: 'translate(50%, 50%)'
|
||||
};
|
||||
|
||||
export default Dot;
|
||||
@@ -0,0 +1,19 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react';
|
||||
import Styletron from 'styletron-client';
|
||||
import { StyletronProvider } from 'styletron-react';
|
||||
import View from './View';
|
||||
|
||||
const styletron = new Styletron();
|
||||
|
||||
class Provider extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<StyletronProvider styletron={styletron}>
|
||||
<View>{this.props.children}</View>
|
||||
</StyletronProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Provider;
|
||||
@@ -0,0 +1,26 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { styled } from 'styletron-react';
|
||||
|
||||
const View = styled('div', ({ style }) => ({
|
||||
...viewStyle,
|
||||
style
|
||||
}));
|
||||
|
||||
const viewStyle = {
|
||||
alignItems: 'stretch',
|
||||
borderWidth: '0px',
|
||||
borderStyle: 'solid',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexBasis: 'auto',
|
||||
flexDirection: 'column',
|
||||
flexShrink: '0',
|
||||
margin: '0px',
|
||||
padding: '0px',
|
||||
position: 'relative',
|
||||
// fix flexbox bugs
|
||||
minHeight: '0px',
|
||||
minWidth: '0px'
|
||||
};
|
||||
|
||||
export default View;
|
||||
@@ -1,9 +1,11 @@
|
||||
import Box from './Box';
|
||||
import Dot from './Dot';
|
||||
import Provider from './Provider';
|
||||
import View from './View';
|
||||
|
||||
export default {
|
||||
Box,
|
||||
Dot,
|
||||
Provider,
|
||||
View
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { injectStylePrefixed } from 'styletron-utils';
|
||||
import React from 'react';
|
||||
import View, { styletron } from './View';
|
||||
|
||||
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
|
||||
<View
|
||||
{...other}
|
||||
style={[
|
||||
styles[`color${color}`],
|
||||
fixed && styles.fixed,
|
||||
layout === 'row' && styles.row,
|
||||
outer && styles.outer
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
const styles = {
|
||||
outer: injectStylePrefixed(styletron, {
|
||||
padding: '4px'
|
||||
}),
|
||||
row: injectStylePrefixed(styletron, {
|
||||
flexDirection: 'row'
|
||||
}),
|
||||
color0: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#222'
|
||||
}),
|
||||
color1: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#666'
|
||||
}),
|
||||
color2: injectStylePrefixed(styletron, {
|
||||
backgroundColor: '#999'
|
||||
}),
|
||||
color3: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'blue'
|
||||
}),
|
||||
color4: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'orange'
|
||||
}),
|
||||
color5: injectStylePrefixed(styletron, {
|
||||
backgroundColor: 'red'
|
||||
}),
|
||||
fixed: injectStylePrefixed(styletron, {
|
||||
width: '20px',
|
||||
height: '20px'
|
||||
})
|
||||
};
|
||||
|
||||
export default Box;
|
||||
@@ -1,37 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
import { injectStylePrefixed } from 'styletron-utils';
|
||||
import { styletron } from './View';
|
||||
|
||||
const Dot = ({ size, x, y, children, color }) => (
|
||||
<div
|
||||
className={classnames(
|
||||
styles.root,
|
||||
injectStylePrefixed(styletron, {
|
||||
borderBottomColor: color,
|
||||
borderRightWidth: `${size / 2}px`,
|
||||
borderBottomWidth: `${size / 2}px`,
|
||||
borderLeftWidth: `${size / 2}px`,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
})
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const styles = {
|
||||
root: injectStylePrefixed(styletron, {
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
width: 0,
|
||||
height: 0,
|
||||
borderColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderTopWidth: 0
|
||||
})
|
||||
};
|
||||
|
||||
export default Dot;
|
||||
@@ -1,33 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import Styletron from 'styletron-client';
|
||||
import { injectStylePrefixed } from 'styletron-utils';
|
||||
import React from 'react';
|
||||
|
||||
export const styletron = new Styletron();
|
||||
|
||||
class View extends React.Component {
|
||||
render() {
|
||||
const { style, ...other } = this.props;
|
||||
return <div {...other} className={classnames(viewStyle, ...style)} />;
|
||||
}
|
||||
}
|
||||
|
||||
const viewStyle = injectStylePrefixed(styletron, {
|
||||
alignItems: 'stretch',
|
||||
borderWidth: '0px',
|
||||
borderStyle: 'solid',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexBasis: 'auto',
|
||||
flexDirection: 'column',
|
||||
flexShrink: '0',
|
||||
margin: '0px',
|
||||
padding: '0px',
|
||||
position: 'relative',
|
||||
// fix flexbox bugs
|
||||
minHeight: '0px',
|
||||
minWidth: '0px'
|
||||
});
|
||||
|
||||
export default View;
|
||||
@@ -1,97 +1,56 @@
|
||||
import aphrodite from './implementations/aphrodite';
|
||||
import cssModules from './implementations/css-modules';
|
||||
import emotion from './implementations/emotion';
|
||||
import jss from './implementations/jss';
|
||||
import glamor from './implementations/glamor';
|
||||
import inlineStyles from './implementations/inline-styles';
|
||||
import radium from './implementations/radium';
|
||||
import reactNativeWeb from './implementations/react-native-web';
|
||||
import reactxp from './implementations/reactxp';
|
||||
import styledComponents from './implementations/styled-components';
|
||||
import styletron from './implementations/styletron';
|
||||
import App from './app/App';
|
||||
import impl from './impl';
|
||||
import Tree from './cases/Tree';
|
||||
import SierpinskiTriangle from './cases/SierpinskiTriangle';
|
||||
|
||||
import renderDeepTree from './cases/renderDeepTree';
|
||||
import renderSierpinskiTriangle from './cases/renderSierpinskiTriangle';
|
||||
import renderWideTree from './cases/renderWideTree';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
const testMatrix = {
|
||||
'inline-styles': [
|
||||
() => renderDeepTree('inline-styles', inlineStyles),
|
||||
() => renderWideTree('inline-styles', inlineStyles),
|
||||
() => renderSierpinskiTriangle('inline-styles', inlineStyles)
|
||||
],
|
||||
'css-modules': [
|
||||
() => renderDeepTree('css-modules', cssModules),
|
||||
() => renderWideTree('css-modules', cssModules)
|
||||
],
|
||||
'react-native-web': [
|
||||
() => renderDeepTree('react-native-web', reactNativeWeb),
|
||||
() => renderWideTree('react-native-web', reactNativeWeb),
|
||||
() => renderSierpinskiTriangle('react-native-web', reactNativeWeb)
|
||||
],
|
||||
const implementations = impl;
|
||||
const packageNames = Object.keys(implementations);
|
||||
|
||||
aphrodite: [
|
||||
() => renderDeepTree('aphrodite', aphrodite),
|
||||
() => renderWideTree('aphrodite', aphrodite)
|
||||
],
|
||||
emotion: [
|
||||
() => renderDeepTree('emotion', emotion),
|
||||
() => renderWideTree('emotion', emotion),
|
||||
() => renderSierpinskiTriangle('emotion', emotion)
|
||||
],
|
||||
glamor: [
|
||||
() => renderDeepTree('glamor', glamor),
|
||||
() => renderWideTree('glamor', glamor)
|
||||
// disabled: glamor starts to lock up the browser
|
||||
// () => renderSierpinskiTriangle('glamor', glamor)
|
||||
],
|
||||
jss: [() => renderDeepTree('jss', jss), () => renderWideTree('jss', jss)],
|
||||
radium: [
|
||||
() => renderDeepTree('radium', radium),
|
||||
() => renderWideTree('radium', radium),
|
||||
() => renderSierpinskiTriangle('radium', radium)
|
||||
],
|
||||
reactxp: [
|
||||
() => renderDeepTree('reactxp', reactxp),
|
||||
() => renderWideTree('reactxp', reactxp),
|
||||
() => renderSierpinskiTriangle('reactxp', reactxp)
|
||||
],
|
||||
'styled-components': [
|
||||
() => renderDeepTree('styled-components', styledComponents),
|
||||
() => renderWideTree('styled-components', styledComponents),
|
||||
() => renderSierpinskiTriangle('styled-components', styledComponents)
|
||||
],
|
||||
styletron: [
|
||||
() => renderDeepTree('styletron', styletron),
|
||||
() => renderWideTree('styletron', styletron),
|
||||
() => renderSierpinskiTriangle('styletron', styletron)
|
||||
]
|
||||
const createTestBlock = fn => {
|
||||
return packageNames.reduce((testSetups, packageName) => {
|
||||
const { name, components, version } = implementations[packageName];
|
||||
const { Component, getComponentProps, sampleCount, Provider, benchmarkType } = fn(components);
|
||||
|
||||
testSetups[packageName] = {
|
||||
Component,
|
||||
getComponentProps,
|
||||
sampleCount,
|
||||
Provider,
|
||||
benchmarkType,
|
||||
version,
|
||||
name
|
||||
};
|
||||
return testSetups;
|
||||
}, {});
|
||||
};
|
||||
|
||||
const allTests = Object.keys(testMatrix).reduce((acc, curr) => {
|
||||
testMatrix[curr].forEach(test => {
|
||||
acc.push(test);
|
||||
});
|
||||
return acc;
|
||||
}, []);
|
||||
const tests = {
|
||||
'Mount deep tree': createTestBlock(components => ({
|
||||
benchmarkType: 'mount',
|
||||
Component: Tree,
|
||||
getComponentProps: () => ({ breadth: 2, components, depth: 7, id: 0, wrap: 1 }),
|
||||
Provider: components.Provider,
|
||||
sampleCount: 50
|
||||
})),
|
||||
'Mount wide tree': createTestBlock(components => ({
|
||||
benchmarkType: 'mount',
|
||||
Component: Tree,
|
||||
getComponentProps: () => ({ breadth: 6, components, depth: 3, id: 0, wrap: 2 }),
|
||||
Provider: components.Provider,
|
||||
sampleCount: 50
|
||||
})),
|
||||
'Update dynamic styles': createTestBlock(components => ({
|
||||
benchmarkType: 'update',
|
||||
Component: SierpinskiTriangle,
|
||||
getComponentProps: ({ cycle }) => {
|
||||
return { components, s: 200, renderCount: cycle, x: 0, y: 0 };
|
||||
},
|
||||
Provider: components.Provider,
|
||||
sampleCount: 100
|
||||
}))
|
||||
};
|
||||
|
||||
const tests = [];
|
||||
|
||||
if (window.location.search) {
|
||||
window.location.search
|
||||
.slice(1)
|
||||
.split(',')
|
||||
.forEach(implementation => {
|
||||
if (Array.isArray(testMatrix[implementation])) {
|
||||
tests.push(...testMatrix[implementation]);
|
||||
} else {
|
||||
throw new Error(`Benchmark for ${implementation} not found`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
tests.push(...allTests);
|
||||
}
|
||||
|
||||
tests.push(() => () => Promise.resolve(console.log('Done')));
|
||||
|
||||
tests.reduce((promise, test) => promise.then(test()), Promise.resolve());
|
||||
ReactDOM.render(<App tests={tests} />, document.querySelector('.root'));
|
||||
|
||||
@@ -30,7 +30,7 @@ module.exports = {
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
cacheDirectory: false,
|
||||
presets: babelPreset,
|
||||
plugins: ['react-native-web']
|
||||
}
|
||||
@@ -49,14 +49,10 @@ module.exports = {
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
dead_code: true,
|
||||
drop_console: true,
|
||||
screw_ie8: true,
|
||||
warnings: false
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native': 'react-native-web'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ class KeyboardAvoidingView extends Component<*> {
|
||||
|
||||
onLayout = (event: ViewLayoutEvent) => {
|
||||
this.frame = event.nativeEvent.layout;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
||||
156
yarn.lock
156
yarn.lock
@@ -430,7 +430,7 @@ anymatch@^1.3.0:
|
||||
micromatch "^2.1.5"
|
||||
normalize-path "^2.0.0"
|
||||
|
||||
aphrodite@^1.2.5:
|
||||
aphrodite@1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-1.2.5.tgz#8358c36c80bb03aee9b97165aaa70186225b4983"
|
||||
dependencies:
|
||||
@@ -659,7 +659,7 @@ babel-cli@^6.26.0:
|
||||
optionalDependencies:
|
||||
chokidar "^1.6.1"
|
||||
|
||||
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
|
||||
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
dependencies:
|
||||
@@ -2610,25 +2610,6 @@ css-in-js-utils@^2.0.0:
|
||||
dependencies:
|
||||
hyphenate-style-name "^1.0.2"
|
||||
|
||||
css-loader@^0.28.7:
|
||||
version "0.28.7"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b"
|
||||
dependencies:
|
||||
babel-code-frame "^6.11.0"
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
cssnano ">=2.6.1 <4"
|
||||
icss-utils "^2.1.0"
|
||||
loader-utils "^1.0.2"
|
||||
lodash.camelcase "^4.3.0"
|
||||
object-assign "^4.0.1"
|
||||
postcss "^5.0.6"
|
||||
postcss-modules-extract-imports "^1.0.0"
|
||||
postcss-modules-local-by-default "^1.0.1"
|
||||
postcss-modules-scope "^1.0.0"
|
||||
postcss-modules-values "^1.1.0"
|
||||
postcss-value-parser "^3.3.0"
|
||||
source-list-map "^2.0.0"
|
||||
|
||||
css-loader@^0.28.8:
|
||||
version "0.28.8"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.8.tgz#ff36381464dea18fe60f2601a060ba6445886bd5"
|
||||
@@ -2648,6 +2629,25 @@ css-loader@^0.28.8:
|
||||
postcss-value-parser "^3.3.0"
|
||||
source-list-map "^2.0.0"
|
||||
|
||||
css-loader@^0.28.9:
|
||||
version "0.28.9"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.9.tgz#68064b85f4e271d7ce4c48a58300928e535d1c95"
|
||||
dependencies:
|
||||
babel-code-frame "^6.26.0"
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
cssnano "^3.10.0"
|
||||
icss-utils "^2.1.0"
|
||||
loader-utils "^1.0.2"
|
||||
lodash.camelcase "^4.3.0"
|
||||
object-assign "^4.1.1"
|
||||
postcss "^5.0.6"
|
||||
postcss-modules-extract-imports "^1.2.0"
|
||||
postcss-modules-local-by-default "^1.2.0"
|
||||
postcss-modules-scope "^1.1.0"
|
||||
postcss-modules-values "^1.3.0"
|
||||
postcss-value-parser "^3.3.0"
|
||||
source-list-map "^2.0.0"
|
||||
|
||||
css-select@^1.1.0, css-select@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
|
||||
@@ -2687,7 +2687,7 @@ cssesc@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
|
||||
|
||||
"cssnano@>=2.6.1 <4", cssnano@^3.10.0:
|
||||
cssnano@^3.10.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
|
||||
dependencies:
|
||||
@@ -3107,7 +3107,7 @@ emotion-utils@^8.0.12:
|
||||
version "8.0.12"
|
||||
resolved "https://registry.yarnpkg.com/emotion-utils/-/emotion-utils-8.0.12.tgz#5e0fd72db3008f26ce4f80b1972df08841df2168"
|
||||
|
||||
emotion@^8.0.12:
|
||||
emotion@8.0.12:
|
||||
version "8.0.12"
|
||||
resolved "https://registry.yarnpkg.com/emotion/-/emotion-8.0.12.tgz#03de11ce26b1b2401c334b94d438652124c514c6"
|
||||
dependencies:
|
||||
@@ -3323,6 +3323,12 @@ eslint-config-prettier@^2.9.0:
|
||||
dependencies:
|
||||
get-stdin "^5.0.1"
|
||||
|
||||
eslint-plugin-cup@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-cup/-/eslint-plugin-cup-1.0.0.tgz#6ceced9a06d29e6e7bdc76ca9e398c9bf53072be"
|
||||
dependencies:
|
||||
globals "^10.0.0"
|
||||
|
||||
eslint-plugin-promise@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75"
|
||||
@@ -3925,7 +3931,7 @@ gitconfiglocal@^1.0.0:
|
||||
dependencies:
|
||||
ini "^1.3.2"
|
||||
|
||||
glamor@^2.20.40:
|
||||
glamor@2.20.40, glamor@^2.20.40:
|
||||
version "2.20.40"
|
||||
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.40.tgz#f606660357b7cf18dface731ad1a2cfa93817f05"
|
||||
dependencies:
|
||||
@@ -4394,7 +4400,7 @@ inline-style-prefixer@^2.0.5:
|
||||
bowser "^1.0.0"
|
||||
hyphenate-style-name "^1.0.1"
|
||||
|
||||
inline-style-prefixer@^3.0.1, inline-style-prefixer@^3.0.3, inline-style-prefixer@^3.0.6:
|
||||
inline-style-prefixer@^3.0.1, inline-style-prefixer@^3.0.6:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz#8551b8e5b4d573244e66a34b04f7d32076a2b534"
|
||||
dependencies:
|
||||
@@ -5594,10 +5600,6 @@ marked@^0.3.9:
|
||||
version "0.3.12"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519"
|
||||
|
||||
marky@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.0.tgz#9617ed647bbbea8f45d19526da33dec70606df42"
|
||||
|
||||
math-expression-evaluator@^1.2.14:
|
||||
version "1.2.17"
|
||||
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
|
||||
@@ -6501,27 +6503,33 @@ postcss-minify-selectors@^2.0.4:
|
||||
postcss "^5.0.14"
|
||||
postcss-selector-parser "^2.0.0"
|
||||
|
||||
postcss-modules-extract-imports@^1.0.0, postcss-modules-extract-imports@^1.1.0:
|
||||
postcss-modules-extract-imports@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb"
|
||||
dependencies:
|
||||
postcss "^6.0.1"
|
||||
|
||||
postcss-modules-local-by-default@^1.0.1, postcss-modules-local-by-default@^1.2.0:
|
||||
postcss-modules-extract-imports@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
|
||||
dependencies:
|
||||
postcss "^6.0.1"
|
||||
|
||||
postcss-modules-local-by-default@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
|
||||
dependencies:
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
postcss "^6.0.1"
|
||||
|
||||
postcss-modules-scope@^1.0.0, postcss-modules-scope@^1.1.0:
|
||||
postcss-modules-scope@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
|
||||
dependencies:
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
postcss "^6.0.1"
|
||||
|
||||
postcss-modules-values@^1.1.0, postcss-modules-values@^1.3.0:
|
||||
postcss-modules-values@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
|
||||
dependencies:
|
||||
@@ -6776,7 +6784,16 @@ querystring@0.2.0, querystring@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
|
||||
radium@^0.19.0, radium@^0.19.6:
|
||||
radium@0.21.0:
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/radium/-/radium-0.21.0.tgz#15ad5f7dccdc9b5a4d09e3c8f23dddcd8717f15b"
|
||||
dependencies:
|
||||
array-find "^1.0.0"
|
||||
exenv "^1.2.1"
|
||||
inline-style-prefixer "^4.0.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
radium@^0.19.0:
|
||||
version "0.19.6"
|
||||
resolved "https://registry.yarnpkg.com/radium/-/radium-0.19.6.tgz#b86721d08dbd303b061a4ae2ebb06cc6e335ae72"
|
||||
dependencies:
|
||||
@@ -6855,6 +6872,10 @@ react-art@^16.2.0:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-component-benchmark@^0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-component-benchmark/-/react-component-benchmark-0.0.4.tgz#eee3585e2203645ed968a40020f607d89bc82f64"
|
||||
|
||||
react-deep-force-update@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c"
|
||||
@@ -6912,9 +6933,9 @@ react-inspector@^2.2.2:
|
||||
babel-runtime "^6.26.0"
|
||||
is-dom "^1.0.9"
|
||||
|
||||
react-jss@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-8.2.0.tgz#8440f08aef27d408ba31f63df09167ed22a5b99b"
|
||||
react-jss@8.2.1:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-8.2.1.tgz#b2905063ba8b950f095a139a75232d851c79e15e"
|
||||
dependencies:
|
||||
hoist-non-react-statics "^2.3.1"
|
||||
jss "^9.3.2"
|
||||
@@ -7011,9 +7032,9 @@ react@^16.2.0:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
reactxp@^0.46.6:
|
||||
version "0.46.6"
|
||||
resolved "https://registry.yarnpkg.com/reactxp/-/reactxp-0.46.6.tgz#166a503a7147f3a1e29efc4469bda32603471a5f"
|
||||
reactxp@0.51.0-alpha.9:
|
||||
version "0.51.0-alpha.9"
|
||||
resolved "https://registry.yarnpkg.com/reactxp/-/reactxp-0.51.0-alpha.9.tgz#471ee6e7be65fe2461143eb6f49413cbb321b327"
|
||||
dependencies:
|
||||
"@types/lodash" "^4.14.78"
|
||||
"@types/react" "^16.0.0"
|
||||
@@ -7839,7 +7860,7 @@ style-loader@^0.19.1:
|
||||
loader-utils "^1.0.2"
|
||||
schema-utils "^0.3.0"
|
||||
|
||||
styled-components@^2.3.2:
|
||||
styled-components@2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.4.0.tgz#086d0fd483d54638837fca3ea546a030b94adf75"
|
||||
dependencies:
|
||||
@@ -7852,21 +7873,38 @@ styled-components@^2.3.2:
|
||||
stylis "^3.4.0"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
styletron-client@^3.0.0-rc.5:
|
||||
version "3.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/styletron-client/-/styletron-client-3.0.0-rc.5.tgz#275ca0b5f971d244f0e42079ad570be9c31a2a70"
|
||||
styletron-client@3.0.2, styletron-client@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/styletron-client/-/styletron-client-3.0.2.tgz#9b2853e8b94e6e94d70166b8403f27ab2d10c514"
|
||||
dependencies:
|
||||
styletron-core "^3.0.0-rc.3"
|
||||
styletron-core "^3.0.2"
|
||||
|
||||
styletron-core@^3.0.0-rc.3:
|
||||
version "3.0.0-rc.3"
|
||||
resolved "https://registry.yarnpkg.com/styletron-core/-/styletron-core-3.0.0-rc.3.tgz#9468e275d9085d2e5d6d6468cc6d8733dbfa3cba"
|
||||
styletron-core@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/styletron-core/-/styletron-core-3.0.2.tgz#67513feed50fb39753f72e547d00dfdb619ae79f"
|
||||
|
||||
styletron-utils@^3.0.0-rc.3:
|
||||
version "3.0.0-rc.3"
|
||||
resolved "https://registry.yarnpkg.com/styletron-utils/-/styletron-utils-3.0.0-rc.3.tgz#21fef2099f1c368e6ff2b8f76bf7a64bb547b760"
|
||||
styletron-react@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/styletron-react/-/styletron-react-3.0.3.tgz#67d2932db82972e0ea60544b7d5b8c6d5aecd3a3"
|
||||
dependencies:
|
||||
inline-style-prefixer "^3.0.3"
|
||||
"@types/react" "*"
|
||||
eslint-plugin-cup "^1.0.0"
|
||||
prop-types "^15.6.0"
|
||||
styletron-client "^3.0.2"
|
||||
styletron-server "^3.0.2"
|
||||
styletron-utils "^3.0.2"
|
||||
|
||||
styletron-server@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/styletron-server/-/styletron-server-3.0.2.tgz#0b989c833ed48437d68b728f65e9406fb8802de6"
|
||||
dependencies:
|
||||
styletron-core "^3.0.2"
|
||||
|
||||
styletron-utils@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/styletron-utils/-/styletron-utils-3.0.2.tgz#3bd18f60d8a8534e19d500ffa052a2f1c6c31198"
|
||||
dependencies:
|
||||
inline-style-prefixer "^4.0.0"
|
||||
|
||||
stylis-rule-sheet@^0.0.5:
|
||||
version "0.0.5"
|
||||
@@ -8410,9 +8448,9 @@ webidl-conversions@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
|
||||
webpack-bundle-analyzer@^2.9.1:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.9.1.tgz#c2c8e03e8e5768ed288b39ae9e27a8b8d7b9d476"
|
||||
webpack-bundle-analyzer@^2.9.2:
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.9.2.tgz#63ed86eb71cc4cda86f68e685a84530ba0126449"
|
||||
dependencies:
|
||||
acorn "^5.1.1"
|
||||
chalk "^1.1.3"
|
||||
@@ -8424,7 +8462,7 @@ webpack-bundle-analyzer@^2.9.1:
|
||||
lodash "^4.17.4"
|
||||
mkdirp "^0.5.1"
|
||||
opener "^1.4.3"
|
||||
ws "^3.3.1"
|
||||
ws "^4.0.0"
|
||||
|
||||
webpack-dev-middleware@^1.12.2:
|
||||
version "1.12.2"
|
||||
@@ -8588,9 +8626,9 @@ write@^0.2.1:
|
||||
dependencies:
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
ws@^3.3.1:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
|
||||
ws@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-4.0.0.tgz#bfe1da4c08eeb9780b986e0e4d10eccd7345999f"
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
Reference in New Issue
Block a user