The Future of Ember Templating
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 37 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/34716 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EmberConf 20169 / 37
4
5
7
10
11
13
14
15
16
17
20
23
24
25
26
27
29
30
31
32
00:00
CodeVideoconferencingData typeScripting languageContent (media)Component-based software engineeringChainCodeProcess (computing)Population densityContent (media)Musical ensembleLimit (category theory)InternetworkingConnectivity (graph theory)Mereology1 (number)Bookmark (World Wide Web)TwitterXMLComputer animation
01:28
Category of beingSound effectCommon Language InfrastructureWebsiteState observerProcess (computing)Axiom of choiceProjective planeContent (media)Point (geometry)Server (computing)Computer animation
03:05
Linker (computing)Vector potentialMultiplication signProjective planeWordSign (mathematics)Ferry CorstenOnline helpOffice suiteFormal languageJSONXMLUML
03:44
Correlation and dependenceCompilation albumSign (mathematics)WebsiteComputer animation
04:13
Template (C++)Declarative programmingComputer programInterface (computing)Message passingString (computer science)Constructor (object-oriented programming)MereologyLattice (order)Boolean algebraoutputAreaObject (grammar)Pay televisionOperator (mathematics)Core dumpResultantLibrary (computing)MathematicsSingle-precision floating-point formatDifferent (Kate Ryan album)Boolean algebraInterface (computing)State of matterCASE <Informatik>Similarity (geometry)Computer programmingString (computer science)Key (cryptography)System callPhysical systemParticle systemPower (physics)NeuroinformatikCategory of beingNatural numberMaxima and minimaImplementationACIDLevel (video gaming)Pattern languageData structureGroup actionParameter (computer programming)Military basePrimitive (album)Fitness functionFunctional (mathematics)RecursionChainValidity (statistics)Content (media)BijectionWordMultiplication signReferenzmodellTemplate (C++)Channel capacityDeclarative programmingSlide ruleRight angleAbstractionVariable (mathematics)Performance appraisalBit rateWaveInstance (computer science)Web browserDiscrete groupFraction (mathematics)Projective planeFocus (optics)Information securityTerm (mathematics)Extension (kinesiology)Data transmissionHypothesisKeyboard shortcutReference dataTransformation (genetics)Combinational logicSocial classWebsiteFreewareWritingModal logicConstructor (object-oriented programming)GodFunction (mathematics)Endliche ModelltheorieTouchscreenXML
12:48
String (computer science)MereologyLattice (order)Constructor (object-oriented programming)Boolean algebraLevel (video gaming)Revision controlRun time (program lifecycle phase)Block (periodic table)Radio-frequency identificationBloch waveUniform resource nameComputer iconOpen setNumerical digitExecution unitEmailInformation managementMaxima and minimaBuildingCellular automatonLipschitz-StetigkeitInclusion mapCovering spaceFood energyWeb browserTemplate (C++)Physical systemPrimitive (album)Mathematical optimizationCompilation albumPoint (geometry)Line (geometry)Sheaf (mathematics)Validity (statistics)Multiplication signLimit (category theory)MereologyoutputBit rateObject (grammar)Revision controlVirtual machineVideo gameCodeBitWorkstation <Musikinstrument>BuildingIntegerRight angleLibrary (computing)WordDynamical systemComputer programmingComputer fontPhase transitionLoop (music)Dirac delta functionNumberQuicksortRun time (program lifecycle phase)Cellular automatonCategory of beingConnectivity (graph theory)Operator (mathematics)Form (programming)CASE <Informatik>Representation (politics)Just-in-Time-CompilerProgramming languageType theoryArtistic renderingSingle-precision floating-point formatInformationRadical (chemistry)Software bugDampingPoisson-KlammerSpring (hydrology)WhiteboardCommunications protocolInterface (computing)Functional (mathematics)MathematicsLevel (video gaming)String (computer science)Content (media)Real-time operating systemComputer architectureElectronic mailing listProcess (computing)Entire functionDifferent (Kate Ryan album)OpcodeCompilerComputer iconDirection (geometry)Proxy serverBytecodeVisualization (computer graphics)RoutingSoftware repositoryVariable (mathematics)2 (number)ParsingStructural loadImplementationResultantFunction (mathematics)
21:23
Adaptive behaviorConvex hullTerm (mathematics)Form (programming)Artistic renderingElement (mathematics)Bound stateString (computer science)Interface (computing)Integrated development environmentCompilerOperations researchElectronic program guideRead-only memoryRight anglePhysical systemPoint (geometry)CASE <Informatik>Endliche ModelltheorieConnectivity (graph theory)ResultantPrimitive (album)Artistic renderingCartesian coordinate systemPosition operatorCycle (graph theory)Cursor (computers)outputElement (mathematics)Object (grammar)HypermediaTemplate (C++)Social classComputer architectureClassical physicsRun time (program lifecycle phase)Field (computer science)Mathematical optimizationComputer iconReal numberProgramming paradigmMultiplication signFreezingAtomic numberPerformance appraisalWage labourStrategy gameOpcodeInterface (computing)Different (Kate Ryan album)Logical constantAbstractionMatching (graph theory)QuicksortNatural numberLine (geometry)Client (computing)Core dumpIterationVisualization (computer graphics)CodeGreatest elementTunisDependent and independent variablesSoftware testingIntegrated development environmentWeb browserLimit (category theory)Goodness of fitProcess (computing)Traffic reportingExterior algebraOpen setImplementationMathematicsAlgorithmAdaptive optimizationContent (media)Speech synthesisOperator (mathematics)InformationRoundness (object)Compilation albumBoss CorporationSubsetWordMusical ensembleOnline helpBuffer solutionParsingMultiplicationElectronic mailing listSystem callType theoryFlagInterpreter (computing)Software bugMobile appDynamical systemSound effectMacro (computer science)Entire functionServer (computing)NumberNetwork topologyLoop (music)Mixed realityXML
29:59
Figurate number
30:28
Selectivity (electronic)Table (information)Staff (military)Different (Kate Ryan album)Line (geometry)Bus (computing)Multiplication signImage registrationSlide ruleGraph (mathematics)WordChainGoodness of fitComputer animation
Transcript: English(auto-generated)
00:15
I'm not quite starting yet, but before we start, I would like to give you a fair warning.
00:24
What is gonna happen in the next half an hour is you will see a lot of very dense and technical content. There will be TypeScript code involved. It would probably not help you with your job, and you might actually want to reconsider going to Mixonic's component talk and it's gonna be a great talk,
00:42
and it's gonna be very practical. It's gonna help you with your job. And you should only stay here if you're up for really, really dense technical content. You have been warned.
01:02
No one's taking the bait, okay. All right. A couple people. Okay, so let's get started. Hello, I'm Godfrey. You can find me on the internet as changing code. If you were around last year, you might remember me as one of your favorite speakers with glowing reviews from Twitter and papers like I have no idea what this talk is about
01:21
and the changing code deliberately misspelled temperature. You may also remember me as a Canadian or perhaps for my very important technical contributions such as the Canadian style sheet spec. As you can see, it fixes some of the glaring typos
01:41
in the CSS spec and made a lot of things more polite in general. So, this is actually an Ember CLI add-on you can get today, but unfortunately, it doesn't have a lot of points on Ember Hub server because it didn't have enough downloads, but nothing can fix with a few hundred people in the same room.
02:02
I'm sure you can fix that for me. Anyway, unfortunately, I talked on a new job last year with a company called Tilder. Since they're located in Portland, I have no choice but to move Canada to Portland, so I'm very pleased to be the first speaker at the conference to welcome you to Portland, Canada.
02:20
If you don't believe me, you can look at my bio. It says my job title is in-house Canadian at Tilder and it's listed on the conference website, so you know it's true. Anyway, with my credibility blown away from last year's talk, I figured the best way to recover from that is to do a really technical talk with Yehuda, and so you're probably here for Glimmertude.
02:43
So Glimmertude is a huge project. Yehuda and I have been working on this for over half a year and there are just way too many, way too much content to fit into a 30-minute talk, so I just want to warn you that there will be a lot of hand-waving going on in this talk,
03:02
and yeah, but I figured that would fit in pretty well with the conference theme anyway. Before I begin, I just want to thank Tilder and LinkedIn for sponsoring our time to work on Glimmertude. Without their help, we probably couldn't take on such an ambitious project.
03:22
You probably don't know this, but LinkedIn is a really cool company. As you can see, they own the most punable two-letter word in the entire English language, so as you can imagine, there are a lot of puns everywhere in the office, but I don't think they realize the full potential of the assets, so I decided to give them some suggestions,
03:43
if they, hopefully they don't mind. I think their signs at the parking lot could use some work and perhaps they should rename their design team, and I fixed their website for them. And I also fixed their ad campaign.
04:02
If you know anyone from LinkedIn's marketing department, please consider hiring us for your next campaign. Anyway, with all of that out of the way, let's get started. Glimmertude, so throughout the history of Ember, we have always spent pretty hard on declarative templates.
04:21
In fact, the original goal of the Ember project was to add template support to Sprout Core. And one of the things we love about templates is that it's just HTML and CSS, you already know how to write them, and your designers already know how to write them, and HTML and CSS is great.
04:43
But that's easier said than done, because there are actually a lot of edge cases in the HTML spec, but thankfully, it's carefully spec'd so people who work on browser know how it works, so the best way to handle all the edge cases in HTML and CSS
05:02
is basically to implement the HTML spec, and we did that with HTML parse, we have a spec-compliant HTML parser, it supports SVG and all the weird things in there, and I think that result pays off. And the other thing we like about templates is that they're very declarative, and it turns out declarative is just a fancy way
05:22
of saying they're a pure function of states, but more importantly, they're actually FRP programs, whatever that means, it basically means they're a program that you can run over and over again to get the latest results, put them on the screen.
05:41
So I guess I will leave the rest to Yehuda and Kevin. Unfortunately, we only had a three-minute budget for jokes and God free took the whole thing, so I'm just gonna dive right in. So the core primitive of Glimmer is the reference data structure.
06:01
Fundamentally, a reference is just a stable object that represents the result of a pure site of free computation, where the result of the computation might change over time. So here is the interface, this is, if you know TypeScript, this is like the simplest interface you could possibly write, and if you know, if you've read anything about FRP, this is pretty similar to a discrete FRP signal. The key difference between references
06:20
and similar constructs in other libraries, including in Glimmer one, is that references are completely pull-based with no notion of subscriptions or notifications. What we found through experience, having done this for a few years now, is that a pull-based system is a better fit for the kind of problems we're trying to solve, especially when maximum efficiency is at stake. So to give you an idea for the flavor of references,
06:41
let's make a very simple reference that captures the foo variable over its lifetime. This is a very simple example, but it illustrates the power of the reference abstraction. Even though JavaScript variables always contain values that can be passed around and held onto by other functions, variable bindings themselves in JavaScript are not a first class value.
07:02
The idea behind references is that using the reference system is trivial to pass a variable by reference, hence the name for the reference data type. To give you, sorry. Now, interestingly, because the reference is such a simple concept to begin with, it's very easy to compose two references. So we're gonna look here at the thing which is the add reference,
07:21
so we have the foo plus bar reference. And hand wave, hand wave, you don't have to know exactly how this works, but it's pretty small, you can see the composition works pretty nicely. It's therefore also really easy to create functional combinators for them. And in fact, it's very easy to write the usual functional combinators that you would have expected from any streaming kind of primitive,
07:40
as long as it makes sense for discrete values. I can't go into this too much more, but reference also has a lot of other cool properties. For example, they are also a natural fit for lazy evaluation, which makes it easy to implement things like short circuit Boolean logic correctly. Okay, sorry. So at a high level, this slide,
08:00
what this slide is saying is a template that you've seen before. Each of the curlies here is represented by a reference. On the initial render, we're gonna pull a value out. On an update, what we're gonna do is we're gonna pull a value out and replace. So with that, that's a very, if that felt simple, you're probably gonna be okay. If that felt complicated, good luck. I got it.
08:21
So while it is cool that the core reference interface is so simple and so flexible, they could also be hiding or encapsulating arbitrarily expensive computation under the hood. Therefore, it's usually a good idea to avoid recomputing reference value more often than necessary.
08:41
In particular, because references are modeling pure computations, that means they're basically just taking some inputs and making some outputs based on the inputs. And if the inputs didn't change, then there's no reason to reevaluate the value of a reference.
09:01
For example, helpers in handlebars are required to be pure functions that operate solely on its input arguments. So if the arguments didn't change, then the result of the helper invocation also wouldn't change. And here we have two hypothetical helpers, concat, which joins the arguments together
09:21
into a single string, and uppercase, which takes a single string as input and capitalize all the letters in the string. So let's see how we can model that as references. Let's start with the uppercase helper. The uppercase helper basically describing a simple map operation that takes a single input and apply one-to-one transformation on it.
09:41
The implementation is pretty simple. It basically takes a single reference as input, and to compute the value, it takes the value from the input reference, which returns a string and call to uppercase on it. The concat helper is a pretty similar story, except that it's describing a reduce operation
10:01
that takes multiple inputs and reduce them into a single value. The implementation is pretty similar, though. It takes an array of references as input, and to compute the value, it evaluates all the references into an array of strings, and then it called join on the array to arrive at a single string.
10:21
As you can see, the inputs of both of these helper reference are very clearly enumerated. Uppercase reference is a map operation that takes a single input reference as input, so it should only be recomputed if and only if the input reference also needs to be recomputed, or if the input reference has changed.
10:41
On the other hand, the concat reference is a reduce operation that takes an array of references as input. Therefore, it needs to be recomputed if and only if any of the inputs has changed. This presents a recursive problem. If we have a way to determine the freshness of the input references,
11:02
then we also know how to model the freshness of these helper references. In other words, we need a system that allows us to describe the freshness of a computation in terms of its inputs. This is exactly what the validation system in Glimmer is designed to do. The core primitive here is called an entity tag.
11:21
An entity tag is a stable object that provides certain guarantees about the freshness of a computation, or a computation result. Specifically, an entity tag has a value method on it that returns an opaque validation ticket. When you want to catch a computation, you should also acquire a validation ticket from the associated tag.
11:43
This ticket can later be passed back into the validate method on the same entity tag to determine the freshness of the catch value, which returns a boolean value, indicating whether the catch is still good or not. More specifically, or more accurately,
12:00
it determines whether the catch result might have changed since the validation ticket was printed. I can't spend too much time on this, but so let's set aside the fundamental question of how to derive freshness in the first place and focus on the composition aspect of the validator system.
12:22
So let's say we have an extension to the reference interface that requires each reference to have a corresponding tag. This tag will tell you whether you need to recompute the value of a reference again. Now again, we're just assuming this tag works by magic for now, but with this primitive,
12:42
we can go back to the helper references. More hand wave. Here, we have updated the uppercase helper reference to implement the tag reference interface. So to satisfy the interface, we need to have a tag on the reference.
13:01
Not a problem, though. Here, we're trying to express that if the input reference didn't change, then the uppercase reference also didn't change. So we can just proxy the tag from the input reference directly. The concat reference is slightly more involved
13:22
because we need to combine all the tags, all the input tags into a single tag, but the concept is not that complicated. The idea is pretty simple. Instead of having to give out a single value as the concat reference validation ticket,
13:40
you hand out an array of validation tickets and recheck all of them against each of the upstream tickets during revalidation. So while the entity tag system is pretty cool and very flexible, if we are willing to forego some of those flexibility, we can implement that much more efficiently. In Glimmer, we use a specialized version
14:02
of the entity tag system called revision tagging. This system pairs a global revision counter with a per-object revision counter, which I can't get into too much details here, but the biggest benefit of the approach is that when it allows us to compress
14:21
an arbitrary number of validation tickets into a single integer, making it significantly more efficient to both store and compute the revalidation result. More in with. There are a lot of details that we couldn't cover here,
14:40
but I've started to write a mini book on the Glimmer repo with a lot more details that I couldn't cover here, so you should check it out after the talk. So all right, let's take a deep breath, everyone. We have just went through a very quick tour of the Glimmer primitives, but how do we actually build a rendering engine out of that?
15:01
So brace yourself, we are leaving the station again. I would like to give you a very quick, high-level overview of how the Glimmer runtime works, and one of the biggest realization when we're building Glimmer 2 is that the template is actually describing an FRP program, so we should just do whatever the programming language
15:22
implementers usually do to make the program as fast as possible. So we built a JIT compiler and a byte code VM for our templates. So what does that actually mean? So what happens when you have a template like this and you want to render that in Glimmer 2?
15:41
The first step actually happens at build time. When you run ember build in a terminal, it first compiles that into something we call the wire format. Here's a formatted version of the wire format, but it's basically just a simple representation of the precompiled template. This allows us to front load some of the costs of parsing the template at build time
16:01
so users don't have to pay any of the costs. Notably, we switch from emitting JavaScript functions in JavaScript code in Glimmer 1 to emitting a JSON object in this step in Glimmer 2, which is how we reduce the template size by five times. And furthermore, because it's now data, not code,
16:20
the browser doesn't have to eagerly eval the code, and we can defer some of the parsing costs until the template is actually needed. Before your template is rendered for the first time to the user, we run the wire format through the runtime compiler to produce a list of instructions for our virtual machine.
16:44
And for simple operations like appending a stack string to the DOM, it's pretty much a one-to-one compilation. But for more complicated syntax, like the if conditional, the compilation is a little bit more involved. If you have worked with assembly or bytecode VMs before, the compilation is probably roughly
17:01
in line with what you expect. Otherwise, it might be a little bit intimidating, but you can safely hand-wave that away. The point of this runtime compilation phase is that we can take advantage of the information we have at runtime and encode them into a program that we can reuse when we render same template over and over again
17:23
in the future, like for example, you might switch away from run route and then you press the back button and you have to re-render that template from scratch again. Or the most obvious case of this is you have a loop and there's a single component inside the loop and you're repeating it over and over again. You only have to do this work one time for the entire loop. Right, so a concrete example is
17:42
when we see simple curlies, or in other words, a curly bracket with a single string inside it. At build time, we don't actually know whether that is a variable lookup or whether it's a helper invocation or a component invocation, because they all have the same syntactical form.
18:00
However, at runtime, we can do the triage once for each template and avoid repeatedly asking that question over and over again as we re-render the template in the loop or in a different route. So finally, when we actually get to executing this program,
18:21
two different artifacts will be produced in the process. First, it would render this template into the DOM as you would expect, because that's kind of the whole point of this thing. But more importantly, it also produced an updating program that you could run again to re-render the template.
18:40
Now, even though the original template might look pretty complicated, there are only exactly two dynamic things here that needs to be dirty checked every time. If you still remember the things we went through in the first half of the talk, each of these curlies here are represented by a single reference inside the updating opcode.
19:00
Furthermore, we also take advantage of the revision tagging system to avoid re-checking anything in most cases. This is how we got to the 60 frame per second re-rendering performance you saw in the keynote yesterday. Finally, when we're developing this, obviously it's very important that we understand what our program is doing.
19:23
So we built this visualizer thing that you can type in some live templates and look at the compilation output and play with the result. And with that, I'm gonna pass it to Yoshida to talk about some optimizations and future work.
19:41
So the point of this section over here is to say that if you thought what we already did was pretty cool, it's actually sort of the front line, the first line of what we can do. And I'm gonna present a bunch of optimizations that we were planning on doing in the future that are relatively small deltas over what we've already done. In fact, the first one is an optimization that we already did.
20:00
One of the earliest optimizations that we targeted and what we already implemented is what we call the const optimization. So if you take a look at, this is an example of the optimization at work when we landed the PR. So as Godfrey says, we always take a look at the visualizer when we're working on an optimization, try to figure out what's going on. And one way to think about this
20:20
is that there's a lot of, when you have a component, you might have some properties in the component that are dynamic. You might say, for example, let's say you're using the font awesome library. You might have faicon, icon equals, and then something dynamic. Or you might say faicon, icon equals, and then the string bug. And if you say the string bug, obviously there's a lot less things
20:41
that can actually change in practice. So in this case, what we were able to do is, and this was actually, it was more like what we were doing before was unnecessarily stupid, but interestingly, if you don't have this architecture in the first place, it's hard to figure out exactly what's going on. So the short version of this is to say, if there's a constant value
21:01
that's somewhere floating around, when we construct a reference for the constant value, we remember that it's a constant value. And then whenever we have any dynamic updating step that we would want to emit based on the input value, if we see that the input value is constant, we just don't bother emitting the updating opcode. There's no reason to even emit it. And in Glimmer, references can say that they're constant and we will avoid doing work.
21:21
This, and so here's another part of that same change. This same optimization could be applied to an immutable JS object in a read-only field, as well as the unbound helper. So expressing that something is unbound would do the same thing. And we get a lot of leverage out of this. Once we landed this optimization, it actually had pretty significant macro effects because in real applications,
21:41
actually do have a decent amount of constant values that come from the template in natural ways. Second of all, the VM architecture also makes it pretty easy to do adaptive optimizations based on runtime information. So let's say that the FA icon component doesn't happen to have a component class. So if you look at what happens when you,
22:01
in the visualizer, what happens when you start running a component is that we have to, there's a bunch of stuff on the bottom right over there that represents the component, and we have to run it and it does things like run lifecycle hooks, construct the component in the first place, et cetera, et cetera. And the point of this optimization is that if we see that there's no component, we can pretty much eliminate
22:20
the vast majority of that work, but we can only do that once we notice that there's no component class at runtime. We can also do this again once at compile time and we get the benefit of the optimization every time the template is called, which is very important in loops, but also if there's the same component used many times, we only have to do this work one time. But furthers, let's say that we have a component
22:41
that doesn't have a component class and the template is very simple. So let's say the simplest way to implement the FA icon component is you just, it's a template that has a I tag in it and says class equals FA icon, FA icon, and then like FA curly curly for the input, right? And again, there's really no reason that you should not be able to just take the result
23:01
and inline it at compile time. Of course, usually people's architectures can't figure that out, but the idea is that we wanna do something about this. So if you invoke it like, again, with a dynamic value, it's hard to do something very good, but if you invoke it with a static content, you would like to effectively replace the invocation
23:21
with literally just I class equals FA icon, FA bug and eliminate the component entirely. And the Glimmer architecture, so this optimization that I just talked about, which is basically noticing that the thing that you're trying to do is relatively simple and just doing the work, the evaluation at compile time. This is a thing that I've had in mind literally from the beginning of the Glimmer 2 work
23:41
and it's something that we built the entire architecture to make this optimization a layup. So the idea here is that if you look at the visualizer, the bottom right, the FA icon opcodes, there's like 10 opcodes there. What we can do is we can simply, we can basically eliminate all those opcodes because almost we know for a fact that all the things that it's doing are free.
24:05
Another optimization that we've had in mind is chunked rendering. And the idea behind trunked rendering is you would like to be able to stop what you're doing. So people have observed that basically you start rendering and some time goes by and the user's trying to scroll and things are janked and they're like,
24:20
oh, if only I could just pause and let the browser go back and then come back to the rendering after a millisecond and then keep doing that in batches, wouldn't that be awesome? And this is something that is an architectural question. It's not always so easy to break in the middle, especially if most of the work is happening in user code. In our case, because of the fact that, again, if you look at this thing, what's happening is a big list of opcodes
24:42
and we have an interpreter loop that's just running the opcodes one at a time, it's actually quite easy for us to say some amount of time has gone by, okay, given that that amount of time has gone by, we'll just yield to the browser and then when we come back, we'll just continue from exactly where we picked off. We haven't written this optimization yet, but the actual architecture is a bunch of calls to .next,
25:01
so it's very easy to just not call .next and then start calling it again later. So again, because the Glimmer rendering is an interpreter loop, it's pretty trivial for us to pause and resume the process at any time, which will give us responsiveness, which is also pretty important for rehydration. The idea behind rehydration, as you might know, is that we render the entire content on the server
25:21
and then update it once it gets to the client. The thing about rehydration is that that is also pretty straightforward with Glimmer and that's because all operations in Glimmer go through an element stack, which basically works with the DOM. You can see that this is basically an implementation of the HTML parser algorithm. It's a spec-compliant implementation of the non-error subset of the HTML tree builder algorithm.
25:41
So for example, if there's an operation that calls create element on the element stack, during rehydration, all we have to do is say, instead of actually creating elements, we maintain a cursor position and if create element is being called and the cursor is sitting in front of an element with that same tag, we simply return that element instead of creating a new one. So we replace just this interface here, these 10 or so methods,
26:01
with something that knows how to process an existing DOM and that's it, the rest of the system works exactly the same. I'm not announcing Glimmer native because not working on that, but it is also the case that the process of executing a Glimmer template itself is highly abstract. Here are the interfaces that deal with components. So there's nothing really stopping somebody
26:21
from implementing the component interfaces in a different way that was designed specifically for, that was designed specifically for native. Again, remember that all that's happening with your template is it's emitting a bunch of opcodes and the interfaces that you would need to implement Glimmer native are already extracted so you can do something different. Finally, if that wasn't enough,
26:41
the interfaces that you need to build the entire, to interface with the entire system are also well defined and this is the environment interface that Ember implements. So if you implement these handful of methods, then you're also gonna be good. So the Ember system is built by implementing the environment which has some number of hooks here and I'm pretty excited to see people experiment with alternative hosts for the Glimmer system
27:01
that for example might lean more heavily on immutable models or RxJS or whatever interesting technology people are excited about and want to explore more thoroughly. One of the greatest strengths of Glimmer in general is that its primitives are simple enough and powerful enough to allow people to model all kinds of data abstractions and mix and match them if they need to instead of being sort of forced into a particular paradigm
27:21
and I'm excited to see what people do with it. All right, so you can take a deep breath again. We're done with the technical part but before we wrap up, there are some people I would like to thank. So this, all of these Glimmer 2.0 work, once again, would not be possible if Tilde and LinkedIn were not sponsoring for a time
27:43
but that's not it. A few weeks ago, I spent a few hours, wrote this very long quest issue on GitHub outlining a lot of the work that we, a lot of the ground work that we still have to do to get Glimmer 2.0 shipped in Ember
28:01
and at the time, I honestly wasn't sure if this is gonna be a good use of time because it's pretty close to EmberConf. We have a lot of work to do and this took an entire afternoon to write and I'm not sure if people read it but the Ember community has proved me wrong. Just a few hours later, after this quest issue was posed,
28:24
over the weekend, we have received many, many pull requests flying in from people to the point that now there are too many pull requests waiting for me to review and that's very awesome. In particular, Chad and Gavin has paved the way
28:41
to porting a lot of these new tests and for example, Robert on the core team has landed the actual feature flag that allows you to enable this on your app. A lot of contributors, a lot of new contributors that have never contributed to Ember before has responded to the call for help and opened multiple pull requests to help with this effort
29:02
but that's not even it because we couldn't have built Ember, Glimmer 2.0 without Glimmer 1.0, without HTML bars, without handlebars and all the work that have paved the way to here. So a lot of contributors have paved the way for us and that got us here today
29:21
and based on what you could have just talked about, I think the future here is pretty bright for us and I just wanna say thank you everyone for being an awesome community member and yeah, thank you for being awesome. Thank you very much. Actually, there are two more things.
29:42
Speaking of thanking. I was just saying thank you to the community. Oh, okay. Thank you to the community. You should actually give yourself a round of applause. I'm speaking of thanking someone. The other day Leah told me someone made these stickers for me
30:02
and thought they were pretty awesome but I don't know who made them so I don't know who to thank and this secret person also dropped me some more stickers so if you know who this person is or if you know how I can get more of them because everyone wants them, please come talk to me afterwards and I have some stickers here
30:22
so if you want them, you can come ask for them after the talk and finally, there's one more thing. So three or more months ago, well, I don't know. Leah will say it's like a year of time. We started, we had a good idea for a swag item
30:41
at EmberConf and we actually did a lot of work and we thought we were definitely gonna get it by yesterday but for a whole bunch of comedy of errors, we didn't end up arriving on time but we didn't give up. Leah spent hours on the phone with various people and these things are here. We don't wanna give up on getting them.
31:01
We have a special final swag item for those of you who have made it through to the near end of the conference. So here is the swag item. There are three different bus toys. Everyone gets just one. If you stop by the registration desk before 6.20, the selection is random. You get whatever staff member grabs out of the bag and unfortunately, you don't get to choose. Please don't stop at the lines trying to negotiate.
31:21
Trading is encouraged and if you want to complete your collection, you can buy them at the DevSwag table until they run out. Thank you very much.