Skip to content

Commit 4f0aff8

Browse files
committed
App shell for optimally small bundle size.
1 parent 30939b6 commit 4f0aff8

File tree

15 files changed

+308
-17
lines changed

15 files changed

+308
-17
lines changed

.core/app/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import _ from 'underscore';
88
import deps from 'dependencies';
99
import 'externals';
1010

11-
export const Loader = async () => {};
12-
1311
const loadFramework = async () => {
1412
console.log('Loading Core SDK');
1513
const { default: Reactium } = await import('reactium-core/sdk');

.core/app/shell.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export const Shell = async () => {
2+
const { default: React, useRef } = await import('react');
3+
const { default: _ } = await import('underscore');
4+
const { createRoot } = await import('react-dom/client');
5+
const { Loading } = await import('../components/Loading');
6+
7+
const Shell = () => {
8+
window.LoadingRef = useRef();
9+
return <Loading ref={window.LoadingRef} />;
10+
};
11+
12+
const something = createRoot(
13+
document.body.appendChild(document.createElement('div')),
14+
).render(<Shell />);
15+
16+
const { App } = await import('./index');
17+
await App();
18+
19+
_.defer(() => window.LoadingRef.current.setVisible(false));
20+
};

.core/components/Loading/domain.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* -----------------------------------------------------------------------------
3+
* DDD Domain Loading - Change name to place domain artifacts in this directory
4+
* in a different domain.
5+
* -----------------------------------------------------------------------------
6+
*/
7+
module.exports = {
8+
name: 'LoadingSpinner',
9+
};

.core/components/Loading/index.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import op from 'object-path';
2+
import ReactDom from 'react-dom';
3+
import PropTypes from 'prop-types';
4+
5+
import React, {
6+
forwardRef,
7+
useEffect,
8+
useImperativeHandle,
9+
useRef,
10+
useState,
11+
} from 'react';
12+
13+
/**
14+
* -----------------------------------------------------------------------------
15+
* Functional Component: Loading
16+
* -----------------------------------------------------------------------------
17+
*/
18+
let Loading = (
19+
{ controlled, visible: initVisible, style: initStyle, ...props },
20+
ref,
21+
) => {
22+
const containerRef = useRef();
23+
const ival = useRef();
24+
const opacity = useRef(initVisible === true ? 1 : 0);
25+
26+
const [visible, setVisible] = useState(initVisible);
27+
28+
const [init, setInit] = useState(false);
29+
30+
const [style, setStyle] = useState({
31+
...initStyle,
32+
display: opacity.current === 1 ? null : 'none',
33+
opacity: opacity.current,
34+
});
35+
36+
const show = () => {
37+
let i = ival.current;
38+
if (i) clearInterval(i);
39+
40+
const cont = containerRef.current;
41+
if (cont) {
42+
cont.style.display = null;
43+
if (init !== true) {
44+
cont.style.opacity = 0;
45+
}
46+
}
47+
48+
i = setInterval(() => {
49+
opacity.current = opacity.current + 0.0125;
50+
opacity.current = Math.min(opacity.current, 1);
51+
52+
if (cont) cont.style.opacity = opacity.current;
53+
54+
if (opacity.current === 1) {
55+
clearInterval(i);
56+
setStyle({ ...style, display: null });
57+
}
58+
}, 1);
59+
60+
ival.current = i;
61+
};
62+
63+
const hide = () => {
64+
let i = ival.current;
65+
if (i) clearInterval(i);
66+
const cont = containerRef.current;
67+
68+
i = setInterval(() => {
69+
opacity.current = opacity.current - 0.0125;
70+
opacity.current = Math.max(opacity.current, 0);
71+
72+
if (cont) cont.style.opacity = opacity.current;
73+
74+
if (opacity.current === 0) {
75+
cont.style.display = 'none';
76+
clearInterval(i);
77+
setStyle({ ...style, opacity: null });
78+
}
79+
}, 1);
80+
81+
ival.current = i;
82+
};
83+
84+
useImperativeHandle(
85+
ref,
86+
() => ({
87+
...props,
88+
hide,
89+
show,
90+
containerRef,
91+
visible,
92+
setStyle,
93+
setVisible,
94+
}),
95+
[visible],
96+
);
97+
98+
useEffect(() => {
99+
if (controlled === true) {
100+
const val = op.get(props, 'visible');
101+
if (val !== visible) setVisible(val);
102+
}
103+
}, [controlled, initVisible]);
104+
105+
useEffect(() => {
106+
if (controlled === true) {
107+
const val = op.get(props, 'style');
108+
if (val !== style) setStyle(val);
109+
}
110+
}, [controlled, initStyle]);
111+
112+
useEffect(() => {
113+
if (visible === true) {
114+
show();
115+
} else {
116+
hide();
117+
}
118+
}, [visible]);
119+
120+
useEffect(() => {
121+
setInit(true);
122+
}, []);
123+
124+
return ReactDom.createPortal(
125+
<div ref={containerRef} style={style} {...props} />,
126+
document.body,
127+
);
128+
};
129+
130+
Loading = forwardRef(Loading);
131+
132+
Loading.propTypes = {
133+
className: PropTypes.string,
134+
controlled: PropTypes.bool,
135+
style: PropTypes.object,
136+
visible: PropTypes.bool,
137+
};
138+
139+
Loading.defaultProps = {
140+
className: 'reactium-loading',
141+
controlled: false,
142+
style: {},
143+
visible: true,
144+
};
145+
146+
export { Loading };
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* -----------------------------------------------------------------------------
3+
* Reactium Plugin Loading
4+
* -----------------------------------------------------------------------------
5+
*/
6+
7+
import { Loading } from './index';
8+
import Reactium from 'reactium-core/sdk';
9+
10+
(async () => {
11+
Reactium.Component.register('Loading', Loading);
12+
})();

.core/server/renderer/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ ReactiumBoot.Hook.registerSync(
151151
(req, AppBindings) => {
152152
AppBindings.register('router', {
153153
template: () => {
154-
const binding = `<div id="router">${req.content || ''}</div>`;
154+
const binding = ` <div data-reactium-bind="App"></div>`;
155155
return binding;
156156
},
157157
requestParams: ['content'],
@@ -585,7 +585,7 @@ export default async (req, res, context) => {
585585
586586
// Add ordinary markup for React to bind to
587587
AppBindings.register('router', {
588-
markup: '<div id="router"></div>',
588+
markup: ' <div data-reactium-bind="App"></div>',
589589
});
590590
},
591591
ReactiumBoot.Enums.priority.highest,

.core/server/template/feo.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ module.exports = {
1313
${req.headerScripts}
1414
${req.appBindings}
1515
16-
<div data-reactium-bind="Loader"></div>
17-
<div data-reactium-bind="App"></div>
18-
<div data-reactium-bind="Foo"></div>
19-
<div data-reactium-bind="Bar"></div>
20-
2116
<script>
2217
window.defines = ${serialize(defines)};
2318
${req.appGlobals}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
body {
2+
padding: 0;
3+
margin: 0;
4+
overflow: hidden;
5+
6+
iframe {
7+
outline: none;
8+
border: none;
9+
}
10+
}

src/app/components/Welcome/domain.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* -----------------------------------------------------------------------------
3+
* DDD Domain Welcome - Change name to place domain artifacts in this directory
4+
* in a different domain.
5+
* -----------------------------------------------------------------------------
6+
*/
7+
module.exports = {
8+
name: 'Welcome',
9+
};

src/app/components/Welcome/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
3+
/**
4+
* -----------------------------------------------------------------------------
5+
* Functional Component: Welcome
6+
* -----------------------------------------------------------------------------
7+
*/
8+
const Welcome = () => {
9+
return (
10+
<div style={{ width: '100vw', height: '100vh' }}>
11+
<iframe width='100%' height='100%' src='https://reactium.io/' />
12+
</div>
13+
);
14+
};
15+
16+
export { Welcome };
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* -----------------------------------------------------------------------------
3+
* Reactium Plugin Welcome
4+
* -----------------------------------------------------------------------------
5+
*/
6+
7+
import { Welcome } from './index';
8+
import Reactium from 'reactium-core/sdk';
9+
10+
(async () => {
11+
Reactium.Component.register('Welcome', Welcome);
12+
})();

src/app/components/Welcome/route.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Welcome } from './index';
2+
3+
export default {
4+
exact: true,
5+
component: Welcome,
6+
path: ['/'],
7+
};

src/app/main.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22
// import 'core-js/stable';
33
// import 'regenerator-runtime/runtime';
44

5-
let App, AppError;
5+
import { Shell } from 'reactium-core/app/shell';
66

77
(async () => {
8-
const mod = await import('reactium-core/app');
9-
10-
App = mod.App;
11-
AppError = mod.AppError;
12-
138
try {
14-
App();
9+
await Shell();
1510
} catch (error) {
16-
AppError(error);
11+
const { AppError } = await import('reactium-core/app');
12+
await AppError(error);
1713
}
1814

1915
/**

src/assets/style/_scss/_reactium-modules.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
// WARNING: Do not directly edit this file !!!!
33
// File generated by gulp styles:partials task
44

5+
@import '_reactium-style-molecules';
6+
@import '../../../app/components/Welcome/_reactium-style-organisms';
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
$reactium-blue: #4f82ba !default;
2+
$reactium-white: #ffffff !default;
3+
4+
.reactium-loading {
5+
top: 0;
6+
left: 0;
7+
width: 100vw;
8+
height: 100vh;
9+
position: fixed;
10+
background-color: $reactium-white;
11+
12+
&,
13+
* {
14+
box-sizing: border-box;
15+
}
16+
17+
&:before {
18+
content: '';
19+
width: 64px;
20+
height: 64px;
21+
border-radius: 100%;
22+
z-index: 1;
23+
left: 50%;
24+
top: 50%;
25+
position: absolute;
26+
transform: translate(-50%, -50%);
27+
box-shadow: 0 0 0 0 rgba($reactium-blue, 1);
28+
animation: reactium-pulse 1.2s infinite;
29+
}
30+
31+
&:after {
32+
content: '';
33+
width: 64px;
34+
height: 64px;
35+
z-index: 2;
36+
left: 50%;
37+
top: 50%;
38+
position: absolute;
39+
transform: translate(-50%, -50%);
40+
background-size: cover;
41+
background-position: center;
42+
background-repeat: no-repeat;
43+
background-image: url('/assets/images/logo.png');
44+
}
45+
}
46+
47+
@keyframes reactium-pulse {
48+
0% {
49+
box-shadow: 0 0 0 0 rgba($reactium-blue, 0.7);
50+
}
51+
52+
70% {
53+
box-shadow: 0 0 0 12px rgba($reactium-blue, 0);
54+
}
55+
56+
100% {
57+
box-shadow: 0 0 0 0 rgba($reactium-white, 0);
58+
}
59+
}

0 commit comments

Comments
 (0)