First Impressions Using React Native
jlongster.com
jlongster.com
I think this is actually possible on the web as well. Someone could write a UI framework which runs JS in a Worker, and sends messages to the main thread, on which there is HTML and minimal JS to receive the messages and handle them.
I'm surprised this hasn't been done, or has it and I just haven't heard about it?
If you're worried about the overhead of transferring lots of messages from the Worker to the main thread, I think it can be pretty fast actually. I did an experiment with proxying WebGL that way, which is a fairly high-traffic API, with nice results,
https://blog.mozilla.org/research/2014/07/22/webgl-in-web-wo...
For something rendering a UI, message passing overhead should be reasonable, especially if the framework is smart enough to only send over what changes (like React Native does).
I've seen Web Workers used in things like graphing libraries, though.
Serialized data. Workers currently can't have access to canvas contexts.
There was a lot of hype about hybrid apps "sucking", but I bet it doesn't once you get off the thread.
But running React in a web worker is still a really great idea. There would just be a lot of little edge cases to handle (like when you click a link - you need to prevent default of navigation, then send that link click to the web worker to see if your app wants to prevent default, if not, force the redirect back on the main thread). Having tight control over text editing might be challenging as well. These are difficulties, but I suspect they are a fixed set of challenges that are worth the increased parallelism in an increasingly multicore world.
But are web workers currently The Solution To All Our Mobile App Needs? No, but they're a great tool that are highly underutilized by JS developers, and that React is uniquely positioned to take advantage of.
It's easy to be too aggressive. For example registering a `touchstart` on a DOM node would kill the native behavior and prevent scrolling, even if that's what you wanted. Of course, you could implement scrolling in JavaScript. That's a lot of work and you have to make sure the web worker doesn't block for more than 16ms so that the effect is smooth.
In my experience it's best to use native browser behaviors where possible. You get all sorts of benefits, like scrolling being executed on a separate thread, and don't have to rely on reimplementing everything from the ground up.
I wonder if there's even value in something like an asm.js-compiled layout system, which absolutely positions elements. One of the insights of React Native is that to build apps, we really only need a small subset of the web's layout algorithms. Only flexbox, really. So if we recognize this subset, and remove everything else, there main thread can focus on really smooth performance.
React Native even performs the flexbox layout on a 3rd thread, and tells the main thread where to absolutely position stuff.
Obviously we want to re-use as much of HTML as we can, but there might be some crazy ways to remove stuff from the main thread.
EDIT: It should be noted that Mercury, a React-inspired library (https://github.com/Raynos/mercury), has examples of running in a web worker. It is pretty cool, but I think it needs to be fleshed out more.
I'd love to chat more about this with both of you, this seems like a direction definitely worth exploring.
Maybe we could set up a github project for it? Or talk in an issue on your existing repo, nwienert?
Some reading:
https://news.ycombinator.com/item?id=6982485 http://stackoverflow.com/questions/18056922/is-there-a-way-t...
Edit: webpack + webwoker: https://github.com/webpack/webpack/tree/master/examples/web-...
https://github.com/kripken/worker-ui/wiki
Not familiar with webpack, will take a look.
You basically need to change BackendIDOperations and ReactEventListener to send/receive messages vs talking to the real APIs. It's already set up in the codebase to do this (because it actually worked at one time).
Webpack, per usual, already thought of this and has an answer for you :) https://github.com/webpack/worker-loader
Might be worth reading one of the react native devs about why animations might still be hard: http://jlongster.com/First-Impressions-using-React-Native#co...
This idea is also why I hooked up the css-layout project (https://github.com/facebook/css-layout) to a live demo to play around with: http://layout.jlongster.com/
Now of course, I had hand optimized the performance, but my point is that on the web, there was nothing I could do, and with React Native, there was something I could do to make animations smooth. This is not to say you should be doing animations in JS, but if you want highly customizable interactions that can be immediately stopped by a touch processed in JS, you should try it out and see how it feels. For things that are "fire and forget", or platform specific, you should try using CoreAnimation/keyframes etc which protects the animation from your business logic.
I can't even think of an app that has a parallax effect. If your app is required to have complex animations then web tech is not the right tech choice in general imo
What am I missing?
https://github.com/reactjs/react-future/tree/master/05%20-%2...
The biggest problems with performance are:
- GC pauses
- triggering reflow
- marshalling data across interfaces (serialization/deserialization of native types into strings and back again).
That last one is an absolute killer when it comes to applying 3D matrix transforms. Basically, you're taking an array of floats, serializing them into a string to do an element.style property assignment, so that the browser can then take that stringified representation and convert it back into an array of floats that it can apply. Huge perf hit here.
People attribute pauses to GC, when it's sometimes just the browser container environment acting up and there's nothing we can do about it - so it's easy to write it off as GC. Not sure about today, but 1.5 years ago (i = new Image(), i.src="http...") could block the JS thread for as much as 19ms. In a larger app, it's easy to write that off as GC, but (at least on iOS) the performance tooling is really lacking and it's tough to find the culprit.
Reflowing is a big deal, I agree.
EDIT: Searching for "Worker" right now didn't bring any mention, but it seems it is a very recent edit (cf https://github.com/gss/gss.github.io/commit/d6a931e3629d4b5d...).
N2O framework might do that.
Book:
https://synrc.com/apps/n2o/doc/book.pdf
One pattern you can do is send events to the server, server renders data asynchronously (maintains state for each client in a lightweight process), then ships result back to client via websocket binary frames.
You also decide how much rendering happens where. Can even do whole HTML elements on the server if you want.
Would be interested to see real examples of where this is makes sense.
Disclosure: we're developing an email client using Cordova and purely web tech using our own framework: https://github.com/techlayer/espresso.js
What, you mean like we do in Servo? https://github.com/servo/servo :-)
Our main thread (if you can call it that) just does compositing and handles dispatching UI events. Script, layout, resource loading, and the rest run concurrently in background threads.
In current browsers, JavaScript runs in the same thread as the UI, right? In Servo, how do you do interaction with the DOM like `clientHeight`? It just pauses the entire JS engine while it goes and talks to the UI thread?
Maybe we should be thinking of all of this in terms that map well to Servo's current architecture.
EDIT: What's really exciting about Servo is that hopefully the architecture's parallelism is really sound, even if certain properties of the current web restrain it. Then we can work on ways to remove those properties, and in Servo it's a simple switch to turn on more and more parallelism.
Yes, but we'd like to experiment with new APIs in the future like `getBoundingClientRectAsync()` that will allow pages to do that kind of thing asynchronously.
By restricting what the programmer can do, it naturally formed a pipeline where layout can be performed in the second stage while JS is determining the next UI update and so on. I'm not sure the extent to which this benefits us right now, but even mobile devices are beginning to have four cores so it seems like a nice property to maintain as long as it doesn't cause problems.
Servo sounds cool, and I'm curious how it takes advantage of a similar architecture but while the programmer has free reign to "clog the pipeline" by synchronous queries on layout etc. I'm sure they've thought of it, I'd just like to hear what they came up with.
Too bad they stopped working on it.
WPF has a UI and a separate closed off rendering thread, which works quite well performance wise.
BeOS took UI multithreading farther than any other environment I've ever used. And it paid off: I still think it might be the case that BeOS on circa 2000 hardware was more consistently responsive than any environment I have used before or since.
More technical detail about BeOS's multithreaded UI design: http://arstechnica.com/civis/viewtopic.php?p=17348543&sid=e2...
This just comes off as really weird to me. Why would any sane developer make a statement like this? It sounds preachy and brainwash-y and weird. If there's anything we learn as developers it's that there never is and never will be a single "right way" to do everything. Reading stuff like this makes me doubt the entire article.
There's a difference between writing objectively about something that's interesting that you enjoyed, and trying to lay down a dogma. TBH, the more of this article I read, the more my view of it's goals swayed towards the latter.
So far correct.
> and saying that it should have been worded in a mealy-mouthed way. That's silly, it's just an expression of an opinion.
Don't act like something is decided when it's not. Don't say something is 0.0 mm when you measure using using a ruler. Basics in politeness and engineering, isn't it?
Some might find it really annoying to discuss with people who use very strong statements after so short time.
For example, saying "React is the best way to build all apps no matter what" vs. saying "Compared to building native UIs with objective C, react-native made for a much smoother experience for me because of X Y and Z" are not only phrased differently, they are communicating different things. The first one is an absurd overarching dogma declaring every other app-building technology to be inferior to react with no backing whatsoever, and the second one is a useful and specific analysis of react in one situation compared to an alternative.
I can't figure out if you're trolling or not, honestly.
When you alter a quote, you're only illustrating your own bias, not that of the author.
How is this relevant to the conversation? This isn't a letter to his boss, it's a blog post. Even so personality types differ vastly between individuals and your argument appears to be culturally conditioned in a different cultural. In other words, we live completely different worlds due to our cultural conditioning (or lack of - by that I mean our association with our inner voice).
> The first one is an absurd overarching dogma declaring every other app-building technology to be inferior to react with no backing whatsoever
It's just a matter of using the word 'a' vs. 'the'. We actually get it wrong MOST of the time. Replacing 'the' with 'a' provides much more clarity. For example, you could say 'Please bring me the green chair in the closet', but if there's more than one green chair? Well there's more than one 'right' way to build apps. React is 'a' right way to build an app. There are MANY wrong ways to build apps, and most web frameworks (in my opinion) build apps a wrong way. React is one of the few. That's how I feel.
I think you either have an ulterior motive for criticizing React itself (money, company), or you're just closed minded.
I know Andy (former UIKit team) was quoted in the intro thread but I'll do it again:
>I say with confidence as a former UIKit author: React's model for the UI layer is vastly better than UIKit's. React Native is a huge deal.
https://twitter.com/andy_matuschak/status/560511204867575808
If you're averse to React because of JSX, “mixing templates and views” and similar superficial “best practices”, you're missing out. Engineers embracing React are not dumb. You should consider a possibility that they think it's good for a reason, and that reason is something you should learn about instead of armchair-rejecting it.
Try tuning out your inner rule-of-thumb linter for a weekend and really give it a try.
Its true innovation is its declarative component model.
You are missing the point of React.
https://medium.com/@dan_abramov/youre-missing-the-point-of-r...
Separating `props` and `state`, component boundaries, lack of two-way binding and predictable top-down data flow make it easy to reason about where any data comes from, and how UI will change over time.
Read this:
http://jlongster.com/Removing-User-Interface-Complexity,-or-...
So we agree, you're just separating the concept from the implementation and I'm talking about them as one.
In React, components are not just functions that return their own virtual DOM. AFAIK for many vdom-based libraries this statement wouldn't be true.
React components may have local state (as much as some people hate it, some find it useful), they have a lifecycle, can react to receiving new props with side effects, can implement diff bail-out hook. And you can nest such components declaratively.
And declarative nesting is a feature of all of the frameworks I've come across, I'm not sure why you think that's unique to React. The advantage feature I would credit React for is the size of its community and influential advocates like you.
Declarative nesting of lifecycle-ful and stateful components without going full FRP.
I'm actually excited to learn about other frameworks that do this! Which do you have in mind?
If you are interested in academics, I published such a system at ECOOP in 2006:
http://research.microsoft.com/pubs/179366/mcdirmid06superglu...
FRP is based around the idea of declarative components, but a lot of developers have an aversion to it because of the academic aura around it.
React's innovation is using virtual DOM to make declarative components usable without delving into FRP.
Not just that. I may be stupid but personally I find it mentally simpler to `setState` than to `flatMapLatest`. To each their own I suppose.
>React's innovation is using virtual DOM to make declarative components usable without delving into FRP.
Precisely.
>The "declarative component model" is not an innovation, it's an obvious approach [..] can achieve the same [..] by [..] obviously doesn't perform and has some edge cases where it breaks things (textboxes, for example), but the idea is the same
React is not an academic paper, it's a tool. It doesn't need to have new ideas, it needs to execute on them in a practical way. Which it does.
You should also check out Mithril: https://www.npmjs.com/package/mithril
Not everyone is ready to go into FP-land right now.
React lets you take these decisions yourself.
Whether local state is practical for your team or not.
You must be living in a very different world than mine if you think that compared to its rivals (Angular, Ember, etc), React is somehow “encouraging” local state. Sure you could go more functional than that, but take a look at the mainstream frameworks and you'll see it's such a long way to go, that had React not allowed local state, it would not have gotten adoption at all.
All I'm saying is that when people praise React I wish they were really praising what you call "declarative component model".
React is receiving 100% of the attention in this space when imo it should be receiving about 75%.
I long for time when these concepts are boring enough no one thinks of React anymore. Sadly we're not there yet.
I just want to emphasize again that Flux is entirely possible without singletons, and works just as well on the server if you create new instances for every request. Flummox does it, Fluxible does it (at least for stores). It's just a shame Facebook pushed singletons and then everyone followed their lead.
I also think flux's real-world implementation came from the necessity to build React components within pre-built apps, where they simply didn't have the ability to pass down props because they had to create complete separate components.
The approach that raynos/mercury takes where state is fully decoupled from layout/rendering is the way to go. In mercury, all the render functions are composed together to make one large pure function. You give it the current state and it deterministically will always render the same layout. So much better than the react approach. Furthermore, the complete decoupling from the rendering functions and the reliance on using bijective lenses with shallow copying means you get time travel debugging for free (i.e. undo redo is available right out of the box)
It really has nothing to do with React's approach, at all.
[1]: https://github.com/muut/riotjs/blob/master/lib/view.js#L75
Either I'll be unnecessary stubborn and miss this awesome new tech or I'll shovel my opinion aside and do try working with this approach.... or at least until someone else introduces new framework that comes with code separation.
It's not the end of the world.
When you think of it this way, it makes sense. From a designer perspective it doesn't, and you have to adapt designs into a view, just the same, you usually do anyway.
Events happen to be triggered by the view and they affect global state which is then reflected in the view.
This is the separation of concerns you want. Components don't need to know about events beyond triggering the ones they need. Components only worry about rendering state.
After learning react something conked in my brain. As I rehashed the arguments against logic in views, I realized that they recapitulated FP's arguments against uncontrolled mutable state, just without the nuance. Nothing wrong with purely functional logic/computation itself. And that delineation feels a lot less arbitrary than "logic in views is bad".
To be clear, I'm not arguing you should implement domain logic in your views. That's a dumb strawman.
But the religious fervor that people have against logic in views is absurd. Reexamine why you think logic in views is bad, and I think you'll find the arguments are actually against 1. poor factoring resulting in ridiculously complex views (and hiding logic is a halfass, crappy way to control complexity) or 2. mutable state.
This is in contrast to a model where you mutate an existing UI model each time something interesting happens.
React is closer to an immediate-mode UI model: you write programs that compute exactly what the UI should look like on each frame, rather than mutating a scene graph each time something interesting happens (as occurs in retained-mode UI models). Substitute DOM for scene graph, and the distinction might hold.
But I'm not sure.
But yes, exactly. React is similar to an immediate mode graphics API. Except that also has weird connotations, because people think of things like canvas that are very low-level: all you get are lines, arcs, and fills. React's primitives are at the same level of abstraction as the DOM, you just work with them in immediate mode, not retained mode.
In contrast, a UI model like WPF uses (declarative) data binding to achieve something similar, but without as much flexibility and with more verbosity.
I'm working on a system that allows for state retention in an immediate mode model, though wrapping WPF rather than HTML:
http://research.microsoft.com/en-us/people/smcdirm/managedti...
> With the latter, you're also interfacing directly with native objects all the time, which is doomed to fail performance-wise. React Native actually performs the layout on a separate thread [...]
Wrong. With Titanium you work with proxies. And JS is in a separate thread. The only actual difference between ReactNative and Titanium on this side is the functional/fully-declarative/almost-stateless vs imperative DOM-like philosophy.
Let me slip this through: «if you don’t know something then don’t make it look like you do».
Sorry for the rant. I’m just very upset from yet another post like this.
The lack of a function/reactive componentized UI paradigm forces you to work with native objects (the views) a lot. React can optimize how much it touches the bridge because you don't interface directly with the UI. From what I've seen, Titanium can't do nearly as good of a job as that because it's like the DOM. You touch the UI in several places and it needs to always talk across the bridge.
I never said it doesn't run JS on a separate thread. React performs layout on a separate thread, providing the flexbox layout algorithm.
EDIT: It's all of these little details that can make or break something like this.
Much of what makes React Native special is that everything -- from the original React API all the way to the latest and greatest bridge stuff -- has been designed with the assumption that the bridge (DOM) is the bottleneck so everything is batchable and async.
The API that Titanium gives you is much more traditional OOP which means that developers can easily create applications that chatter over the bridge.
If you coupled this with conditional stuff around what kind of form factor you're on (screen size, etc.) you could design mobile first UIs that gracefully enriched on a larger form factor. Lalalalalala!
I don't know of Facebook cares, but I WILL PAY FOR THIS! For a well-engineered modern platform that did all of the above I would pay thousands of dollars. So if the choice comes down to staying free and abandoning this effort vs. making it a profit center, please for the love of all that is holy take my money.
Really when you look at the labor costs of developing parallel UI efforts on many platforms, a cross-platform dev system that delivered a high quality native-feeling experience across every major platform could be worth at least tens of thousands of dollars to millions of people.
I honestly believe you will be able to see something like that in the near future as device gapping technologies gain more momentum.
>bloated code sizes, interop issues, poor runtime performance, etc
I've heard about no such problems about ClojureScript. In fact there's less code size than you'd usually have because Google Closure Compiler advanced more works with it out of the box[2]. It's also fast because immutability.
[1]: https://github.com/omcljs/om
[2]: http://swannodette.github.io/2015/01/06/the-false-promise-of...
I have used cljs for non-mobile web interfaces, but the performance of Om in Phonegap on mobile hardware was terrible enough that I scrapped it for Xamarin.
Secondly, Om in a Webview and Xamarin are not fair comparisons.
What about shared immutable data structures?
As Douglass Crockford says, JS is a great language with some terrible parts. I don't understand why some people can't get past that.
Having many different parts by itself is enough to make a language bad. The fact that some of the most important of those parts are basic makes it terrible.
Have you given CoffeeScript a try? Bloated code size and interop issues are essentially nonexistent. Poor runtime performance is a non-issue with most C2JS languages because, well, they're compiled.
Websharper (http://websharper.com/) for F# is now Apache-licensed and comes with the UI.Next framework that provides a really nice reactive paradigm for creating web UIs. Unfortunately it doesn't help with mobile apps as React Native does but is still pretty good.
Since the JS execution is isolated on a single thread and communicates with the main thread via a bridge, it should be possible to implement the rendering code, vDOM diffing, bridge etc in any language you want. That might take some effort, but I can't see any fundamental reasons why it wouldn't work.
js_of_ocaml has good code size and performance in my experience. Interop with js is variable -- some js libraries are inherently typed and are easy to bind to in a well typed way, others use very dynamic typing and those are difficult to bind.
But if you want to access an API, you still need to wrap it. Depending on the API, you need to be careful performance-wise. Native React avoids a ton of problems that other frameworks have though because they provide a solid mechanism for dynamically working with UIs, and it's very efficient because they only send minimal diffs across the bridge.
1) You don't have full access to native SDK functionality (e.g. all the latest cool things in iOS8). You're going through a cross-platform API wrapper and limited to the choices of the framework architect. So it can be frustrating to go down this path only to find you still can't quite get the native experience you want.
2) Debugging is harder because the native toolchain (e.g. Xcode) doesn't understand the framework. You have to rely on tools provided by the framework.
AFAICS the author doesn't address these issues. He seems to focus largely on the (theoretical?) performance optimization of not crossing the JS-to-native bridge as much in React... by being even more isolated from the native APIs and doing more work in JS. But even if true, performance was not the chief complaint with the closest predecessor to this.
For #2, there's actually a great story. You can literally run the JavaScript inside an existing engine, like Chrome or Firefox, and serve it from there. You can use the normal devtools and set breakpoints on the JS.
I totally understand where the author is coming from, and do agree... BUT there is a flip side to this, which is that HTML and CSS enable us to come up with and implement totally unique designs and interfaces. The lack of standard layout and complex "widgets" is definitely a pain in the ass, but it also enables a lot of unique-looking websites and designs. It's kind of a pet peeve of mine when platforms/CMS's try to output markup instead of just providing data to the view layer... they are always outputting the "best practice" (if lucky) at the time they were built, and then a year or two later you want to do things a different way and you're stuck.
So I'm super excited about React.js and love the simple mental model with flux etc., but another part of me also worries that one can't dictate the markup exactly the way one wants because it has to be recognizable to the virtual dom as well (or the iOS view in native, or whatever other front-end React will output to). Maybe someone with more React.js experience can enlighten me about this though? (I've only dabbled).
I'm not sure what you mean. On the opposite, with React, you specify exactly the DOM (or UIView) tree you want to get.
You will build different components for React web and React Native, there's no common ground between them. The platforms are too different.
It's just due to React <=0.12 using an HTML tag whitelist to tell native tags from custom components. It's not an issue anymore in 0.13, where any HTML tag (including custom Web Components) will work: https://github.com/facebook/react/pull/2830
There's still an attribute whitelist, and that's a trickier problem to solve: https://github.com/facebook/react/issues/140
Souns a lot like GWT, s/Enterprise "architects"/Web "ninja"/ to me.
This blog post summed it up perfectly for me: https://joshaber.github.io/2015/01/30/why-react-native-matte...
[ReactiveCocoaLayout](https://github.com/ReactiveCocoa/ReactiveCocoaLayout) is a good example of how much work it takes to get close to this pattern, but the view lifecycle as a whole (adding and removing subviews, layout passes, etc.) makes it hard.
From what I understand React-Native does this for you natively under-the-hood, but using JS as an implementation detail.
I really don't think that anyone is advocating for JS being the "better language", but rather one that has a framework (read: React.js) being used in practice which will work with native view as well.
Very interesting that this stuff comes from Facebook, who have very little concern about being indexable by search engines.
This does look interesting, but honestly, I think this can either already, or very soon, be replicated on the web, a platform which holds tremendous advantages that native will likely never be able to catch up to. Perhaps there's an argument that these apps can also be translated to the web when their time comes, but I wonder what sacrifices are being made in the name of going Native?
React Native seems to be an attempt to fight in the opposite direction (Web -> native) while the real momentum is going the other way (native -> Web), and the best part is, you don't even have to do anything to get it, the major players are building that open ecosystem for us.
Looking at what HTML 5 offers and what any native platform from desktops to mobiles OS offers, I would rather stay with the disadvantages of native platforms.
> while the real momentum is going the other way (native -> Web)
Really?
Is WebGL OpenGL 4.5 compatible already?
What about those sensor APIs?
Oh, which browser is doing OpenCL and CUDA?
Web is stuck in a 90's desktop feature level and it will always be playing catch up native.
The real direction is web -> native/micro-services.
What the web has going for it (and what native will never catch up to) is having solved the distribution problem. Fact is, I can deploy to more machines, faster, and more securely than native (at least if there remain fragmented vendors) ever will be able to. I can already access most sensors and can run shaders. It's not like it's difficult to get what's missing into the browsers either and all the native vendors are also spending the resources to develop the browsers.
apt-get, yum, app stores, click once, web start, ...
Web: URL + links
>a url
pick one
>a url with a JavaScript exploit
>a url with a img/css browser buffer overrun
>a url with cross site scripting
I see no difference.
EDIT: Actually I do. I is easier to exploit users that can't wait 3 minutes.
I know that it has taken Titanium years to mature, so I wonder if it will take a similar amount for React to iron out the bugs - I'll be surprised / pleased if they hit the ground running.
Hopefully they'll hurry up and make it public!
They could have control of their application and behavior and make even more changes than before without re-submitting to the App Store.
...running in a WebView. So yes, RN apps will not enable this.
"React Native actually performs the layout on
a separate thread, so the main thread is as free
as it can possibly be to focus on smooth animations
(it also provides flexbox for layout,
which something that no other framework provides)"
Interestingly - though perhaps increasingly less relevant - this is how BlackBerry 10 platform native QML-based applications work as well.What does React bring to the table that these do not?
Layout (which is also behavior if the layout changes with the dimensions of the viewport) and animations are two things that need to be removed from CSS and implemented in JavaScript.
Yes, animations probably should be in JavaScript, but you probably shouldn't do them in JavaScript right now as they won't be hardware accelerated. The reason it works well in CSS is that you're setting a property and letting native code do the rest, whereas in JS you need to set a property in each requestAnimationFrame() call. Not good.
i believe we should be able to see javascript being used as a responsive language portable across all devices and being used to control native components as a separate layer.
im actually working with a flexbox xml/html wrapper framework for iscroll that i might use to build a responsive app that not only does pc animations but performs alot of nice mobile slider animations that seem to go at 60 fps on modern handhelds, but its up to emerging gapping technologies like cordova and this to make the use of future "responsive ui kits" which i believe should be emerging soon.
There is also localStorage (not in this release though), but it's not 100% compatible because it has an async API.