Skip to content

Releases: neomjs/neo

Neo.mjs v10.5.4 Release Notes

18 Aug 11:36
Compare
Choose a tag to compare

Neo.mjs v10.5.3 Release Notes

15 Aug 08:08
Compare
Choose a tag to compare

Bug Fixes

  • grid.Container: Corrected the calculation for the aria-rowcount attribute. The count was previously store.count + 2, and has been adjusted to store.count + 1 to accurately reflect the number of data rows plus the single header row, improving accessibility for screen readers.

Neo.mjs v10.5.2 Release Notes

14 Aug 10:40
Compare
Choose a tag to compare

Features

  • grid.Container: Added the aria-colcount attribute to the grid's wrapper element to enhance accessibility.
  • This attribute dynamically updates with the number of columns, ensuring screen readers can accurately announce the grid's structure.

Enhancements

  • grid.Container: The updateColCount() method now includes a silent parameter. This allows for updating the column count without triggering an immediate DOM update, optimizing performance in scenarios where multiple changes occur in sequence.
  • examples.grid.bigData.ControlsContainer: To improve user feedback, a loading mask is now displayed during the initial data filtering process in the Big Data grid example.

Bug Fixes

  • data.Store: Fixed an issue where the isLoaded flag was not set to true when records were added to the store via
    the add() method. This ensures that the load event is fired correctly, even when the store is populated manually
    instead of through assigning data or autoLoad.

Neo.mjs v10.5.1 Release Notes

13 Aug 10:19
Compare
Choose a tag to compare

Bug Fixes

table.Body

  • Fixed a JavaScript error that occurred when filtering a table's store. A previous change modified the method signature of onStoreLoad() to expect a destructured object containing the store's items. However, the onStoreFilter() method was not updated to reflect this change and continued to call onStoreLoad() without the required arguments.
  • onStoreFilter() now correctly passes the store's data to onStoreLoad(), resolving the error and ensuring that table filtering works as expected.

Neo.mjs v10.5.0 Release Notes

12 Aug 08:03
Compare
Choose a tag to compare

Major Performance Enhancements for Grids and Data Handling

This release introduces a groundbreaking set of performance optimizations for Neo.data.Store and Neo.grid.Container, fundamentally transforming how large datasets are handled within Neo.mjs applications. These enhancements dramatically reduce initial load times, improve UI responsiveness, and resolve critical VDom reconciliation issues, making it feasible to work with millions of data points with unprecedented fluidity.

Key Highlights:

  • Lazy Record Instantiation (GET-driven approach):

    • Neo.data.Store now defers the creation of Neo.data.Record instances. Raw data objects are stored directly, and Record instances are only created on-demand when an item is explicitly accessed (e.g., via store.get(), store.getAt(), or during VDom rendering of visible rows).
    • Impact: This eliminates the massive upfront cost of instantiating millions of Record objects, leading to up to 97% reduction in initial data processing time for large datasets.
  • Configurable Data Chunking for UI Responsiveness:

    • Introduced an initialChunkSize config in Neo.data.Store (default 0). When enabled, Store.add() processes data in chunks, significantly mitigating UI freezes during synchronous loading of extremely large datasets (e.g., 1,000,000+ rows).
    • Impact: Provides a smoother perceived user experience during initial data loads, even for datasets that would otherwise cause multi-second UI blocks.
  • Robust Component ID Management for VDom Stability:

    • Resolved critical VDom reconciliation errors (e.g., RangeError, infinite loops) that could occur with component columns when chunking was active. Neo.grid.column.Component now intelligently generates unique IDs based on the store's chunking state, ensuring VDom stability.
    • Impact: Eliminates a major source of instability and crashes when using component columns with large, dynamically loaded datasets.
  • Automated Component Instance Cleanup:

    • Enhanced Neo.grid.Body with sophisticated component instance management. Components are now automatically destroyed when the grid body is destroyed, the store is cleared, the store changes, or when they scroll out of view after a chunked load.
    • Impact: Reduces memory overhead and improves long-term performance by preventing the accumulation of unused component instances.
  • GPU-Accelerated Vertical Scrolling (translate3d):

    • Grid rows now utilize transform: translate3d(0px, Ypx, 0px) for vertical positioning. This hints to the browser to promote rows to their own composite layers, offloading rendering to the GPU.
    • Impact: Leads to noticeably smoother and more fluid vertical scrolling, especially during rapid movements through large grids.

