Today we are excited to announce the release of Vue 3.5 "Tengen Toppa Gurren Lagann"!
This minor release contains no breaking changes and includes both internal improvements and useful new features. We will cover some highlights in this blog post - for a full list of changes and new features, please consult the full changelog on GitHub.
In 3.5, Vue's reactivity system has undergone another major refactor that achieves better performance and significantly improved memory usage (-56%) with no behavior changes. The refactor also resolves stale computed values and memory issues caused by hanging computeds during SSR.
In addition, 3.5 also optimizes reactivity tracking for large, deeply reactive arrays, making such operations up to 10x faster in some cases.
Reactive Props Destructure has been stabilized in 3.5. With the feature now enabled by default, variables destructured from a defineProps
call in <script setup>
are now reactive. Notably, this feature significantly simplifies declaring props with default values by leveraging JavaScript's native default value syntax:
Before
const props = withDefaults(
defineProps<{
count?: number
msg?: string
}>(),
{
count: 0,
msg: 'hello'
}
)
After
const { count = 0, msg = 'hello' } = defineProps<{
count?: number
message?: string
}>()
Access to a destructured variable, e.g. count
, is automatically compiled into props.count
by the compiler, so they are tracked on access. Similar to props.count
, watching the destructured prop variable or passing it into a composable while retaining reactivity requires wrapping it in a getter:
watch(count /* ... */)
// ^ results in compile-time error
watch(() => count /* ... */)
// ^ wrap in a getter, works as expected
// composables should normalize the input with `toValue()`
useDynamicCount(() => count)
For those who prefer to better distinguish destructured props from normal variables, @vue/language-tools
2.1 has shipped an opt-in setting to enable inlay hints for them:
Details:
3.5 brings a few long-requested improvements to server-side rendering (SSR).
Async components can now control when they should be hydrated by specifying a strategy via the hydrate
option of the defineAsyncComponent()
API. For example, to only hydrate a component when it becomes visible:
import { defineAsyncComponent, hydrateOnVisible } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
})
The core API is intentionally lower level and the Nuxt team is already building higher-level syntax sugar on top of this feature.
Details: PR#11458
useId()
useId()
is an API that can be used to generate unique-per-application IDs that are guaranteed to be stable across the server and client renders. They can be used to generate IDs for form elements and accessibility attributes, and can be used in SSR applications without leading to hydration mismatches:
<script setup>
import { useId } from 'vue'
const id = useId()
</script>
<template>
<form>
<label :for="id">Name:</label>
<input :id="id" type="text" />
</form>
</template>
Details: PR#11404
data-allow-mismatch
In cases where a client value will be inevitably different from its server counterpart (e.g. dates), we can now suppress the resulting hydration mismatch warnings with data-allow-mismatch
attributes:
<span data-allow-mismatch>{{ data.toLocaleString() }}</span>
You can also limit what types of mismatches are allowed by providing a value to the attribute, where the possible values are text
, children
, class
, style
, and attribute
.
3.5 fixes many long-standing issues related to the defineCustomElement()
API, and adds a number of new capabilities for authoring custom elements with Vue:
configureApp
option.useHost()
, useShadowRoot()
, and this.$host
APIs for accessing the host element and shadow root of a custom element.shadowRoot: false
.nonce
option, which will be attached to <style>
tags injected by custom elements.These new custom-element-only options can be passed to defineCustomElement
via a second argument:
import MyElement from './MyElement.ce.vue'
defineCustomElements(MyElement, {
shadowRoot: false,
nonce: 'xxx',
configureApp(app) {
app.config.errorHandler = ...
}
})
useTemplateRef()
3.5 introduces a new way of obtaining Template Refs via the useTemplateRef()
API:
<script setup>
import { useTemplateRef } from 'vue'
const inputRef = useTemplateRef('input')
</script>
<template>
<input ref="input">
</template>
Prior to 3.5, we recommended using plain refs with variable names matching static ref
attributes. The old approach required the ref
attributes to be analyzable by the compiler and thus was limited to static ref
attributes. In comparison, useTemplateRef()
matches the refs via runtime string IDs, therefore supporting dynamic ref bindings to changing IDs.
@vue/language-tools
2.1 has also implemented special support for the new syntax, so you will get auto-completion and warnings when using useTemplateRef()
based on presence of ref
attributes in your template:
A known constraint of the built-in <Teleport>
component is that its target element must exist at the time the teleport component is mounted. This prevented users from teleporting content to other elements rendered by Vue after the teleport.
In 3.5, we have introduced a defer
prop for <Teleport>
which mounts it after the current render cycle, so this will now work:
<Teleport defer target="#container">...</Teleport>
<div id="container"></div>
This behavior requires the defer
prop because the default behavior needs to be backwards compatible.
Details: PR#11387
onWatcherCleanup()
3.5 introduces a globally imported API, onWatcherCleanup()
, for registering cleanup callbacks in watchers:
import { watch, onWatcherCleanup } from 'vue'
watch(id, (newId) => {
const controller = new AbortController()
fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
// callback logic
})
onWatcherCleanup(() => {
// abort stale request
controller.abort()
})
})
For a comprehensive list of changes and features in 3.5, check out of the the full changelog on GitHub. Happy hacking!
A couple of weeks back, we reported on one of those occasional moments that makes reality feel all wobbly beneath our feet: The Kamala Harris/Tim Walz presidential campaign including an actual tweet from internet comedian dril in one of their campaign emails, a moment that marked either the ultimate triumph of Weird Twitter, or heralded its final, permanently co-opted demise.
At the time, dril himself fired back at the inclusion of his work in the campaign's materials, blasting Harris for her ongoing support of Israel's ongoing military actions in Gaza. Now, though, he's given a fuller interview on the moment to Rolling Stone, and since the world can probably never have too many "in-character" dril interviews, it felt worth diving into the series of emailed exchanges. Including the online writer's insistence that Harris and Walz should pay him "the full value" of his classic "im not mad" tweet, "which I estimate would be about $25.00.” (Also: "I know they aren’t hurting for money right now, they must have raised like half a billion dollars up to this point. So, they must hate me, or otherwise wish me dead.”)
dril being dril, he then immediately pivots: "If anything, I should be paying the new media toilet robber who pilfered my waste product for the free exposure that this incident has provided me. My posts strictly belong in the dumpster. They must never be allowed in any emails, especially not any emails associated with the Resolute Desk. They are Beneath the office.” The comedian's disinterest in charting out any territory except that which he personally finds funny is partly why it was so weird that some staffer in the Harris campaign thought they could get some heat by using him as a meme: Although he's done plenty of political material, the "dril sensibility," for lack of a better word, is chaotic, absurdist, and loosely pessimistic above all else, in ways that sit ill at ease with traditional campaigning.
As to whether he thought the tweet-pick in question, applying the "please dont put in the newspaper that i got mad" mindset to Donald Trump, was apt, dril had some further thoughts:
Well, it’s not the tweet I personally would have picked to send to millions of people to prove some sort of point about human emotion. When I wrote that tweet, I think I had more petty issues in mind. I did not consider that it would be used by a presidential candidate to ‘madshame’ their opponent. And that’s fucked, because I think it’s fine to be mad in certain cases, particularly during an election that everyone says could decide if one billion toddlers get bombed or not. If I genuinely believed that, I suppose I would also get mad, and that’s fine.
As to what this means for his lasting impact (and the basic inability to translate being the funniest person on the internet into other kinds of success), dril was typically humble:
I think it’s the greatest honor to have your art screenshotted and commodified by the most annoying people online and deployed like chess pieces in obnoxious, inconsequential arguments, alongside such elevated content as animated gifs from NBC’s The Office and the funny cartoon frog that supposedly represents disenfranchised young white men. I’m truly happy just to be part of the conversation.
You can read the full interview here.
If you need more proof that we're living in some sort of bizarre, ad-sponsored version of The Sims, have we got a news bite for you. According to Deadline (not The Onion, we double-checked), Chick-fil-A is leaving the sandwiches in the coop and enlisting the streaming wars. The trade reports that the fast-food chain "has been working with a number of major production companies, including some of the studios, to create family-friendly shows, particularly in the unscripted space." It's also, apparently "in talks to license and acquire content," like Disney's Chicken Little, we guess? Or something like Amelia Dimoldenberg's Chicken Shop Date? The whole thing is almost too bizarre to fully comprehend.
Actual details don't help. According to Deadline, one of Chick-fil-A's planned originals is a family-friendly game show from Glassman Media, which produced The Wall for NBC, and Sugar23, which produced Netflix's 13 Reasons Why. Sure! The series has reportedly already been handed a 10-episode order. Brian Gibson, who worked on the Americanized versions of Top Gear and The X Factor, is heading up programming, which apparently also includes a $400,000 per half-hour budget for shows on the scripted side. Again… sure!
What's easier to wrap one's head around is the fact that Community nailed it yet again. It's a shame the show isn't on anymore, because Chick-fil-A's streaming service would make a great real-life companion to human Subway or the KFC space flight simulator. (At least the chicken fried platform will be in good company with Netflix's Exploding Kittens show and Tim Hortons' equally real, but no less bizarre musical.) Whenever this thing does launch, just imagine Troy confusing it with Peacock (because, y'know, they're both birds) or Britta saying she can excuse homophobia, but she draws the line at animal cruelty (because, y'know, chicken sandwiches). It will be just like Community never left.
Article URL: https://ytch.xyz
Comments URL: https://news.ycombinator.com/item?id=41247023
Points: 2560
# Comments: 497