Unpoly 3.5.0 released #549
triskweline
announced in
Announcements
Replies: 2 comments
-
Fantastic release, thanks a ton! It's been interesting watching the commits over the last few months. |
Beta Was this translation helpful? Give feedback.
0 replies
-
Woah! I'm always amazed by how much you work on this and the love, effort, and thoguht you put into every part. Amazing! |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Unpoly 3.5 brings major quality-of-life improvements and addresses numerous edge cases in existing functionality.
Notification flashes
You can now use an
[up-flashes]
element to render confirmations, alerts or warnings.To render a flash message, include an
[up-flashes]
element in your response.The element's content should be the messages you want to render:
An
[up-flashes]
element comes with useful default behavior for rendering notifications:[up-hungry]
).[up-flashes]
container.You can use a compiler to clear messages after a delay.
will be shown on a parent layer.
See notification flashes for more details and examples.
Detection of changed scripts and styles
Unpoly now detects changes in your JavaScripts and stylesheets after deploying a new version of your application.
While rendering new content, Unpoly compares script and style elements in the
<head>
and emits anup:assets:changed
event if anything changed.It is up to you to handle new frontend code revisions, e.g. by loading new assets or notifying the user.
See handling asset changes for more details and examples.
Automatic update of meta tags {#meta-tags}
Render passes that update history now synchronize meta tags in the
<head>
, such asmeta[name=description]
orlink[rel=canonical]
.In the document below, the highlighted elements will be updated when history is changed, in additional to the location URL:
The linked JavaScript and stylesheet are not part of history state and will not be updated.
Consistent behavior in overlays
Overlays with history now update meta tags when opening. When the overlay closes the parent layer's meta tags are restored.
Deprecating
[up-hungry]
in the<head>
Existing solutions using
[up-hungry]
to update meta tags can be removed from your application code.Other than
[up-hungry]
the new implementation can deal with meta tags that only exist on some pages.Opting in or out
See
[up-meta]
for ways to include or exclude head elements from synchronization.You can disable the synchronization of meta tags globally or per render pass:
Forgiving error handling
In earlier versions, errors in user code would often crash Unpoly. This would sometimes leave the page in a corrupted state. For example,
a render pass would only update some fragments, fail to scroll, or fail to run destuctors.
This version changes how Unpoly handles exceptions thrown from user code, like compilers, transition functions or callbacks like
{ onAccepted }
.User errors are no longer thrown
Starting with this version, Unpoly functions generally succeed despite exceptions from user code.
The code below will successfully compile an element despite a broken compiler:
Instead an
error
event onwindow
is emitted:This behavior is consistent with how the web platform handles errors in event listeners
and custom elements.
Debugging and testing
Exceptions in user code are also logged to the browser's error console.
This way you can still access the stack trace or detect JavaScript errors in E2E tests.
Some test runners like Jasmine already listen to the
error
event and fail your test if any uncaught exception is observed.In Jasmine you may use
jasmine.spyOnGlobalErrorsAsync()
to make assertions on the unhandled error.Hungry elements
Element with an
[up-hungry]
attribute are updated whenever the serversends a matching element, even if the element isn't targeted.
This release addresses many issues and requests concerning hungry elements:
Conflict resolution
There is now defined behavior when multiple targets want to render the same new fragments from a server response:
Rendering in multiple layers
Many edge cases have been addressed for render passes that affect multiple layers:
the discarded response can now be rendered into matching hungry elements on other layers.
the layer closest to the rendering layer will be chosen.
[up-if-layer]
.For example,
[up-if-layer="current child"]
would only piggy-back on render passes for the current layer or its direct overlay.More control over updates
You can now freely control when an hungry element is updated:
Before a hungry element is added to a render pass, a new event
up:fragment:hungry
is now emitted on the element.The event has properties for the old and new element, and information about the current render pass.
You may prevent this event to exclude the hungry element from the render pass. Use this to define arbitrary conditions
for when an hungry element should be updated:
Hungry elements can now set an
[up-on-hungry]
attribute. It contains a code snippet that receives anup:fragment:hungry
event.Calling
event.preventDefault()
will prevent the hungry fragment from being updated.Deprecated the
[up-if-history]
modifier for hungry elements.This functionality is now covered by the more generic
[up-on-hungry]
attribute. Also its main use case was synchronizing meta tags,and that is now supported out of the box.
Animation
Some improvements have been to hungry elements with animated transitions:
[up-duration]
and[up-easing]
attributes.up.render().finished
promise.Polling
This release ships many improvements for the
[up-poll]
attribute.Pausing and resuming
Unpoly has always paused polling when the user minimizes the window or switches to another tab.
This behavior has been improved by the following:
When at least one poll interval was spent paused in the background and the user then returns to the tab, Unpoly will now immediately reload the fragment.
You can use this to load recent data when the user returns to your app after working on something else for a while. For example, the following
would reload your main element after an absence of 5 minutes or more:
Polling now unschedules all JavaScript timers while polling is paused. This allows browser to keep the inactive window suspended, saving battery life.
Unpoly also pauses polling for fragments that are covered by an overlay. This behavior has been improved by the following:
Unpoly will now immediately reload the fragment.
[up-if-layer="any"]
attribute on an[up-poll]
fragment.Disabling polling
[up-poll=false]
. The previous method of omitting the[up-poll]
attribute remains supported.up.radio.config.pollEnabled
. To disable polling, prevent theup:fragment:poll
event instead.Rendering
Unpoly's rendering engine has been reworked to address many edge cases found in production use.
More practical callback order
.up-current
classes are updated before compilers are called.{ onAccepted }
and{ onDismissed }
callbacks fire.This allows callbacks to observe all fragment changes made by a closing overlay.
Matching in destroyed elements
This release addresses many many errors when matching fragments in closed layers, detached elements or destroyed elements in their exit animation:
{ failTarget }
or{ failLayer }
cannot be resolved.up.fragment.toTarget()
no longer crashes when deriving targets for destroyed elements that are still in their exit animation.{ layer }
does not exist or has been closed.{ failLayer }
is no longer open.General improvements
This allows to use
[up-validate]
in forms that are not submitted through Unpoly.[up-keep]
no longer need to also be[up-keep]
. You can prevent keeping by setting[up-keep=false]
. This allows you to set[up-keep]
via a macro."/true"
(sic)."revalidating undefined"
Network quality is no longer measured
Previous versions of Unpoly adapted the behavior some features when it detected high latency or low network throughput.
Due to cross-browser support for the Network Information API,
measuring of network quality was removed:
Unpoly no longer doubles poll intervals on slow connections. The configuration
up.radio.config.stretchPollInterval
was removed.Unpoly no longer prevents preloading on slow connections. The configuration
up.link.config.preloadEnabled = 'auto'
was removed.To disable preloading based on your own metrics, you can still prevent the
up:link:preload
event.The configuration
up.network.config.badDownlink
was removed.The configuration
up.network.config.badRTT
was removed.The function
up.network.shouldReduceRequests()
was removed.Unpoly retains all other functionality for dealing with network issues.
Fragment API
More control over region-aware fragment matching
When targeting fragments, Unpoly will prefer to
match fragments in the region of the user interaction. For example, when
a link's
[up-target]
could match multiple fragments, the fragment closest to the link is updated.In cases where you don't want this behavior, you now have more options:
{ match: 'first' }
option to any function that matches or renders a fragment.[up-match=first]
option on a link or form that matches or renders a fragment.up.fragment.config.matchAroundOrigin
has been replaced byup.fragment.config.match
. Its values are'region'
(default) and'first'
.General improvements
New experimental function
up.fragment.contains()
. It returns whether the givenroot
matches or contains the given selector or element.Other than
Element#contains()
it only matches fragments on the same layer. It also ignores destroyed fragments in an exit animation.The event
up:fragment:keep
received a new property{ renderOptions }
. It contains the render options for the current render pass.The event
up:fragment:aborted
received new experimental property{ newLayer }
. It returns whether the fragment was aborted by a new overlay opening.Many functions in the fragment API now also support a
Document
as the search root:up.fragment.get()
up.fragment.all()
up.fragment.contains()
Passing an element to
up.fragment.get()
now returns that element unchanged.Scripting
Destructors are now called with the element being destroyed.
This allows you to reuse the same destructor function for multiple elements:
Unpoly 3.0.0 introduced a third
meta
argument for compilerscontaining information about the current render pass:
Unfortunately we realized that access to the response this would to bad patterns where fragments would compile
differently for the initial page load vs. subsequent fragment updates.
In Unpoly 3.5 compilers can no longer access the current response via the
{ response }
of thatmeta
argument.The
{ layer }
and{ revalidating }
property remains available.The
up.syntax
package has been renamed toup.script
.Layers
subtree
in your{ layer }
options or[up-layer]
attributes.This matches fragments in either the current layer or its descendant overlays.
up.Layer
objects now support a new method#subtree()
. It returns an array ofup.Layer
containing this layer and its descendant overlays.Links
up:link:preload
event received a new property{ renderOptions }
. It contains the render options for the current render pass.[up-on-offline]
attribute now supports a CSP nonce.up.link.followOptions()
now takes anObject
as a second argument. It will override any options parsed from the link attributes.up.link.config.preloadEnabled
was deprecated. To disable preloading, preventup:link:preload
.DOM helpers
up.element.isEmpty()
was added. It returns whether an element has neither child elements nor non-whitespace text.Viewports
up.viewport.config.anchoredRight
toup.viewport.config.anchoredRightSelectors
up.viewport.config.fixedTop
toup.viewport.config.fixedTopSelectors
up.viewport.config.fixedBottom
toup.viewport.config.fixedBottomSelectors
unpoly-migrate.js
up.element.isAttached()
andup.element.isDetached()
functions were changed so they behavelike their implementation in Unpoly 2.x. In particular the functions now only consider attachment in
window.document
, but not to otherDocument
instances.Build
unpoly.js
is now compiled using ES2021 (up from ES2020). The ES6 build for legacy browsers remains available.Improve compression of minified builds. In particular private object properties are now prefixed with an underscore (
_
) so they can be mangled safely.If you are re-bundling the unminified build of Unpoly you can configure your minifier
to do the same.
Beta Was this translation helpful? Give feedback.
All reactions