Other Enhancements:

  • ComboBox Initial Display Fix: Resolved an issue where Neo.form.field.ComboBox instances would appear blank on initial load when backed by lazily instantiated stores. The updateInputValueFromValue method now correctly displays values from raw data or Record instances.
  • Enhanced BigData Grid Example: The examples/grid/bigData demo has been updated to include control options for up to 200 columns, allowing for testing with up to 20,000,000 cells. This provides a more extreme and comprehensive benchmark for grid performance.

These collective improvements mark a significant leap forward in Neo.mjs's capability to handle and display massive amounts of data with high performance and a superior user experience.


Performance Benchmarks (from examples/grid/bigData):

Scenario Before (Eager Instantiation) After (Lazy Instantiation, with chunking) After (Lazy Instantiation, no chunking)
1,000 rows, 50 columns 49ms (Record creation) 2ms (Data gen + add) 2ms (Data gen + add)
50,000 rows, 50 columns 2391ms (Record creation) 1252ms (Data gen + add) 93ms (Data gen + add)
50,000 rows, 100 columns 4377ms (Record creation) 1289ms (Data gen + add) 95ms (Data gen + add)
100,000 rows, 50 columns N/A (too slow) 1299ms (Data gen + add) 156ms (Data gen + add)
100,000 rows, 200 columns N/A (too slow) 1427ms (Data gen + add) 174ms (Data gen + add)

Note: "Record creation" refers to the time taken for Neo.data.Record instantiation. "Data gen + add" refers to the time taken to generate raw data and add it to the store's collection.

Important Note on Chunking:
The introduction of lazy record instantiation significantly reduces the need for chunking in most common use cases, as the initial data loading is now extremely fast even for large datasets. However, Neo.mjs still optionally supports data chunking via the initialChunkSize config for scenarios involving truly massive synchronous data additions where mitigating UI freezes is paramount.

Try it out by yourself:
https://neomjs.com/examples/grid/bigData/index.html
https://neomjs.com/dist/production/examples/grid/bigData/index.html

All changes combined into 1 Commit: 5d4760b

Neo.mjs v10.4.1 Release Notes

11 Aug 12:34
Compare
Choose a tag to compare

Highlights

This patch release polishes the "instant preview" feature for grids introduced in v10.4.0, ensuring the grid's scrollbar and accessibility properties are correctly sized from the very first paint when loading large datasets. The non-buffered table.Body also receives a major performance boost for clearing data.

Enhancements & Bug Fixes

1. Polished "Instant Preview" for Large Datasets in Grids

The chunked loading mechanism for stores and grids has been refined. When adding a large dataset, the initial load event now carries the final total record count. The grid.Container uses this information immediately to set the correct aria-rowcount and to size the vertical scrollbar accurately, preventing layout shifts and providing a more stable and accessible user experience from the very first render.

2. Standardized Internal Store load Event

To support the "instant preview" refinements, the data.Store load event payload has been standardized internally. It now consistently uses an object containing an items property (e.g., {items: [...]}). Framework components have been updated to use this new signature.

3. Performance Fast Path for table.Body

The non-buffered table.Body is now significantly faster when clearing its data. It uses the same "fast path" optimization as grid.Body, directly clearing the DOM instead of processing a large and unnecessary VDOM diff when an empty dataset is loaded. This aligns the performance of the two components.

Neo.mjs v10.4.0 Release Notes

11 Aug 10:40
Compare
Choose a tag to compare

Highlights

This release focuses heavily on performance and robustness, especially when dealing with very large datasets in collections, stores, and grids. Key improvements include non-blocking chunked data loading for stores, a fix for stack overflow errors when adding large arrays to collections, and significant optimizations for grid scrolling and data clearing.

Enhancements

1. High-Performance Chunking for Store.add()

To prevent the UI from freezing when adding massive datasets (e.g., 1M+ records), Store.add() now uses a two-chunk loading strategy. It first adds a small "interactive" batch of records to make the UI responsive almost instantly. It then silently adds the remaining data in the background by leveraging the suspendEvents flag, and fires a final load event to update the UI (e.g., grid scrollbars) once complete. This ensures a non-blocking, highly responsive user experience.

2. Refactored Grid ScrollManager for Smoother Scrolling

