Repository navigation
Faster In-Context Editing, and Steadier Rolling Deploys #5558
BoDonkey
announced in
Release Notes
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
When first posted, this announcement mentioned a lighter admin UI JavaScript bundle. That has been postponed to September because it is a feature, not a fix, and this is a maintenance release.
Hello Apostrophe Community!
Apostrophe 4.32.1 is a maintenance release: a focused round of performance work and fixes, hence the patch version number change. It contains two security fixes (see the Changelog below for details), so we recommend an update as soon as practical.
A Leaner Admin UI
The logged-in admin UI JavaScript bundle is roughly 200KB smaller minified — about 90KB gzipped — with no change in behavior. Two dependencies came out of it:.
lodashis CommonJS and not tree-shakeable, so importing a single function pulled the entire library into the bundle;@paralleldrive/cuid2brought its own dependencies along with it. The small set of utilities the browser actually needed now lives in a dependency-free module in core, fuzz-tested against the original implementations. Every editor loading the admin interface gets a faster start, on every page.Speaking of which, we should mention one requirement that came into play starting last month: Apostrophe now requires Node.js 22.12 or newer. This requirement doesn’t really come from us: Node.js 20.x is officially unsupported and should not be used in any case, and older versions of Node.js 22 should not be used because they do not have the fixes in more recent releases, including security fixes. So with that in mind, we are now taking advantage of features requiring up to date releases of Node.js 22 or better.
Faster In-Context Editing
Two changes make editing widgets on the page noticeably quicker. Patches to deeply nested properties have been optimized, so an edit to a single widget in context no longer costs the same as saving the entire page through the page settings dialog. Separately, widget preview rendering is now properly debounced: when the server hasn't returned a first preview before a second one is requested, Apostrophe waits for the render in flight and then works from the latest data rather than stacking requests. For widgets that are slow or expensive to preview, this meaningfully reduces server load.
We're treating both as fixes rather than features. The nested-property issue in particular was acute enough to prevent effective editing in some cases.
We will continue to deliver optimizations in this area.
Steadier Rolling Deploys
Schema field
_idvalues are now derived from a field's position in the schema tree, such asdoc.article.pets.petName, rather than hashed from the field definition. Under the old scheme, editing an unrelated property like a label changed the hash, so two processes running slightly different code (— exactly what happens during a rolling deploy) — disagreed about ids, and a field id the browser already held could be rejected as invalid. Position-based ids only change when a field is genuinely renamed or moved, and they have the pleasant side effect of being readable when you're debugging.For developers:
apos.schema.registernow requires a fourthparentPathargument and throws if it's missing. If you've overridden a method that calls it, pass the argument through — the error message includes guidance. No migration is needed:scopedArrayNameandscopedObjectNamekeep their existing form for now, since they're stored in the database on every array item and object.Additional Improvements
piecesFilterswithstatic: trueno longer revert to the unfiltered index for logged-in editors who have clicked Edit. Both the browser URL and the filtered content now survive a refresh.box-sizingon Apostrophe elements. Vite builds were unaffected.Set-Cookieheader. Thanks to Erika for this fix.AposTemplate.astroalso now forwards additional props through to the resolved page template component, matching howAposAreaandAposWidgetalready behaved.How to Update
Update your projects with
npm updateand let us know what you think on our roadmap.The “stable” option
Our Hosting, Pro and Assembly customers also have the option of following our “stable” releases. The difference is simple: The stable releases receive new features one full quarter later, but receive bug fixes and security fixes at the same time as “latest.” In order for this to be an effective technique to increase stability, customers still need to actively evaluate “latest” so that they have meaningful head start on what is coming in “stable.” Customers interested in following this path should reach out for complete information on how to point their dependencies to “stable.”
Everything we ship as “latest” is 100% ready for production. The “stable” series is an option for those with a large investment in training, automated testing, etc. It allows delayed implementation of new features without falling behind on fixes.
🚀 Happy coding!
Apostrophe 4.32.1
Changes
Schema field
_idproperties are now derived from the position of the field in the schema tree, such asdoc.article.pets.petName, rather than hashed from the field definition. Ids hashed from the definition changed whenever an unrelated property such as a label was edited, so two processes running slightly different code, as during a rolling deploy, did not agree on them and a field id already held by the browser could be rejected as invalid. Position-based ids only change when a field is renamed or moved, and are readable when debugging.apos.schema.registernow requires a fourthparentPathargument and throws if it is missing. If you have overridden a method that callsapos.schema.registeryou must pass it through; the error message includes guidance.The
scopedArrayNameandscopedObjectNameproperties are unchanged, keeping their existing form and continuing to honor thearrayNameandobjectNameoptions, because they are stored in the database on every array item and object. No migration is required.Fixes
piecesFiltersnavigation (withstatic: true) reverting to the unfiltered index when logged in and an editor had clicked Edit at least once. It now recognizes filter path segments appended to the context doc's URL and preserves both the browser URL and the correctly filtered content on refresh.emailschema field now validates and stores the laundered value, so surrounding whitespace is trimmed rather than causing a valid address to be rejected as invalid. Non-string input (for example a number sent through the REST API) is now coerced by the launder step instead of throwing an uncaught error. Thanks to spokodev for the fix.box-sizingfor.apos-elements. Sass is now compiled withcharset: falsein webpack builds, so the marker is never emitted. Vite builds were unaffected.Security
apos.util.set()andapos.util.get()refused the__proto__,constructorandprototypesegments, but followed every other property inherited fromObject.prototypeandArray.prototype. An authenticated editor could send a single PATCH REST API request with a body of{ "toString.call": "x" }to reach the sharedObject.prototype.toStringfunction and shadow itscallmethod, breaking every laterObject.prototype.toString.call()in the process, including those inside the MongoDB driver: one request took the site down until it was restarted. Both methods now traverse own properties only, which confines a dot path to the request body and the document being patched. All users should update. Thanks to Fabian Bräunlein of Positive Security for reporting the vulnerability.Free Modules
@apostrophecms/apostrophe-astro1.15.0This module integrates ApostropheCMS into your Astro application.
Adds
AposTemplate.astronow forwards any additional props passed to it (beyondaposData) to the resolved page template component, matching the existing behavior ofAposAreaandAposWidget.Fixes
aposProxy.js(e.g. OAuth login callbacks) lost every header exceptLocation. This affected setups where Apostrophe is only reachable through the Astro proxy (e.g. a sidecar deployment), causing the sessionSet-Cookieheader from an OAuth callback redirect to be silently dropped and the login to appear to fail.aposResponse.jsto remove entity headers describing the body when dropping the body (e.g. redirects) which may otherwise cause strict clients to hang waiting for bytes. Thanks to Erika for this fix.All reactions