📜 ⬆️ ⬇️

SvelteJS: Second Version Release

Just yesterday , the 2nd version of the young but very promising SvelteJS framework was released . The version is major, which means it contains not only new features and fixed bugs, but also corresponding “breaking changes”. What's new offers developers a new version and why Svelte is even better, read under the cut.
image

If suddenly, for some unknown reason, you do not know what Svelte is and why it is not “yet another javascript framework” . I suggest first catching up to better understand what they mean.

New template syntax


The most obvious and global change in the new version is a radical change in the syntax of the templates. Rich finally decided to get rid of "uso" -like syntax in favor of a more concise version:

It was
')
{{#if foo}} {{bar}} {{else}} {{baz}} {{/if}} 

It became

 {#if foo} {bar} {:else} {baz} {/if} 

Obviously, the syntax is visually simpler and cleaner. The changes affected all designs in the templates, including the special elements of Svelte :

It was

 <:Component {foo ? Red : Blue} name="thing" /> {{#if foo}} <:Self /> {{/if}} <:Window on:keydown="handleKey(event)" /> <:Head> <title>{{post.title}} • My blog</title> </:Head> 

It became

 <svelte:component this="{foo ? Red : Blue}" name="thing"/> {#if foo} <svelte:self/> {/if} <svelte:window on:keydown="handleKey(event)" /> <svelte:head> <title>{post.title} • My blog</title> </svelte:head> 

The previous syntax of special elements was too unusual and most code editors did not cope with its highlighting. The new syntax resembles the syntax of namespace from XML and is much better perceived by editors.

We must pay tribute to Rich and separately note that all changes were actively discussed with the community, and some of my suggestions were included in the final version of the syntax and, like, even contributed to simplifying the parser.

In general, there are a lot of changes in the syntax and this could be a problem for migration to the new version, if not for the svelte-upgrade utility, specially created for the automatic upgrade of Svelte components. A complete list of changes can be viewed there .

Good, Rich! Goodbye "mustache"!

image

ES6 only


Since Svelte is primarily a compiler, it is worth first to note that the final code of the previous version was compiled in ES5 . Therefore, to support IE11 and other "progressive" versions of browsers, there was no need to communicate with transpillers like Babel or Bublé .

But in the courtyard of 2018, and so that the compiler could produce a more optimal and even more compact code, it was decided to abandon support for ES5 . In other words, Svelte now compiles the components in ES6 and we will have to use a transpiler if we need support for older versions.

I myself fully support this approach. Moreover, it is not difficult for anyone to connect Babel to a Webpack or Rollup . Especially when you consider that using Svelte without it will still not work. ;-)

Actions


I still do not understand why this feature is called actions , but for myself I decided that the native speakers know better. Although for me personally - this is not an obvious name.

Anyway, the feature is useful. In fact, this is a kind of hook that works when an element is rendered in the DOM . For this, a new use directive has been introduced :

 <img src="placeholder.jpg" use:lazyload="{ src: 'giant-photo.jpg' }"> 

And the corresponding section in behavior:

 export default { actions: { lazyload(node, data) { // do something return { update(data) {}, destroy() {} } } } }; 

An action is a function that takes as its first parameter the element to which the directive is applied, and the data that was passed to it. The function must return an object with the required destroy () method, which will be called at the moment when the element is removed from the DOM . Also, an object can contain an optional method update () , which will be called every time when the data associated with the action has been changed.

In general, if there is a need to make manipulations with the DOM directly, past the reactivity of Svelte , actions allow you to do this conveniently and provide a mechanism for synchronizing these changes.

New Life Cycle Hooks


In the previous version there were only 2 hooks: oncreate () and ondestroy () . Now we also have 2 additional hooks responsible for working with the state:

 export default { onstate({ changed, current, previous }) { //   oncreate(),   ,    }, onupdate({ changed, current, previous }) { //   oncreate(),   ,  DOM      } }; 

As you can see, each hook accepts an object with 3 properties:



You can use it like this:

 export default { onstate({ changed: { foo }, current, previous }) { if (foo) { console.log('foo has changed from %s to %s', previous.foo, current.foo); } } }; 

Or even like this:

 component.on('state', ({ changed, current, previous }) => {...}); 

In connection with this important change, observe () was moved from the core to the svelte-extras add -on package . Therefore, if you like the previous syntax, you can simply connect the appropriate method from this package:

 import { observe } from 'svelte-extras'; export default { methods: { observe }, oncreate() { this.observe('foo', (current, previous) => {...}); } }; 

If we recall that Rich, as the creator of Rollup , is a fan of tree-shaking , this approach immediately becomes obvious.



Spread attributes


Yes, I know, it was spied on by JSX , but essentially it does not change. Many voted FOR and now Svelte can also:

 <Child {...childProps} /> 


Other changes


Important changes have occurred in some of the existing api framework. Here are the main ones:

The get () method no longer accepts parameters and always returns the entire state of the component:


It was

 const foo = this.get('foo'); const bar = this.get('bar'); 

It became

 const { foo, bar } = this.get(); 

This is cool and we can use destructuring assignment to determine the necessary properties. Moreover, now this method has become more similar to its antagonist, the set () method, which in the previous version accepted only the object:

 this.set({ foo: 1 }); const { foo } = this.get(); 

In general, I have the impression that Svelte is increasingly inclined to use RORO in its interfaces. A full transition to ES6 only contributes to this.

The same observation confirms the new syntax of the calculated properties:


It was

 export default { computed: { d: (a, b, c) => a = b + c } }; 

It became

 export default { computed: { d: ({ a, b, c }) => a = b + c } }; 

At first glance, a strange and not very useful change (perhaps RORO), but in fact the next step will be the possibility of creating a calculated property dependent on the entire state of the component. For example, to filter it or otherwise manipulate it, as well as transfer it to child components using a spread attribute, in the following way (as long as it does not work):

 <Child {...props}/> <script> import Child from './Child.html'; export default { components: { Child }, computed: { props: state => { const { unwanted, alsoUnwanted, ...props } = state; return props; } } }; </script> 

I think many understand how cool it is. I hope Rich will fix this feature in the near future.

Custom event handlers should now return destroy () instead of teardown () for consistency:


It was

 export function eventHandler(node, callback) { //... return { teardown() {} } } 

It became

 export function eventHandler(node, callback) { //... return { destroy() {} } } 


Svelte no longer renders component attribute values ​​to type.


Now you need to explicitly specify a type other than a string using an expression. Most of all it concerns numbers:

It was

 <Counter start="1"/> 

It became

 <Counter start="1"/> <!--  --> <Counter start="{1}"/> <!--  --> 

I think the meaning is clear. A wise decision.

In templates, the methods of the store can now be called using the $ prefix.


It was

 <button on:click="store.set({ clicked: true })">click me</button> 

It became

 <button on:click="$set({ clicked: true })">click me</button> 

In the previous version, only data from the store was available through the $ prefix.

Tudushechka



For clarity, dashed off his own "tudushechku." In it, I tried to reflect the maximum of new Svelte features that can be applied to this task, again for clarity.

Tudushechka can CRUD over tasks, emulate asynchronous interaction with persistent state (storage, backend, etc.) and querying by one parameter - type of todo-sheet (work, family, hobby), as well as light animations. Works primitive, spelled quickly. Everything I love))))

→ Feel

That's all, thank you all! Good Friday and weekend!

UPDATE:


Who is interested in Svelte and would like to follow its development - welcome to the Russian-language telegram channel SvelteJS . We will be glad to you!

Source: https://habr.com/ru/post/353896/


All Articles