neo.mjs 9.13.0 → 9.14.0
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.
- package/ServiceWorker.mjs +2 -2
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/home/parts/Features.mjs +2 -2
- package/apps/portal/view/home/parts/How.mjs +2 -2
- package/package.json +1 -1
- package/resources/data/deck/learnneo/pages/benefits/FourEnvironments.md +206 -0
- package/resources/data/deck/learnneo/tree.json +3 -2
- package/src/DefaultConfig.mjs +2 -2
- package/src/vdom/Helper.mjs +2 -2
- /package/resources/data/deck/learnneo/pages/benefits/{Multi-Window.md → MultiWindow.md} +0 -0
- /package/resources/data/deck/learnneo/pages/benefits/{Multi-Threading.md → OffTheMainThread.md} +0 -0
package/ServiceWorker.mjs
CHANGED
@@ -31,7 +31,7 @@ class Features extends BaseContainer {
|
|
31
31
|
*/
|
32
32
|
items: [{
|
33
33
|
header: 'Multi-threading',
|
34
|
-
route : '#/learn/benefits.
|
34
|
+
route : '#/learn/benefits.OffTheMainThread',
|
35
35
|
|
36
36
|
content: [
|
37
37
|
'Following the OMT (Off the Main-Thread) paradigm',
|
@@ -42,7 +42,7 @@ class Features extends BaseContainer {
|
|
42
42
|
]
|
43
43
|
}, {
|
44
44
|
header: 'Multi-Window Apps',
|
45
|
-
route : '#/learn/benefits.
|
45
|
+
route : '#/learn/benefits.MultiWindow',
|
46
46
|
|
47
47
|
content: [
|
48
48
|
'No need for a Native Shell (e.g. Electron)',
|
@@ -33,9 +33,9 @@ class How extends FeatureSection {
|
|
33
33
|
*/
|
34
34
|
headline: 'How?',
|
35
35
|
/**
|
36
|
-
* @member {String} learnMoreRoute='#/learn/
|
36
|
+
* @member {String} learnMoreRoute='#/learn/benefits.OffTheMainThread'
|
37
37
|
*/
|
38
|
-
learnMoreRoute: '#/learn/benefits.
|
38
|
+
learnMoreRoute: '#/learn/benefits.OffTheMainThread',
|
39
39
|
/**
|
40
40
|
* @member {String} paragraph
|
41
41
|
*/
|
package/package.json
CHANGED
@@ -0,0 +1,206 @@
|
|
1
|
+
## Introduction
|
2
|
+
|
3
|
+
Neo.mjs was the very first frontend framework, which enabled full support for a zero builds instant development mode,
|
4
|
+
while sticking to the latest ECMAScript features (e.g. the ES6 class system, modules and dynamic imports).
|
5
|
+
|
6
|
+
Developers can save massive amounts of time when creating and debugging their apps, but at some point apps want to be
|
7
|
+
deployed. To do this right, it is crucial to have an overview of the available environments.
|
8
|
+
|
9
|
+
## Zero builds development mode
|
10
|
+
|
11
|
+
JavaScript was originally conceived as the sole programming language capable of running directly within web browsers,
|
12
|
+
defining the interactive web experience. By around the year 2012, JS evolved significantly faster outside the Browser in
|
13
|
+
environments like Node.js, free from the constraints of browser release cycles and offering access to a broader set of APIs.
|
14
|
+
Developers, naturally wanting to use the latest language features, and especially Angular and React, picked up on this,
|
15
|
+
moving the entire frontend development into Node.js. This way, the new features were available, but at the significant
|
16
|
+
cost of introducing a mandatory, and often complex, build step, since developers now wrote code which Browsers can not
|
17
|
+
understand.
|
18
|
+
|
19
|
+
Over time, an entire ecosystem evolved around this paradigm. Think of hot module replacements, the webpack-dev-server,
|
20
|
+
Vite, or Bun. While builds have become reasonably fast, developers receive transpiled and bundled code in the Browsers,
|
21
|
+
which can introduce debugging challenges and requires source-maps to even have a chance of debugging.
|
22
|
+
|
23
|
+
What most companies and developers have completely missed is the fact that Browser Vendors have done a great job at
|
24
|
+
catching up with modern ECMAScript features (like classes, dynamic imports, and native browser module support).
|
25
|
+
At this point in time, we can create highly modern and performant code directly inside Browsers again.
|
26
|
+
|
27
|
+
Especially when it comes to debugging, the advantages are huge: No source-maps are needed, and developers can work with
|
28
|
+
the real code, even inside the dev-tools console.
|
29
|
+
|
30
|
+
Neo.mjs picks up on this pattern, and even supports the full creation of apps directly inside the console. Developers can
|
31
|
+
easily grab existing Component instances inside the console, inspect and change reactive configs on the fly, and watch
|
32
|
+
the UI update instantly – even within a multi-window scope, or creating entirely new components directly.
|
33
|
+
|
34
|
+
This is possible because Neo.mjs is ***100% based on web standards***. There's ***no hidden magic*** or proprietary syntax;
|
35
|
+
you're working directly with what the browser understands. This commitment to standards provides a level of transparency
|
36
|
+
and future-proofing that's hard to match.
|
37
|
+
|
38
|
+
Sticking exclusively to the builds dev-mode paradigm means relying on an abstraction layer that moves away from the
|
39
|
+
browser's native capabilities. History has shown the advantages of embracing the web platform directly, as seen with the
|
40
|
+
evolution from plugin-based solutions to native browser features. Neo.mjs champions this direct, standards-aligned
|
41
|
+
approach, providing a future-proof development experience.
|
42
|
+
|
43
|
+
## dist/esm: Embracing Native ES Modules for Modern Deployment
|
44
|
+
|
45
|
+
While Neo.mjs's zero-builds development mode offers unmatched speed and debugging clarity, deploying your application
|
46
|
+
effectively for the world requires a different set of considerations. This is where the **`dist/esm`** environment steps in:
|
47
|
+
it represents the optimal bridge between raw development efficiency and a robust, modern deployment.
|
48
|
+
|
49
|
+
The `dist/esm` environment allows you to deploy your Neo.mjs application as a collection of native ES Modules.
|
50
|
+
This means you're not shipping a single, monolithic JavaScript bundle, but rather smaller, individual module files.
|
51
|
+
|
52
|
+
### Identical Code Structure to Dev Mode
|
53
|
+
|
54
|
+
A standout feature of `dist/esm` is that it preserves the exact same file and folder structure as your development mode.
|
55
|
+
This means the code you deploy is the same code you develop and debug. There are no opaque bundling transformations, no complex source map deciphering; what you see in your IDE is precisely what's running in the browser. This unparalleled fidelity dramatically simplifies debugging and vastly reduces "it works on my machine" scenarios.
|
56
|
+
|
57
|
+
### Native Modularity, Uncompromised
|
58
|
+
|
59
|
+
`dist/esm` fully embraces native ES Module support in modern browsers. Each class and utility remains its own module,
|
60
|
+
directly loaded by the browser as needed. This aligns perfectly with the "100% web standards" philosophy of Neo.mjs – no
|
61
|
+
proprietary bundlers or complex configurations obscuring your code.
|
62
|
+
|
63
|
+
### Leveraging HTTP/2 & HTTP/3 for Efficiency
|
64
|
+
|
65
|
+
With the capabilities of modern protocols like HTTP/2 and HTTP/3, serving numerous small module files becomes incredibly
|
66
|
+
efficient. Browsers can fetch these modules in parallel, often leading to faster initial load times and significantly
|
67
|
+
improved caching granularity compared to large, single bundles.
|
68
|
+
|
69
|
+
### Optimized On-Demand Delivery for Dynamic UIs
|
70
|
+
|
71
|
+
When your application needs to render a new component or view based on a JSON blueprint (whether manually crafted,
|
72
|
+
backend-generated, or dynamically produced), the framework efficiently fetches only the specific component modules
|
73
|
+
required for that UI, without loading unnecessary code upfront. This ensures optimized resource usage and faster
|
74
|
+
rendering for dynamic content.
|
75
|
+
|
76
|
+
### Unparalleled Debugging in Production
|
77
|
+
|
78
|
+
Since the code remains in its modular, unbundled form (though optimized compared to dev mode), debugging issues in a
|
79
|
+
live `dist/esm` environment is dramatically simpler. You're working directly with the actual files and module structure.
|
80
|
+
|
81
|
+
### Seamless Shared Worker Integration
|
82
|
+
|
83
|
+
The same modular `dist/esm` code is efficiently loaded into both the main thread and the application worker(s), ensuring
|
84
|
+
consistent environments and maximizing the benefits of multi-threading for responsive interfaces.
|
85
|
+
|
86
|
+
**This multi-threaded architecture is a core differentiator of Neo.mjs, enabling powerful patterns discussed further in
|
87
|
+
our blog post:</br>
|
88
|
+
<a href="https://itnext.io/the-ui-revolution-how-json-blueprints-shared-workers-power-next-gen-ai-interfaces-60a2bf0fc1dc?source=friends_link&sk=1b0b306285e23bb12f31271dd87bebe5">How JSON Blueprints & Shared Workers Power Next-Gen AI Interfaces</a>.**
|
89
|
+
|
90
|
+
In essence, `dist/esm` is about deploying your Neo.mjs application with the future of the web in mind: native, modular,
|
91
|
+
performant, and transparent. It's ideal for environments where modern server capabilities can efficiently serve
|
92
|
+
individual ES module files, giving you a deployment that's fast, flexible, and exceptionally easy to maintain and debug.
|
93
|
+
|
94
|
+
## dist/production: Optimized Bundles for Broadest Reach and Ultimate Minification
|
95
|
+
|
96
|
+
While the dist/esm environment champions the future of native browser modules, the `dist/production` environment caters
|
97
|
+
to scenarios demanding the broadest compatibility, ultimate minification, and traditional single-file deployment benefits.
|
98
|
+
|
99
|
+
This environment utilizes Webpack, an industry-standard bundler, to process your application's code. However, true to
|
100
|
+
Neo.mjs's multi-threaded architecture, this bundling process is intelligently designed:
|
101
|
+
|
102
|
+
### Thread-Specific Bundles
|
103
|
+
|
104
|
+
Instead of creating a single, monolithic JavaScript file for your entire application, `dist/production` generates separate,
|
105
|
+
optimized bundles for each distinct thread context: a dedicated bundle for the main thread, containing only the code
|
106
|
+
necessary for the DOM bridge, event handling, and initial application setup, and a separate bundle for the application
|
107
|
+
worker(s), containing all the application logic, Vdom processing, and state management that operates off the main thread.
|
108
|
+
|
109
|
+
### Reduced Overhead per Thread
|
110
|
+
|
111
|
+
This unique thread-specific bundling significantly reduces overhead. Each thread only loads and parses the JavaScript
|
112
|
+
code that is strictly relevant to its operations. The main thread doesn't waste resources parsing complex application
|
113
|
+
logic, and the worker isn't burdened with parsing main-thread-specific DOM manipulation code. This contributes to
|
114
|
+
faster startup times and more efficient memory usage in each isolated thread.
|
115
|
+
|
116
|
+
### Aggressive Optimizations
|
117
|
+
|
118
|
+
The Webpack build pipeline in `dist/production` applies aggressive optimizations such as:
|
119
|
+
|
120
|
+
* ***Minification & Uglification***: Stripping away whitespace, shortening variable names, and performing other
|
121
|
+
transformations to achieve the smallest possible file sizes.
|
122
|
+
* ***Dead Code Elimination*** (Tree Shaking): Removing any code that is not actually used by the application, further
|
123
|
+
reducing bundle size.
|
124
|
+
|
125
|
+
### Broadest Browser Compatibility
|
126
|
+
|
127
|
+
Bundling typically includes polyfills and transpilation for older ECMAScript features, ensuring your application runs
|
128
|
+
smoothly even on browsers that don't fully support the latest web standards (which dist/esm relies upon).
|
129
|
+
|
130
|
+
### Simplified Single-File Deployment
|
131
|
+
For environments where serving multiple module files isn't optimal, or for legacy server setups, `dist/production`
|
132
|
+
provides the convenience of deploying just a few highly optimized bundle files.
|
133
|
+
|
134
|
+
In summary, `dist/production` is Neo.mjs's answer for maximum compatibility and minimal payload, offering a robust,
|
135
|
+
Webpack-powered build that respects the framework's multi-threaded nature to deliver highly optimized bundles for each
|
136
|
+
part of your application.
|
137
|
+
|
138
|
+
## dist/development: The Classic "Dev Mode"
|
139
|
+
|
140
|
+
The `dist/development` environment is Neo.mjs's response to what most other JavaScript frameworks—like Angular, React,
|
141
|
+
Vue, or Solid—typically refer to as their "development mode." This environment generates a bundled but unminified version
|
142
|
+
of your application, designed for a more traditional development workflow that includes a build step.
|
143
|
+
|
144
|
+
You'll primarily find yourself needing `dist/development` in very specific scenarios:
|
145
|
+
|
146
|
+
### Debugging Production-Specific Issues
|
147
|
+
|
148
|
+
This mode acts as a vital bridge for debugging. If a bug surfaces in your dist/production build that didn't appear in your
|
149
|
+
zero-builds development mode (a rare occurrence, but possible with aggressive optimizations), `dist/development` allows
|
150
|
+
you to pinpoint the issue in a more readable, albeit bundled, format. Importantly, this mode generates source maps for
|
151
|
+
both JavaScript and CSS, which are crucial for debugging bundled code by mapping it back to your original source files.
|
152
|
+
|
153
|
+
### TypeScript Preference
|
154
|
+
|
155
|
+
For developers who strongly prefer building their applications using TypeScript, this is the environment where you'll
|
156
|
+
typically work. Keep in mind, however, that opting for TypeScript compilation in this mode means sacrificing the
|
157
|
+
instantaneous, zero-builds development experience that Neo.mjs uniquely offers. It introduces a build step for every
|
158
|
+
code change, a trade-off that many Neo.mjs developers find unnecessary given the framework's native ES module support.
|
159
|
+
|
160
|
+
In essence, `dist/development` offers a familiar, bundled development experience for those who need it, serving as a
|
161
|
+
debugging aid for production builds or an option for TypeScript users, but it comes at the cost of Neo.mjs's signature
|
162
|
+
instant development flow.
|
163
|
+
|
164
|
+
## Environment Combinations
|
165
|
+
|
166
|
+
Understanding Neo.mjs's four distinct environments is crucial, but it's equally important to grasp how they interact,
|
167
|
+
especially when your application needs to load additional, code-based modules dynamically—for instance, code written by
|
168
|
+
users within a Monaco editor that contains its own import statements. These scenarios present a unique challenge: how
|
169
|
+
does the framework ensure consistent and correct module loading across different deployment contexts?
|
170
|
+
|
171
|
+
Neo.mjs's architecture handles this by defining specific loading behaviors for dynamically acquired code, ensuring
|
172
|
+
compatibility while maintaining integrity:
|
173
|
+
|
174
|
+
### Loading Behavior for Dynamic Code Modules
|
175
|
+
|
176
|
+
* ***Zero Builds Development Mode***: Dynamically loaded code-based modules will, naturally, load from the dev mode
|
177
|
+
structure itself, leveraging its instant, direct-from-source capabilities.
|
178
|
+
* `dist/esm`: When running in the `dist/esm` environment, dynamically loaded code-based modules will be sourced from
|
179
|
+
the dist/esm structure. This means your application consistently utilizes native ES Modules for both its core and any
|
180
|
+
dynamically extended functionalities.
|
181
|
+
* `dist/development`: Surprisingly, when running in the `dist/development` environment (the Webpack-bundled, unminified
|
182
|
+
version), dynamically loaded code-based modules will revert to loading from the dev mode structure. This is because
|
183
|
+
dist/development bundles your primary application code, but it doesn't pre-bundle every potential dynamic extension.
|
184
|
+
Relying on the dev mode for these ensures they are unminified and retain debugging fidelity.
|
185
|
+
* `dist/production`: Similarly, if your core application is deployed in `dist/production` (the fully optimized Webpack
|
186
|
+
bundle), dynamically loaded code-based modules will be sourced from the `dist/esm` structure. This is the optimal fallback,
|
187
|
+
as `dist/esm` provides highly performant, modular, and standards-compliant loading for individual files, which is critical
|
188
|
+
for code that wasn't part of the initial production bundle.
|
189
|
+
|
190
|
+
### Handling Overhead and Ensuring Integrity
|
191
|
+
|
192
|
+
This mixed loading approach inevitably introduces a degree of overhead, as dynamically loaded modules might result in
|
193
|
+
additional network requests depending on the environment. However, Neo.mjs has a robust mechanism in place to guarantee
|
194
|
+
application integrity and prevent conflicts:
|
195
|
+
|
196
|
+
### The Neo.setupClass() Guarantee
|
197
|
+
|
198
|
+
Core to Neo.mjs's class system is the `Neo.setupClass()` method. This method serves as the central registry for all classes
|
199
|
+
within your application. When a class is defined or dynamically loaded, `Neo.setupClass()` acts as a gatekeeper, ensuring
|
200
|
+
that only the very first module with a given namespace "wins" and is registered.
|
201
|
+
|
202
|
+
This mechanism effectively prevents any duplication of classes or components across your application, regardless of
|
203
|
+
whether they are part of the core build or dynamically loaded. For instance, you could never have multiple instances of
|
204
|
+
a critical utility like an `IDGenerator` registered under the same namespace, as this would inevitably lead to application
|
205
|
+
breakage and unpredictable behavior. `Neo.setupClass()` acts as a safeguard, ensuring a single, authoritative definition
|
206
|
+
for each class, maintaining the application's stability and consistency even in complex, mixed-environment scenarios.
|
@@ -2,10 +2,11 @@
|
|
2
2
|
{"name": "Welcome!", "parentId": null, "id": "Welcome" },
|
3
3
|
{"name": "Benefits", "parentId": null, "isLeaf": false, "id": "Benefits"},
|
4
4
|
{"name": "Introduction ", "parentId": "Benefits", "id": "benefits.Introduction"},
|
5
|
-
{"name": "Off the Main Thread", "parentId": "Benefits", "id": "benefits.
|
5
|
+
{"name": "Off the Main Thread", "parentId": "Benefits", "id": "benefits.OffTheMainThread"},
|
6
|
+
{"name": "4 Environments", "parentId": "Benefits", "id": "benefits.FourEnvironments"},
|
6
7
|
{"name": "Unified Config System", "parentId": "Benefits", "id": "benefits.ConfigSystem"},
|
7
8
|
{"name": "Extreme Speed", "parentId": "Benefits", "id": "benefits.Speed"},
|
8
|
-
{"name": "Multi-Window Applications", "parentId": "Benefits", "id": "benefits.
|
9
|
+
{"name": "Multi-Window Applications", "parentId": "Benefits", "id": "benefits.MultiWindow"},
|
9
10
|
{"name": "Quick Application Development", "parentId": "Benefits", "id": "benefits.Quick"},
|
10
11
|
{"name": "Complexity and Effort", "parentId": "Benefits", "id": "benefits.Effort"},
|
11
12
|
{"name": "Forms Engine", "parentId": "Benefits", "id": "benefits.FormsEngine"},
|
package/src/DefaultConfig.mjs
CHANGED
@@ -264,12 +264,12 @@ const DefaultConfig = {
|
|
264
264
|
useVdomWorker: true,
|
265
265
|
/**
|
266
266
|
* buildScripts/injectPackageVersion.mjs will update this value
|
267
|
-
* @default '9.
|
267
|
+
* @default '9.14.0'
|
268
268
|
* @memberOf! module:Neo
|
269
269
|
* @name config.version
|
270
270
|
* @type String
|
271
271
|
*/
|
272
|
-
version: '9.
|
272
|
+
version: '9.14.0'
|
273
273
|
};
|
274
274
|
|
275
275
|
Object.assign(DefaultConfig, {
|
package/src/vdom/Helper.mjs
CHANGED
@@ -393,7 +393,7 @@ class Helper extends Base {
|
|
393
393
|
}
|
394
394
|
|
395
395
|
Object.entries(attributes).forEach(([key, value]) => {
|
396
|
-
if (this.voidAttributes.
|
396
|
+
if (this.voidAttributes.has(key)) {
|
397
397
|
if (value === 'true') { // vnode attribute values get converted into strings
|
398
398
|
string += ` ${key}`
|
399
399
|
}
|
@@ -559,7 +559,7 @@ class Helper extends Base {
|
|
559
559
|
case 'minHeight':
|
560
560
|
case 'minWidth':
|
561
561
|
case 'width':
|
562
|
-
if (me.rawDimensionTags.
|
562
|
+
if (me.rawDimensionTags.has(node.nodeName)) {
|
563
563
|
node.attributes[key] = value + ''
|
564
564
|
} else {
|
565
565
|
hasUnit = value != parseInt(value);
|
File without changes
|
/package/resources/data/deck/learnneo/pages/benefits/{Multi-Threading.md → OffTheMainThread.md}
RENAMED
File without changes
|