Releases: salesforce/lwc
v7.0.4
What's Changed
- perf: static-optimize
xlink:href
by @nolanlawson in #4346 - chore: run
yarn lint --fix
by @nolanlawson in #4355 - test(hydration): add
.only
support by @nolanlawson in #4356 - test(ssr): use
Document.parseHTMLUnsafe
by @nolanlawson in #4357 - chore(prettier): format
.eslintrc
on commit by @nolanlawson in #4361 - perf: static-optimize
<a>
/<area>
href
by @nolanlawson in #4354 - chore: release v7.0.4 by @nolanlawson in #4364
- chore: release v7.0.4 by @nolanlawson in #4365
Full Changelog: v7.0.3...v7.0.4
v7.0.3
What's Changed
- fix: allow lazy-disabling native lifecycle by @nolanlawson in #4350
- chore: release v7.0.3 by @nolanlawson in #4352
- chore: release v7.0.3 by @nolanlawson in #4353
Full Changelog: v7.0.2...v7.0.3
v7.0.2
What's Changed
- perf: static-optimize
id
/IDref attributes by @nolanlawson in #4330 - fix(class): avoid enumerable prototype for class object binding @W-16109991@ by @wjhsf in #4337
- fix: inline style parsing for "! important" by @Bradels in #4329
New Contributors
Full Changelog: v7.0.1...v7.0.2
v7.0.1
What's Changed
- feat(scripts): add test:bespoke script by @wjhsf in #4307
- fix(template-compiler): parsed template content should be allocated to
content.childNodes
by @ekashida in #4311 - fix(template-compiler): correctly handle open curly bracket resulting from html character entity by @ekashida in #4312
- fix: support v6 engine + v7 compiler by @nolanlawson in #4315
- build(deps-dev): bump @rollup/plugin-commonjs from 25.0.7 to 26.0.1 by @dependabot in #4322
- build(deps-dev): bump rollup-plugin-serve from 1.1.1 to 3.0.0 by @dependabot in #4321
- perf(template-compiler): static-optimize
spellcheck
by @nolanlawson in #4317 - build(deps-dev): bump the theoretically-non-breaking group across 1 directory with 14 updates by @dependabot in #4327
- fix(engine-dom): make native lifecycle all-or-nothing by @nolanlawson in #4316
- chore(ci): rebalance karma tests by @nolanlawson in #4328
- chore: release v7.0.1 by @nolanlawson in #4333
- chore: release v7.0.1 by @nolanlawson in #4334
Full Changelog: v7.0.0...v7.0.1
v7.0.0
LWC v7.0.0 contains breaking changes. Please read carefully below if you are upgrading from v6.
If you are upgrading from v5, please upgrade to v6 first.
Note
LWC v7 corresponds to Salesforce release Winter '25 (API version 62).
New features
- Class object binding for more ergonomic
class
es in templates this.style
for a more ergonomic way to change component styles at runtimethis.hostElement
for an alternative tothis.template.host
that works in light DOM
Summary of breaking changes
- Class object binding
- New
this.style
property - New
this.hostElement
property - Improved TypeScript types
@lwc/template-compiler
API changes
Breaking changes
Class object binding
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Class object binding is a new feature that makes it more ergonomic to render class
attributes in your LWC components. As part of this feature, class
rendering has changed for some uncommon use cases.
If you are using a dynamic class
in your template:
<template>
<div class={myClass}></div>
</template>
Then the rendering of this class
may change if you were previously defining myClass
as something other than a string, null
, or undefined
.
For example, consider if myClass
is a boolean:
export default class extends LightningElement {
myClass = false
}
Old behavior:
This renders:
<div class="false"></div>
New behavior:
<div class=""></div>
This change applies to booleans, numbers, functions, arrays, and objects. Below is a table summarizing the change:
Type | Example | Rendered (old) | Rendered (new) |
---|---|---|---|
Boolean | true |
class="true" |
class="" |
Number | 1 |
class="1" |
class="" |
Function | () => {} |
class="() => {}" |
class="" |
Array | ["a", "b"] |
class="a,b" |
class="a b" |
Object | { a: true } |
class="[object Object]" |
class="a" |
In short:
- Booleans, numbers, and functions are no longer directly stringified, but are stripped instead.
- Arrays and objects are no longer stringified, but instead follow class object binding semantics.
This may break a component if it is using a CSS selector like these:
.false {}
.true {}
[class="1"] {}
Or if it is using querySelector
or other traversal techniques that rely on the class name:
this.template.querySelector('.false')
this.template.querySelector('.true')
this.template.querySelector('[class="1"]')
In rare cases, this can also cause breakages across component boundaries. For example, if you have a global stylesheet relying on light DOM or synthetic shadow DOM, and thus the ability to pierce inside of components you don't own, then the above CSS selectors would break in that case as well.
To resolve any breakages:
- Avoid anti-patterns for styling components.
- In cases where you want to render a value as a string (e.g.
class="false"
orclass="1"
), convert it to a string usingString(value)
.
This change may also require updating snapshots, e.g. in Jest tests.
New this.style
property
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Components can now access their CSSStyleDeclaration
using this.style
:
renderedCallback() {
this.style.color = 'red'
}
This is a breaking change if the component uses this.style
as an expando:
renderedCallback() {
if (!this.style) {
this.style = "foo"
}
}
In the above case, the component author may assume that this.style
is initially undefined
, and then set it to a new value ("foo"
). After this change, the above code will not work as expected, because this.style
is initially truthy rather than undefined
.
To resolve this, set a class property on the component, initialized to undefined
, rather than using an expando:
+ style = undefined
renderedCallback() {
if (!this.style) {
this.style = "foo"
}
}
You may also rename your this.style
expando to something else (e.g. this.customStyle
).
New this.hostElement
property
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Components can now access this.hostElement
as a convenient alternative to this.template.host
:
renderedCallback() {
console.log(this.template.host) // <x-component>
console.log(this.hostElement) // <x-component>
}
Additionally, this works in light DOM components to access the "host" element (similar to the :host
CSS pseudo-class in light DOM scoped styles). This provides an ergonomic way to access the root HTMLElement
object in either light DOM or shadow DOM components.
Similar to the new this.style
property, this is a breaking change if you are using this.hostElement
already as an expando. Refer to the this.style
release notes for a resolution.
Improved TypeScript types
Note
This change only applies to component authors using TypeScript, which is not yet fully supported.
The TypeScript definitions for the lwc
package are greatly improved, to more closely match the ground truth of the actual APIs for LightningElement
, createElement
, etc. at runtime. You may need to adjust your TypeScript code or version to adapt to the new typings.
Summary
- The minimum supported version of TypeScript is v5.4.5.
- The only supported compiler target is
"ESNext"
. ContextValue
has been renamed toWireContextValue
.ContextConsumer
has been renamed toWireContextConsumer
.Contextualizer
has been renamed toWireContextProvider
.StylesheetFactory
has been renamed toStylesheet
.StylesheetFactories
has been renamed toStylesheets
.StringKeyedRecord
has been removed. Instead, use the typeRecord<string, any>
.ShadowSupportMode
has been removed. Instead, use the string values"any"
,"reset"
, or"native"
.WireAdapter
is now a generic type with a default type parameter.WireAdapterConstructor
is now a generic type with a default type parameter.- All decorators can now be used with the new decorator implementation introduced in TypeScript v5 as well as the old, experimental implementation.
this.template
is now possibly null, reflecting the state for components using light DOM.this.template.host
in aLightningElement
is now typed asHTMLElement
, rather than the broaderElement
.- The return type of
createElement
has been updated to reflect the fact that the element created contains the@api
-decorated props from the component definition.- A new helper type,
LightningHTMLElement
, has been introduced to provide an easy way of accessing the return type.const cmp: LightningHTMLElement<MyComponent> = createElement('my-component', { is: MyComponent });
- WARNING: Due to limitations of TypeScript, this new type incorrectly contains all props defined on the component, not just decorated props. Only decorated props are accessible at runtime.
- A new helper type,
- Importing from
"lwc"
now provides module definitions for HTML/CSS imports. The module definitions are also available by directly importing a new package,@lwc/types
.
Common breakages and fixes
Breakage | Fix |
---|---|
HTML imports (import myComponent from './my-component.html' ) |
Import @lwc/types or lwc/types somewhere in your project. I.e.: import '@lwc/types' . |
StringKeyedRecord |
Replace with Record<string, any> or similar. |
ContextValue |
Renamed to WireContextValue , but it's really just Record<string, any> , so you could use a more precise type instead. |
ContextConsumer |
Renamed to WireContextConsumer |
Contextualizer |
Renamed to WireContextProvider |
createElement |
Use type assertion to cast to HTMLElement & MyComponentApiDecoratedProps . You have to define your own interface to get the @api decorated props, because TypeScript can't detect that. (You can use your component class, but that includes all component and LightningElement props, not just component @api decorated props, so it's not ideal.) |
this.template is possibly undefined |
Use [optional chaining](http... |
v7.0.0 (prerelease)
LWC v7.0.0 contains breaking changes. Please read carefully below if you are upgrading from v6.
If you are upgrading from v5, please upgrade to v6 first.
Note
LWC v7 corresponds to Salesforce release Winter '25 (API version 62).
New features
- Class object binding for more ergonomic
class
es in templates this.style
for a more ergonomic way to change component styles at runtimethis.hostElement
for an alternative tothis.template.host
that works in light DOM
Summary of breaking changes
- Class object binding
- New
this.style
property - New
this.hostElement
property - Improved TypeScript types
@lwc/template-compiler
API changes
Breaking changes
Class object binding
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Class object binding is a new feature that makes it more ergonomic to render class
attributes in your LWC components. As part of this feature, class
rendering has changed for some uncommon use cases.
If you are using a dynamic class
in your template:
<template>
<div class={myClass}></div>
</template>
Then the rendering of this class
may change if you were previously defining myClass
as something other than a string, null
, or undefined
.
For example, consider if myClass
is a boolean:
export default class extends LightningElement {
myClass = false
}
Old behavior:
This renders:
<div class="false"></div>
New behavior:
<div class=""></div>
This change applies to booleans, numbers, functions, arrays, and objects. Below is a table summarizing the change:
Type | Example | Rendered (old) | Rendered (new) |
---|---|---|---|
Boolean | true |
class="true" |
class="" |
Number | 1 |
class="1" |
class="" |
Function | () => {} |
class="() => {}" |
class="" |
Array | ["a", "b"] |
class="a,b" |
class="a b" |
Object | { a: true } |
class="[object Object]" |
class="a" |
In short:
- Booleans, numbers, and functions are no longer directly stringified, but are stripped instead.
- Arrays and objects are no longer stringified, but instead follow class object binding semantics.
This may break a component if it is using a CSS selector like these:
.false {}
.true {}
[class="1"] {}
Or if it is using querySelector
or other traversal techniques that rely on the class name:
this.template.querySelector('.false')
this.template.querySelector('.true')
this.template.querySelector('[class="1"]')
In rare cases, this can also cause breakages across component boundaries. For example, if you have a global stylesheet relying on light DOM or synthetic shadow DOM, and thus the ability to pierce inside of components you don't own, then the above CSS selectors would break in that case as well.
To resolve any breakages:
- Avoid anti-patterns for styling components.
- In cases where you want to render a value as a string (e.g.
class="false"
orclass="1"
), convert it to a string usingString(value)
.
This change may also require updating snapshots, e.g. in Jest tests.
New this.style
property
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Components can now access their CSSStyleDeclaration
using this.style
:
renderedCallback() {
this.style.color = 'red'
}
This is a breaking change if the component uses this.style
as an expando:
renderedCallback() {
if (!this.style) {
this.style = "foo"
}
}
In the above case, the component author may assume that this.style
is initially undefined
, and then set it to a new value ("foo"
). After this change, the above code will not work as expected, because this.style
is initially truthy rather than undefined
.
To resolve this, set a class property on the component, initialized to undefined
, rather than using an expando:
+ style = undefined
renderedCallback() {
if (!this.style) {
this.style = "foo"
}
}
You may also rename your this.style
expando to something else (e.g. this.customStyle
).
New this.hostElement
property
Note
On the Salesforce Lightning platform, this change only applies to components with an API version of 62 or above.
Components can now access this.hostElement
as a convenient alternative to this.template.host
:
renderedCallback() {
console.log(this.template.host) // <x-component>
console.log(this.hostElement) // <x-component>
}
Additionally, this works in light DOM components to access the "host" element (similar to the :host
CSS pseudo-class in light DOM scoped styles). This provides an ergonomic way to access the root HTMLElement
object in either light DOM or shadow DOM components.
Similar to the new this.style
property, this is a breaking change if you are using this.hostElement
already as an expando. Refer to the this.style
release notes for a resolution.
Improved TypeScript types
Note
This change only applies to component authors using TypeScript, which is not yet fully supported.
- The minimum supported version of TypeScript is v5.4.5.
- The only supported compiler target is
"ESNext"
. ContextValue
has been renamed toWireContextValue
.ContextConsumer
has been renamed toWireContextConsumer
.Contextualizer
has been renamed toWireContextProvider
.StylesheetFactory
has been renamed toStylesheet
.StylesheetFactories
has been renamed toStylesheets
.StringKeyedRecord
has been removed. Instead, use the typeRecord<string, any>
.ShadowSupportMode
has been removed. Instead, use the string values"any"
,"reset"
, or"native"
.WireAdapter
is now a generic type with a default type parameter.WireAdapterConstructor
is now a generic type with a default type parameter.- All decorators can now be used with the new decorator implementation introduced in TypeScript v5 as well as the old, experimental implementation.
this.template
is now possibly null, reflecting the state for components using light DOM.this.template.host
in aLightningElement
is now typed asHTMLElement
, rather than the broaderElement
.- The return type of
createElement
has been updated to reflect the fact that the element created contains the@api
-decorated props from the component definition.- A new helper type,
LightningHTMLElement
, has been introduced to provide an easy way of accessing the return type.const cmp: LightningHTMLElement<MyComponent> = createElement('my-component', { is: MyComponent });
- WARNING: Due to limitations of TypeScript, this new type incorrectly contains all props defined on the component, not just decorated props. Only decorated props are accessible at runtime.
- A new helper type,
- Importing from
"lwc"
now provides module definitions for HTML/CSS imports. The module definitions are also available by directly importing a new package,@lwc/types
.
@lwc/template-compiler
API changes
Note
This change only affects direct consumers of the @lwc/template-compiler
npm package, who are using the compile
API.
Due to a refactoring of the @lwc/compiler
and @lwc/template-compiler
packages, the @lwc/template-compiler
compile
function now requires the component's file name (i.e. the namespace
and name
options) when compiling the template.
To resolve the breaking change, add the new options. For example:
import { compile } from '@lwc/template-compiler'
compile({
...previousOptions,
// Assuming the component is `<x-foo>`:
namespace: 'x',
name: 'foo',
})
v6.7.2
What's Changed
- chore(integration-karma): fix iframe sandbox warning by @nolanlawson in #4294
- fix(engine-dom): allow FACE in synthetic lifecycle by @nolanlawson in #4295
- test: run webdriverio CI tests in local chrome by @nolanlawson in #4299
- chore: release
v6.7.2
by @rax-it in #4297 - build(deps): bump braces from 3.0.2 to 3.0.3 by @dependabot in #4283
- chore: nucleus release
v6.7.2
by @rax-it in #4300
Full Changelog: v6.7.1...v6.7.2
v6.7.1
What's Changed
- chore(ssr-compiler): remove unused deps by @nolanlawson in #4254
- chore: release v6.7.1 by @nolanlawson in #4288
- chore: release v6.7.1 by @nolanlawson in #4290
Full Changelog: v6.7.0...v6.7.1
v6.7.0
What's Changed
- feat: expose the registered component class as a const declaration to allow hmr hooks for class @W-15890472 by @ravijayaramappa in #4271
- fix: skip hydration validation when static parts have static classes by @jmsjtu in #4278
Full Changelog: v6.6.7...v6.7.0