The grid.ScrollManager has been refactored to use the framework's built-in delayable system instead of manual setTimeout logic. Both vertical and horizontal scroll event handlers are now throttled to align with a 60fps refresh rate, and a debounced onBodyScrollEnd handler efficiently manages the isScrolling state. This results in smoother scrolling, more consistent behavior, and cleaner, more maintainable code.

3. Grid onStoreLoad Fast Path for Instant Clearing

A performance "fast path" has been added to the grid.Body for scenarios where a store is cleared. Instead of performing a full VDOM diff between the existing rows and an empty dataset, the grid now detects this specific case and directly clears the VDOM and the real DOM. This reduces the time to clear a large grid from ~13ms to a near-instantaneous operation.

Bug Fixes

1. Fixed collection.Base#splice Stack Overflow

A RangeError: Maximum call stack size exceeded would occur when adding a very large number of items (e.g., >100k) to an already populated collection at runtime. This was caused by using the spread operator (...) on a massive array. The splice method now intelligently switches to a safer concat()-based approach for large arrays, preventing the crash while retaining the high performance of native splice for smaller arrays.

2. Fixed collection.Base#construct Race Condition

A race condition was fixed where methods on a collection could be called during instantiation before the collection's internal properties were initialized. The construct method's logic was reordered to ensure all internal properties are defined before the parent constructor is called, making the class more robust and preventing subtle bugs during component initialization.

Neo.mjs v10.3.4 Release Notes

09 Aug 07:53
Compare
Choose a tag to compare

This patch release enhances the build-all script to only copy generated docs output into dist envs, in case the
docs app does exist (might not be the case inside custom workspaces).

Neo.mjs v10.3.4 Release Notes

09 Aug 07:13
Compare
Choose a tag to compare

This patch release addresses a critical bug in the grid component that caused stale data to be displayed, along with several build process enhancements and minor documentation corrections.

Bug Fixes

  • Grid Cells Displayed Stale Data After Record Updates

    • Fixed a significant issue in Neo.grid.Body where surgically updating a record's data (e.g., via record.set()) would not visually update the corresponding grid cells if the grid was scrolled. The component was attempting to update VDOM nodes for rows outside the currently rendered (mounted) range, leading to a visual desynchronization between the store and the UI.
    • The onStoreRecordChange method now ensures that cell updates are only performed for rows that are currently visible or within the buffered render range, guaranteeing that the UI always reflects the latest data state.
    • See: GitHub Issue #7070
  • Functional Component Event Handling

    • Corrected an event propagation issue in the functional nested template component example (examples/functional/nestedTemplateComponent/Component.mjs). Clicks on a button within the component were not being handled correctly, and this has now been resolved.

Enhancements & Build System

  • Smarter Docs App Detection

    • The webpack configuration (buildScripts/webpack/development/webpack.config.appworker.mjs, buildScripts/webpack/production/webpack.config.appworker.mjs) now uses a more precise check (docs/app) to detect the presence of the documentation application. This prevents unnecessary build steps if only the output folder (docs/output) exists.
    • See: GitHub Issue #7171
  • Optimized Docs Generation

    • The main build script (buildScripts/buildAll.mjs) will no longer attempt to generate the docs JSON output if the docs application itself is not present in the workspace. This streamlines the build process for projects that do not include the docs app.
    • See: GitHub Issue #7172
  • Documentation Corrections

    • Fixed a typo in a blog post title within the portal application's data.
    • Corrected a method name in the "The Surgical Update: From JSON Blueprints to Flawless UI" blog post from render() to createVdom() for accuracy.

Neo.mjs v10.3.3 Release Notes

04 Aug 09:18
Compare
Choose a tag to compare

This patch release introduces a major new deep-dive article on our rendering architecture and enhances our framework comparison documentation.

New Content & Documentation

  • New Blog Post: The Surgical Update: From JSON Blueprints to Flawless UI

    • A comprehensive deep dive into the Neo.mjs off-thread rendering engine.
    • Explores key concepts like the secure DomApiRenderer, asymmetric update batching, and how our architecture preserves DOM state (e.g., for a playing <video>).
    • This is the fourth article in the v10 blog post series.
  • Enhanced Framework Comparisons

    • The comparison documents for React, Vue, and Angular have been updated with a new section: "Component Mobility: Portals vs. True Persistence."
    • This section details the architectural advantages of Neo.mjs's persistent component model for moving stateful DOM elements, a common challenge for single-threaded frameworks.