neo.mjs 10.0.0-alpha.2 → 10.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.github/CODING_GUIDELINES.md +1 -1
  2. package/README.md +52 -11
  3. package/ServiceWorker.mjs +2 -2
  4. package/apps/portal/index.html +1 -1
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/apps/portal/view/learn/ContentComponent.mjs +2 -1
  7. package/apps/portal/view/learn/MainContainerStateProvider.mjs +3 -6
  8. package/apps/realworld/view/HomeComponent.mjs +1 -1
  9. package/apps/realworld/view/user/ProfileComponent.mjs +1 -1
  10. package/apps/sharedcovid/view/MainContainerController.mjs +1 -1
  11. package/apps/shareddialog/view/MainContainerController.mjs +2 -2
  12. package/examples/component/gallery/ImageStore.mjs +2 -2
  13. package/examples/component/helix/ImageStore.mjs +2 -2
  14. package/learn/README.md +83 -0
  15. package/learn/guides/ApplicationBootstrap.md +354 -0
  16. package/learn/guides/DeclarativeComponentTreesVsImperativeVdom.md +500 -0
  17. package/learn/guides/WorkingWithVDom.md +748 -0
  18. package/learn/tree.json +53 -0
  19. package/package.json +2 -2
  20. package/src/DefaultConfig.mjs +27 -14
  21. package/src/Main.mjs +1 -7
  22. package/src/Neo.mjs +16 -0
  23. package/src/button/Base.mjs +2 -2
  24. package/src/calendar/view/MainContainerStateProvider.mjs +1 -1
  25. package/src/grid/header/Button.mjs +1 -1
  26. package/src/layout/Cube.mjs +2 -2
  27. package/src/main/DeltaUpdates.mjs +20 -12
  28. package/src/main/addon/Navigator.mjs +1 -1
  29. package/src/main/addon/WindowPosition.mjs +1 -1
  30. package/src/main/render/StringBasedRenderer.mjs +1 -1
  31. package/src/tab/header/Toolbar.mjs +1 -1
  32. package/src/table/header/Button.mjs +1 -1
  33. package/src/toolbar/Base.mjs +1 -1
  34. package/src/util/VDom.mjs +1 -1
  35. package/src/util/VNode.mjs +1 -1
  36. package/src/vdom/Helper.mjs +96 -49
  37. package/src/vdom/VNode.mjs +38 -2
  38. package/src/worker/App.mjs +2 -1
  39. package/src/worker/Base.mjs +87 -5
  40. package/src/worker/Manager.mjs +86 -28
  41. package/resources/data/deck/learnneo/tree.json +0 -50
  42. package/resources/data/deck/whyneo.md +0 -80
  43. /package/{resources/data/deck/learnneo/pages → learn}/Glossary.md +0 -0
  44. /package/{resources/data/deck/learnneo/pages → learn}/UsingTheseTopics.md +0 -0
  45. /package/{resources/data/deck/learnneo/pages → learn}/benefits/ConfigSystem.md +0 -0
  46. /package/{resources/data/deck/learnneo/pages → learn}/benefits/Effort.md +0 -0
  47. /package/{resources/data/deck/learnneo/pages → learn}/benefits/Features.md +0 -0
  48. /package/{resources/data/deck/learnneo/pages → learn}/benefits/FormsEngine.md +0 -0
  49. /package/{resources/data/deck/learnneo/pages → learn}/benefits/FourEnvironments.md +0 -0
  50. /package/{resources/data/deck/learnneo/pages → learn}/benefits/Introduction.md +0 -0
  51. /package/{resources/data/deck/learnneo/pages → learn}/benefits/MultiWindow.md +0 -0
  52. /package/{resources/data/deck/learnneo/pages → learn}/benefits/OffTheMainThread.md +0 -0
  53. /package/{resources/data/deck/learnneo/pages → learn}/benefits/Quick.md +0 -0
  54. /package/{resources/data/deck/learnneo/pages → learn}/benefits/Speed.md +0 -0
  55. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/ComponentModels.md +0 -0
  56. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/Config.md +0 -0
  57. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/DescribingTheUI.md +0 -0
  58. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/Events.md +0 -0
  59. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/Extending.md +0 -0
  60. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/References.md +0 -0
  61. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/Setup.md +0 -0
  62. /package/{resources/data/deck/learnneo/pages → learn}/gettingstarted/Workspaces.md +0 -0
  63. /package/{resources/data/deck/learnneo/pages → learn}/guides/ComponentsAndContainers.md +0 -0
  64. /package/{resources/data/deck/learnneo/pages → learn}/guides/CustomComponents.md +0 -0
  65. /package/{resources/data/deck/learnneo/pages → learn}/guides/Forms.md +0 -0
  66. /package/{resources/data/deck/learnneo/pages → learn}/guides/InstanceLifecycle.md +0 -0
  67. /package/{resources/data/deck/learnneo/pages → learn}/guides/Layouts.md +0 -0
  68. /package/{resources/data/deck/learnneo/pages → learn}/guides/MainThreadAddonExample.md +0 -0
  69. /package/{resources/data/deck/learnneo/pages → learn}/guides/MainThreadAddonIntro.md +0 -0
  70. /package/{resources/data/deck/learnneo/pages → learn}/guides/Mixins.md +0 -0
  71. /package/{resources/data/deck/learnneo/pages → learn}/guides/MultiWindow.md +0 -0
  72. /package/{resources/data/deck/learnneo/pages → learn}/guides/PortalApp.md +0 -0
  73. /package/{resources/data/deck/learnneo/pages → learn}/guides/StateProviders.md +0 -0
  74. /package/{resources/data/deck/learnneo/pages → learn}/guides/Tables.md +0 -0
  75. /package/{resources/data/deck/learnneo/pages → learn}/guides/events/CustomEvents.md +0 -0
  76. /package/{resources/data/deck/learnneo/pages → learn}/guides/events/DomEvents.md +0 -0
  77. /package/{resources/data/deck/learnneo/pages → learn}/javascript/ClassFeatures.md +0 -0
  78. /package/{resources/data/deck/learnneo/pages → learn}/javascript/Classes.md +0 -0
  79. /package/{resources/data/deck/learnneo/pages → learn}/javascript/NewNode.md +0 -0
  80. /package/{resources/data/deck/learnneo/pages → learn}/javascript/Overrides.md +0 -0
  81. /package/{resources/data/deck/learnneo/pages → learn}/javascript/Super.md +0 -0
  82. /package/{resources/data/deck/learnneo/pages → learn}/tutorials/Earthquakes.md +0 -0
  83. /package/{resources/data/deck/learnneo/pages → learn}/tutorials/RSP.md +0 -0
  84. /package/{resources/data/deck/learnneo/pages → learn}/tutorials/TodoList.md +0 -0
  85. /package/resources/data/{deck/learnneo/data/theBeatles.json → theBeatles.json} +0 -0
