neo.mjs 10.0.0-alpha.3 → 10.0.0-alpha.5

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