feat: code splitting with react lazy & suspense

This commit is contained in:
tristan 2019-09-18 11:54:38 +08:00
parent 8785781cd3
commit c5bb2883d7
3 changed files with 140 additions and 14 deletions

View File

@ -1,17 +1,30 @@
import React, { useEffect } from 'react';
import React, { useEffect, lazy, Suspense } from 'react';
import styled from 'styled-components';
import pinyin from 'pinyin';
import convert from 'color-convert';
import ColorTitle from './components/ColorTitle';
import Color from './components/Color';
import Preview from './components/Preview';
import ColorParam from './components/ColorParam';
import InfoModal from './components/InfoModal';
import IconInfo from './components/IconInfo';
import IconScreenshot from './components/IconScreenshot';
import Header from './components/Header';
import ColorSet from './components/ColorSet';
import Loading from './components/Loading';
const ColorTitle = lazy(() => import('./components/ColorTitle'));
const Color = lazy(() => import('./components/Color'));
const Preview = lazy(() => import('./components/Preview'));
const ColorParam = lazy(() => import('./components/ColorParam'));
const InfoModal = lazy(() => import('./components/InfoModal'));
const IconInfo = lazy(() => import('./components/IconInfo'));
const Header = lazy(() => import('./components/Header'));
const IconScreenshot = lazy(() => import('./components/IconScreenshot'));
const ColorSet = lazy(() => import('./components/ColorSet'));
// import ColorTitle from './components/ColorTitle';
// import Color from './components/Color';
// import Preview from './components/Preview';
// import ColorParam from './components/ColorParam';
// import InfoModal from './components/InfoModal';
// import IconInfo from './components/IconInfo';
// import IconScreenshot from './components/IconScreenshot';
// import Header from './components/Header';
// import ColorSet from './components/ColorSet';
import { useModal, useColor, usePreview } from './hooks';
import colors from './assets/colors.json';
colors.push({
@ -100,7 +113,7 @@ const App = () => {
document.body.style.backgroundColor = currColor.hex;
}, [currColor]);
return (
<>
<Suspense fallback={<Loading color="#000" size="4" sizeUnit="rem" />}>
<Wrapper>
<aside className="colorSet">
<ColorSet sets={sets} currSetName={currSet.name} setCurrSet={updateCurrSet} />
@ -138,7 +151,7 @@ const App = () => {
/>
)}
{modalVisible && <InfoModal bgColor={currColor.hex} closeModal={closeModal} />}
</>
</Suspense>
);
};
export default App;

View File

@ -8,8 +8,8 @@ const Wrapper = styled.aside`
align-items: center;
margin-bottom: 0.8rem;
.icon {
width: 1.8rem;
height: 1.8rem;
width: 1.4rem;
height: 1.4rem;
}
`;

113
src/components/Loading.js Normal file
View File

@ -0,0 +1,113 @@
import React from 'react';
import styled, { keyframes } from 'styled-components';
const rotate = keyframes`
0% {
transform: rotate(0deg);
}
100%{
transform: rotate(-360deg);
}
`;
const rotateBall = props => keyframes`
${(((props.size / 2 / props.countBalls) * (props.index - 1)) / props.size) * 100}% {
opacity: 0;
}
${(((props.size / 2 / props.countBalls + 0.0001) * (props.index - 1)) / props.size) * 100}% {
opacity: 1;
transform: ${`rotateZ(${0 - (360 / props.countBalls) * (props.index - 2)}deg)`};
}
${(((props.size / 2 / props.countBalls) * (props.index - 0) + 2) / props.size) * 100}% {
transform: ${`rotateZ(${0 - (360 / props.countBalls) * (props.index - 1)}deg)`};
}
${((props.size / 2 + (props.size / 2 / props.countBalls) * (props.index - 0) + 2) / props.size) *
100}% {
transform: ${`rotateZ(${0 - (360 / props.countBalls) * (props.index - 1)}deg)`};
}
100% {
transform: ${`rotateZ(${0 - (360 / props.countBalls) * (props.countBalls - 1)}deg)`};
opacity: 1;
}
`;
const getBalls = ({
countBalls,
radius,
angle,
color = '#fff',
size = 40,
ballSize,
sizeUnit = 'px'
}) => {
const balls = [];
const offset = ballSize / 2;
for (let i = 0; i < countBalls; i++) {
const y = Math.sin(angle * i * (Math.PI / 180)) * radius - offset;
const x = Math.cos(angle * i * (Math.PI / 180)) * radius - offset;
balls.push(
<Ball
countBalls={countBalls}
color={color}
ballSize={ballSize}
size={size}
sizeUnit={sizeUnit}
x={y}
y={x}
key={i.toString()}
index={i + 1}
/>
);
}
return balls;
};
const Wrapper = styled.div`
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
animation: ${rotate} 3s infinite ease-in;
`;
const Ball = styled.div`
position: absolute;
width: ${props => `${props.size}${props.sizeUnit}`};
height: ${props => `${props.size}${props.sizeUnit}`};
animation: ${rotateBall} 2s infinite linear;
transform: ${props => `rotateZ(${(360 / props.countBalls) * props.index}deg)`};
opacity: 0;
&:before {
content: '';
position: absolute;
left: 50%;
top: 0%;
width: ${props => `${props.ballSize}${props.sizeUnit}`};
height: ${props => `${props.ballSize}${props.sizeUnit}`};
background-color: ${props => `${props.color}`};
transform: translateX(-50%);
border-radius: 50%;
}
`;
const Loading = ({ size = 40, color = '#fff', sizeUnit = 'px' }) => {
const radius = size / 2;
const countBalls = 9;
const ballSize = size / 8;
const angle = 360 / countBalls;
return (
<Wrapper size={size} sizeUnit={sizeUnit}>
{getBalls({
countBalls,
radius,
angle,
color,
size,
ballSize,
sizeUnit
})}
</Wrapper>
);
};
export default Loading;