Skip to content

Commit 30939b6

Browse files
committed
New bindpoint loading and much smaller default bundle size.
1 parent 65bf013 commit 30939b6

File tree

9 files changed

+2704
-6681
lines changed

9 files changed

+2704
-6681
lines changed

.core/app/index.js

Lines changed: 92 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,12 @@ import React from 'react';
77
import _ from 'underscore';
88
import deps from 'dependencies';
99
import 'externals';
10-
import { createRoot, hydrateRoot } from 'react-dom/client';
1110

12-
/**
13-
* -----------------------------------------------------------------------------
14-
* @function App()
15-
* @description Scan DOM for <Component> elements and render React components
16-
* inside of them.
17-
* -----------------------------------------------------------------------------
18-
*/
19-
export const App = async () => {
11+
export const Loader = async () => {};
12+
13+
const loadFramework = async () => {
2014
console.log('Loading Core SDK');
21-
const {
22-
default: Reactium,
23-
hookableComponent,
24-
isBrowserWindow,
25-
Zone,
26-
AppContexts,
27-
} = await import('reactium-core/sdk');
15+
const { default: Reactium } = await import('reactium-core/sdk');
2816

2917
console.log('Initializing Application Hooks');
3018

@@ -40,8 +28,6 @@ export const App = async () => {
4028
await Reactium.Hook.run('sdk-init', Reactium);
4129
Reactium.Hook.runSync('sdk-init', Reactium);
4230

43-
const context = {};
44-
4531
/**
4632
* @api {Hook} init init
4733
* @apiName init
@@ -102,96 +88,97 @@ export const App = async () => {
10288
* @apiGroup Hooks
10389
*/
10490
await Reactium.Hook.run('plugin-ready');
91+
};
10592

106-
if (isBrowserWindow()) {
107-
/**
108-
* @api {Hook} component-bindings component-bindings
109-
* @apiName component-bindings
110-
* @apiDescription Called after plugin and routing initialization to define element and dynamic component for
111-
one-off component bindings to the DOM. e.g. In development mode, used to render Redux Dev tools.
112-
async only - used in front-end application only
113-
* @apiParam {Object} context context.bindPoints MUST be an array of binding objects after this hook is called
114-
* @apiParam (binding) {HTMLElement} the DOM element to bind to (e.g. document.getElementById('my-element'))
115-
* @apiParam (binding) {String} string matching a React component module in one of the Reactium built-in webpack contexts
116-
(src/app/components or src/app/components/common-ui) e.g. 'DevTools' maps to src/app/components/DevTools
117-
* @apiGroup Hooks
118-
*/
119-
const { bindPoints } = await Reactium.Hook.run('component-bindings');
120-
121-
/**
122-
* @api {Hook} app-bindpoint app-bindpoint
123-
* @apiName app-bindpoint
124-
* @apiDescription Called after plugin and routing initialization to define the DOM element used for mounting the Single-Page application (SPA).
125-
By default, the application will bind to `document.getElementById('router')`, but this can be changed with this hook. This is related to the HTML
126-
template artifacts left by the server-side `Server.AppBindings` hook.
127-
async only - used in front-end application only
128-
* @apiParam {Object} context context.appElement MUST be an HTMLElement where your React appliation will bind to the DOM.
129-
* @apiParam (appElement) {HTMLElement} the DOM element to bind to - by default `document.getElementById('router')`.
130-
* @apiGroup Hooks
131-
*/
132-
const { appElement } = await Reactium.Hook.run('app-bindpoint');
133-
134-
/**
135-
* @api {Hook} app-context-provider app-context-provider
136-
* @apiName app-context-provider
137-
* @apiDescription Called after app-bindpoint to define any React context providers, using the [Reactium.AppContext](#api-Reactium-Reactium.AppContext) registry.
138-
* @apiGroup Hooks
139-
*/
140-
await Reactium.Hook.run('app-context-provider');
141-
142-
/**
143-
* @api {Hook} app-router app-router
144-
* @apiName app-router
145-
* @apiDescription Called after app-context-provider to define the registered Router component (i.e. `Reactium.Component.register('Router'...)`).
146-
After this hook, the ReactDOM bindings will actually take place.
147-
async only - used in front-end application only
148-
* @apiGroup Hooks
149-
*/
150-
await Reactium.Hook.run('app-router');
151-
152-
const Router = hookableComponent('Router');
153-
154-
// Render the React Components
155-
if (bindPoints.length > 0) {
156-
bindPoints.forEach(item =>
157-
createRoot(item.element).render(
158-
<AppContexts>{item.component}</AppContexts>,
159-
),
160-
);
161-
}
93+
/**
94+
* -----------------------------------------------------------------------------
95+
* @function App()
96+
* @description Scan DOM for <Component> elements and render React components
97+
* inside of them.
98+
* -----------------------------------------------------------------------------
99+
*/
100+
export const App = async () => {
101+
const {
102+
default: Reactium,
103+
hookableComponent,
104+
Zone,
105+
AppContexts,
106+
} = await import('reactium-core/sdk');
107+
108+
await loadFramework();
109+
110+
/**
111+
* @api {Hook} component-bindings component-bindings
112+
* @apiName component-bindings
113+
* @apiDescription Called after plugin and routing initialization to define element and dynamic component for
114+
one-off component bindings to the DOM. e.g. In development mode, used to render Redux Dev tools.
115+
async only - used in front-end application only
116+
* @apiParam {Object} context context.bindPoints MUST be an array of binding objects after this hook is called
117+
* @apiParam (binding) {HTMLElement} the DOM element to bind to (e.g. document.getElementById('my-element'))
118+
* @apiParam (binding) {String} string matching a React component module in one of the Reactium built-in webpack contexts
119+
(src/app/components or src/app/components/common-ui) e.g. 'DevTools' maps to src/app/components/DevTools
120+
* @apiGroup Hooks
121+
*/
122+
const { bindPoints } = await Reactium.Hook.run('component-bindings');
162123

163-
// ensure router DOM Element is on the page
164-
if (appElement) {
165-
/**
166-
* @api {Hook} app-boot-message app-boot-message
167-
* @apiName app-boot-message
168-
* @apiDescription Called during application binding, this minor hook will allow you to
169-
change the format of the of the front-end Javascript console message indicating application start.
170-
async only - used in front-end application only
171-
* @apiGroup Hooks
172-
*/
173-
const { message = [] } = await Reactium.Hook.run(
174-
'app-boot-message',
175-
);
176-
console.log(...message);
177-
178-
createRoot(appElement).render(
179-
<AppContexts>
180-
<Zone zone='reactium-provider' />
181-
<Router history={Reactium.Routing.history} />
182-
<Zone zone='reactium-provider-after' />
183-
</AppContexts>,
184-
);
185-
186-
/**
187-
* @api {Hook} app-ready app-ready
188-
* @apiDescription The final hook run after the front-end application has bee bound or hydrated. After this point,
189-
the all hooks are runtime hooks.
190-
* @apiName app-ready
191-
* @apiGroup Hooks
192-
*/
193-
_.defer(() => Reactium.Hook.run('app-ready'));
124+
/**
125+
* @api {Hook} app-context-provider app-context-provider
126+
* @apiName app-context-provider
127+
* @apiDescription Called after app-bindpoint to define any React context providers, using the [Reactium.AppContext](#api-Reactium-Reactium.AppContext) registry.
128+
* @apiGroup Hooks
129+
*/
130+
await Reactium.Hook.run('app-context-provider');
131+
132+
// Render the React Components
133+
if (bindPoints.length > 0) {
134+
const { createRoot } = await import('react-dom/client');
135+
136+
console.log('Binding components.');
137+
for (const { type, Component, Element } of bindPoints) {
138+
if (type === 'App') {
139+
/**
140+
* @api {Hook} app-router app-router
141+
* @apiName app-router
142+
* @apiDescription Called after app-context-provider to define the registered Router component (i.e. `Reactium.Component.register('Router'...)`).
143+
After this hook, the ReactDOM bindings will actually take place.
144+
async only - used in front-end application only
145+
* @apiGroup Hooks
146+
*/
147+
await Reactium.Hook.run('app-router');
148+
149+
const Router = hookableComponent('Router');
150+
const { message = [] } = await Reactium.Hook.run(
151+
'app-boot-message',
152+
);
153+
154+
console.log(...message);
155+
156+
createRoot(Element).render(
157+
<AppContexts>
158+
<Zone zone='reactium-provider' />
159+
<Router history={Reactium.Routing.history} />
160+
<Zone zone='reactium-provider-after' />
161+
</AppContexts>,
162+
);
163+
164+
/**
165+
* @api {Hook} app-ready app-ready
166+
* @apiDescription The final hook run after the front-end application has bee bound or hydrated. After this point,
167+
the all hooks are runtime hooks.
168+
* @apiName app-ready
169+
* @apiGroup Hooks
170+
*/
171+
} else {
172+
// createRoot(Element).render(<Component />);
173+
createRoot(Element).render(
174+
<AppContexts>
175+
<Component />
176+
</AppContexts>,
177+
);
178+
}
194179
}
180+
181+
_.defer(() => Reactium.Hook.run('app-ready'));
195182
}
196183
};
197184

.core/app/reactium-hooks.js

Lines changed: 11 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,29 @@
1-
import 'core-js/stable';
2-
import 'regenerator-runtime/runtime';
31
import 'reactium-core/components/Router/reactium-hooks';
42
import op from 'object-path';
53
import _ from 'underscore';
64
import deps from 'dependencies';
75

86
import('reactium-core/sdk').then(
9-
async ({ default: Reactium, HookComponent, isServerWindow }) => {
7+
async ({ default: Reactium, useHookComponent }) => {
108
Reactium.Hook.register(
119
'component-bindings',
1210
async context => {
13-
const { default: getComponents } = await import(
14-
'dependencies/getComponents'
15-
);
11+
const { hookableComponent } = await import('reactium-core/sdk');
1612

1713
// Placeholder for the bindable elements
1814
const bindPoints = [];
1915

20-
// <Component /> DOM Elements array
21-
const elements =
22-
typeof document !== 'undefined'
23-
? Array.prototype.slice.call(
24-
document.querySelectorAll('component'),
25-
)
26-
: [];
16+
const elements = Array.from(
17+
document.querySelectorAll('[data-reactium-bind]'),
18+
);
2719

2820
if (elements.length > 0) {
2921
let types = [];
30-
31-
let elms = elements.map(elm => {
32-
let path = elm.getAttribute('path');
33-
let type = elm.getAttribute('type');
34-
35-
types.push(type);
36-
37-
return { path, type };
38-
});
39-
40-
let components = getComponents(elms);
41-
42-
elements.forEach(elm => {
43-
// Get the component type
44-
let type = elm.getAttribute('type');
45-
46-
if (!components.hasOwnProperty(type)) {
47-
return;
48-
}
49-
50-
// Get parameters from container element
51-
let params = {};
52-
let exclude = ['type', 'path'];
53-
Object.entries(elm.attributes).forEach(
54-
([key, attr]) => {
55-
key = String(key).toLowerCase();
56-
if (exclude.indexOf(key) < 0) {
57-
return;
58-
}
59-
params[attr.name] = attr.value;
60-
},
61-
);
62-
63-
// Get the children from the element and pass them to the component
64-
let children = elm.innerHTML;
65-
if (children) {
66-
params['children'] = children;
67-
}
68-
69-
// Create the React element and apply parameters
70-
let cmp = React.createElement(components[type], params);
71-
bindPoints.push({ component: cmp, element: elm });
72-
console.log('Binding components.');
73-
});
22+
for (const Element of elements) {
23+
const type = Element.getAttribute('data-reactium-bind');
24+
const Component = hookableComponent(type);
25+
bindPoints.push({ type, Element, Component });
26+
}
7427
}
7528

7629
context.bindPoints = bindPoints;
@@ -142,7 +95,7 @@ import('reactium-core/sdk').then(
14295
Reactium.Hook.register(
14396
'app-router',
14497
async () => {
145-
const { default: Router } = await import(
98+
const { Router } = await import(
14699
'reactium-core/components/Router'
147100
);
148101
Reactium.Component.register('Router', Router);

.core/components/Router/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React from 'react';
2-
import { Router } from 'react-router-dom';
2+
import { Router as Dom } from 'react-router-dom';
33
import { useHookComponent } from 'reactium-core/sdk';
44

5-
export default ({ history }) => {
5+
export const Router = ({ history }) => {
66
const RoutedContent = useHookComponent('RoutedContent');
77
return (
8-
<Router history={history}>
8+
<Dom history={history}>
99
<RoutedContent />
10-
</Router>
10+
</Dom>
1111
);
1212
};

.core/components/Router/server.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

.core/server/template/feo.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ 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+
1621
<script>
1722
window.defines = ${serialize(defines)};
1823
${req.appGlobals}

.core/webpack.sdk.js

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -315,24 +315,8 @@ class WebpackReactiumWebpack {
315315
splitChunks: {
316316
chunks: 'all',
317317
cacheGroups: {
318-
vendors: {
319-
test: this.matchChunk(/[\\/]node_modules[\\/]/),
320-
priority: -10,
321-
reuseExistingChunk: true,
322-
},
323-
core: {
324-
test: this.matchChunk(/[\\/]\.core/),
325-
priority: -10,
326-
reuseExistingChunk: true,
327-
},
328-
sdk: {
329-
test: this.matchChunk(/[\\/]\.core[\\/]sdk/),
330-
priority: -20,
331-
priority: 0,
332-
reuseExistingChunk: true,
333-
},
334-
sw: {
335-
test: this.matchChunk(/[\\/]node_modules[\\/]workbox/),
318+
main: {
319+
minChunks: 1,
336320
priority: -20,
337321
reuseExistingChunk: true,
338322
},

0 commit comments

Comments
 (0)