@@ -0,0 +1,354 @@
1
+ # Neo.mjs Application Bootstrap Process
2
+
3
+ This guide explains how Neo.mjs applications start, initialize, and come to life - from the initial HTML file to your
4
+ first rendered component.
5
+
6
+ ## Overview
7
+
8
+ When you run a Neo.mjs application in the browser, a sophisticated multi-threaded orchestration happens behind the scenes.
9
+ Unlike traditional web frameworks that run everything on the main thread, Neo.mjs distributes work across multiple threads
10
+ using Web Workers.
11
+
12
+ > **Note:** For a deeper understanding of Neo.mjs's multi-threaded architecture, see the
13
+ > [Off The Main Thread](../benefits/OffTheMainThread.md) guide.
14
+
15
+ ## Bootstrap Sequence
16
+
17
+ ### 1. Entry Point: index.html
18
+
19
+ The bootstrap process begins with a minimal HTML file:
20
+
21
+ ```html
22
+ <!DOCTYPE HTML>
23
+ <html>
24
+ <head>
25
+ <meta name="viewport" content="width=device-width, initial-scale=1">
26
+ <meta charset="UTF-8">
27
+ <title>My Neo.mjs App</title>
28
+ </head>
29
+ <body>
30
+ <script src="../../src/MicroLoader.mjs" type="module"></script>
31
+ </body>
32
+ </html>
33
+ ```
34
+
35
+ The only JavaScript file imported is the `MicroLoader.mjs`, which is loaded as an ES module.
36
+
37
+ > **Note:** You don't need to create these files manually. Neo.mjs provides CLI tools to generate the basic
38
+ > application structure. You can use `npm run create-app` inside the framework repo or `npx neo-app` to generate
39
+ > a workspace with the same structure.
40
+
41
+ ### 2. MicroLoader: Configuration Loading
42
+
43
+ The `MicroLoader.mjs` is a small script that fetches the application configuration and bootstraps the main thread:
44
+
45
+ ```javascript
46
+ fetch('./neo-config.json').then(r => r.json()).then(d => {
47
+ globalThis.Neo = {config: {...d}};
48
+ import(d.mainPath)
49
+ })
50
+ ```
51
+
52
+ It performs these steps:
53
+ 1. Fetches the `neo-config.json` file from the current directory
54
+ 2. Parses the JSON response
55
+ 3. Creates a global `Neo` object with the `config` property set to the parsed JSON
56
+ 4. Dynamically imports the module specified by the `mainPath` property from the config
57
+
58
+ ### 3. Configuration: neo-config.json
59
+
60
+ The `neo-config.json` file contains essential configuration for the application bootstrap. For a complete overview
61
+ of all available configuration options, you can refer to the `src/DefaultConfig.mjs` file in the Neo.mjs framework:
62
+
63
+ ```json
64
+ {
65
+ "appPath" : "apps/myapp/app.mjs",
66
+ "basePath" : "../../",
67
+ "environment" : "development",
68
+ "mainPath" : "./Main.mjs",
69
+ "mainThreadAddons": ["Stylesheet"],
70
+ "themes" : ["neo-theme-light"],
71
+ "useCanvasWorker" : false,
72
+ "useDataWorker" : false,
73
+ "useServiceWorker": false,
74
+ "useSharedWorkers": false,
75
+ "useTaskWorker" : false,
76
+ "useVdomWorker" : true,
77
+ "workerBasePath" : "../../src/worker/"
78
+ }
79
+ ```
80
+
81
+ **Key Configuration Properties:**
82
+ - **`appPath`** - Points to your application's entry point (app.mjs)
83
+ - **`basePath`** - Root path for resolving other paths
84
+ - **`environment`** - Controls optimization and debugging features
85
+ - **`mainPath`** - Framework's main thread bootstrap file
86
+ - **`mainThreadAddons`** - Additional features to load in the main thread
87
+ - **`themes`** - CSS themes to load
88
+ - **`useCanvasWorker`** - Controls whether to use a separate worker for canvas operations
89
+ - **`useDataWorker`** - Controls whether to use a separate worker for data operations
90
+ - **`useServiceWorker`** - Controls whether to use a service worker for caching
91
+ - **`useSharedWorkers`** - When set to true, ALL workers (App, VDom, Data, etc.) will be created as SharedWorkers,
92
+ enabling multi-window applications. When false, all workers will be dedicated workers (better for single-page applications).
93
+ The `worker.Base` class provides an abstraction layer that supports both types with a consistent API, allowing developers
94
+ to create an app with dedicated workers first (which are easier to debug) and then switch to shared workers with just
95
+ a one-line configuration change.
96
+ - **`useTaskWorker`** - Controls whether to use a separate worker for background tasks
97
+ - **`useVdomWorker`** - Controls whether to use a separate worker for virtual DOM operations
98
+ - **`workerBasePath`** - Location of worker initialization files
99
+
100
+ **Configuration Categories:**
101
+ - **Path Resolution** - Where to find files and modules (auto-generated by default)
102
+ - **Worker Settings** - Which workers to use and how they should be configured
103
+ - **Theme Management** - CSS themes to load
104
+ - **Addon Loading** - Additional main thread features to load
105
+
106
+ ### 4. Main Thread Initialization
107
+
108
+ The MicroLoader imports `Main.mjs`, which initializes the main thread:
109
+
110
+ ```javascript
111
+ import Neo from './Neo.mjs';
112
+ import * as core from './core/_export.mjs';
113
+ import DomAccess from './main/DomAccess.mjs';
114
+ import DeltaUpdates from './main/DeltaUpdates.mjs';
115
+ import DomEvents from './main/DomEvents.mjs';
116
+ import Observable from './core/Observable.mjs';
117
+ import WorkerManager from './worker/Manager.mjs';
118
+
119
+ class Main extends core.Base {
120
+ // ...
121
+
122
+ construct(config) {
123
+ super.construct(config);
124
+
125
+ let me = this;
126
+
127
+ WorkerManager.on({
128
+ 'automount' : me.onRender,
129
+ 'message:mountDom' : me.onMountDom,
130
+ 'message:updateDom': me.onUpdateDom,
131
+ 'updateVdom' : me.onUpdateVdom,
132
+ scope : me
133
+ });
134
+
135
+ DomEvents.on('domContentLoaded', me.onDomContentLoaded, me);
136
+
137
+ if (document.readyState !== 'loading') {
138
+ DomEvents.onDomContentLoaded()
139
+ }
140
+ }
141
+
142
+ // ...
143
+ }
144
+ ```
145
+
146
+ The Main class:
147
+ 1. Imports the WorkerManager and other core modules
148
+ 2. Sets up event listeners for worker messages
149
+ 3. Listens for the 'domContentLoaded' event
150
+ 4. When the DOM is loaded, it loads any main thread addons and notifies the WorkerManager
151
+
152
+ ### 5. Worker Manager: Creating Workers
153
+
154
+ The `WorkerManager` is responsible for creating and managing the workers:
155
+
156
+ ```javascript
157
+ class Manager extends Base {
158
+ // ...
159
+
160
+ createWorkers() {
161
+ let me = this,
162
+ config = Neo.clone(NeoConfig, true),
163
+ {hash, href, search} = location,
164
+ {windowId} = me,
165
+ key, value;
166
+
167
+ // Configure the workers
168
+ // ...
169
+
170
+ for ([key, value] of Object.entries(me.workers)) {
171
+ if (key === 'canvas' && !config.useCanvasWorker ||
172
+ key === 'task' && !config.useTaskWorker ||
173
+ key === 'vdom' && !config.useVdomWorker
174
+ ) {
175
+ continue
176
+ }
177
+
178
+ try {
179
+ value.worker = me.createWorker(value)
180
+ } catch (e) {
181
+ document.body.innerHTML = e;
182
+ me.stopCommunication = true;
183
+ break
184
+ }
185
+
186
+ me.sendMessage(key, {
187
+ action: 'registerNeoConfig',
188
+ data : {...config, windowId}
189
+ })
190
+ }
191
+ }
192
+
193
+ onWorkerConstructed(data) {
194
+ let me = this;
195
+
196
+ me.constructedThreads++;
197
+
198
+ if (me.constructedThreads === me.activeWorkers) {
199
+ // All workers are constructed, load the application
200
+ NeoConfig.appPath && me.timeout(NeoConfig.loadApplicationDelay).then(() => {
201
+ me.loadApplication(NeoConfig.appPath)
202
+ })
203
+ }
204
+ }
205
+
206
+ loadApplication(path) {
207
+ this.sendMessage('app', {
208
+ action : 'loadApplication',
209
+ path,
210
+ resourcesPath: NeoConfig.resourcesPath
211
+ })
212
+ }
213
+
214
+ // ...
215
+ }
216
+ ```
217
+
218
+ The WorkerManager:
219
+ 1. Detects browser features (Web Workers, SharedWorkers)
220
+ 2. Creates workers for App, VDom, Data, etc. based on configuration
221
+ 3. Sends the Neo.config to each worker
222
+ 4. When all workers are constructed, it loads the application by sending a message to the App worker
223
+
224
+ ### 6. App Worker: Loading the Application
225
+
226
+ The App worker receives the 'loadApplication' message and loads the application. It's important to note that an "App"
227
+ in Neo.mjs is an instance of Neo.controller.Application, which is not common in other frameworks like React, Angular,
228
+ or Vue (which typically just use a tag):
229
+
230
+ ```javascript
231
+ class App extends Base {
232
+ // ...
233
+
234
+ onLoadApplication(data) {
235
+ let me = this,
236
+ {config} = Neo,
237
+ app, path;
238
+
239
+ if (data) {
240
+ me.data = data;
241
+ config.resourcesPath = data.resourcesPath
242
+ }
243
+
244
+ path = me.data.path;
245
+
246
+ if (config.environment !== 'development') {
247
+ path = path.startsWith('/') ? path.substring(1) : path
248
+ }
249
+
250
+ me.importApp(path).then(module => {
251
+ app = module.onStart();
252
+
253
+ // short delay to ensure Component Controllers are ready
254
+ config.hash && me.timeout(5).then(() => {
255
+ HashHistory.push(config.hash);
256
+ })
257
+ })
258
+ }
259
+
260
+ importApp(path) {
261
+ if (path.endsWith('.mjs')) {
262
+ path = path.slice(0, -4)
263
+ }
264
+
265
+ return import(
266
+ /* webpackInclude: /(?:\/|\\)app.mjs$/ */
267
+ /* webpackExclude: /(?:\/|\\)(dist|node_modules)/ */
268
+ /* webpackMode: "lazy" */
269
+ `../../${path}.mjs`
270
+ )
271
+ }
272
+
273
+ // ...
274
+ }
275
+ ```
276
+
277
+ The App worker:
278
+ 1. Receives the 'loadApplication' message with the path to the application
279
+ 2. Calls importApp(path) to dynamically import the application module
280
+ 3. When the module is loaded, it calls the onStart method of the module
281
+ 4. If there's a hash in the config, it pushes it to the HashHistory after a short delay
282
+
283
+ ### 7. Application Entry Point: app.mjs
284
+
285
+ Finally, the application's `app.mjs` file is loaded and executed:
286
+
287
+ ```javascript
288
+ import Overwrites from './Overwrites.mjs'; // Optional framework extensions
289
+ import Viewport from './view/Viewport.mjs'; // Your main UI component
290
+
291
+ export const onStart = () => Neo.app({
292
+ mainView: Viewport, // Root component of your application
293
+ name : 'MyApp' // Application identifier
294
+ })
295
+ ```
296
+
297
+ The app.mjs file:
298
+ 1. Imports any overwrites and the main view (Viewport)
299
+ 2. Exports an onStart function that creates a new Neo application
300
+ 3. The application is configured with a main view and a name
301
+
302
+ ### 8. Component Tree Construction
303
+
304
+ When Neo.app() is called, it creates an Application controller and instantiates your mainView component:
305
+
306
+ ```javascript
307
+ // Your Viewport component
308
+ class Viewport extends Container {
309
+ static config = {
310
+ className: 'MyApp.view.Viewport',
311
+ layout: 'vbox',
312
+ items: [
313
+ HeaderComponent, // Child components
314
+ MainContainer, // All created in App Worker
315
+ FooterComponent
316
+ ]
317
+ }
318
+ }
319
+ ```
320
+
321
+ The component instantiation process:
322
+ 1. Viewport is created in the App Worker
323
+ 2. Child components are instantiated recursively
324
+ 3. Event listeners are attached via the framework's event system
325
+ 4. Data bindings are established for reactive updates
326
+
327
+ ### 9. VDom Generation and Initial Render
328
+
329
+ Once the component tree is built:
330
+
331
+ 1. Each component generates its virtual DOM structure
332
+ 2. The framework builds a complete virtual DOM tree
333
+ 3. The VDom Worker calculates the initial DOM structure
334
+ 4. Relevant CSS files will get lazy-loaded before the DOM is touched to avoid reflows
335
+ 5. The Main Thread creates the actual DOM elements
336
+ 6. The event system is activated
337
+
338
+ ## Summary
339
+
340
+ The Neo.mjs application bootstrap process follows these key steps:
341
+
342
+ 1. **index.html** loads the MicroLoader
343
+ 2. **MicroLoader.mjs** fetches the configuration and imports Neo.Main
344
+ 3. **Neo.Main** initializes the main thread and creates the Neo.worker.Manager
345
+ 4. **Neo.worker.Manager** creates the workers (Neo.worker.App, VDom, Data, etc.)
346
+ 5. When all workers are constructed, Neo.worker.Manager sends a 'loadApplication' message to the Neo.worker.App worker
347
+ 6. **Neo.worker.App** receives the message and dynamically imports the application module
348
+ 7. **app.mjs** is executed, and its onStart function creates the application
349
+ 8. **Component Tree** is constructed in the Neo.worker.App worker
350
+ 9. **VDom Generation and Rendering** processes vdom changes: App Worker sends vdom to VDom Worker, which calculates deltas,
351
+ and Main Thread applies these deltas to the DOM
352
+
353
+ This multi-threaded architecture allows your application code to run in either a dedicated or shared Neo.worker.App worker,
354
+ completely separate from DOM manipulation, providing better performance and responsiveness.