Who Moved My Cheese? Ember's New Filesystem Layout
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 | 27 | |
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/35704 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer | ||
Production Year | 2018 |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EmberConf 201810 / 27
3
4
6
8
12
13
15
16
18
21
22
23
25
26
00:00
VideoconferencingFile systemLinker (computing)Game theorySystem callBitFile systemArchaeological field surveyXMLComputer animation
00:40
Mobile appArchaeological field surveyArchaeological field surveyMathematical analysisBitFreewareLink (knot theory)Line (geometry)ResultantCurveRevision controlNumberEvent horizonPower (physics)Coma BerenicesMedical imagingLecture/Conference
02:19
Symmetry (physics)Digital photographyProjective planeVideo gameSource codeBitComputer animation
02:57
Correlation and dependenceModule (mathematics)BootingHuman migrationImplementationDirectory serviceData miningModule (mathematics)MereologyCodeBitProjective planeFile systemMobile appMultiplication signImplementationDemo (music)BootingProcess (computing)Point (geometry)Arithmetic progressionOrder (biology)Task (computing)Asynchronous Transfer ModeEndliche ModelltheorieConnectivity (graph theory)Cartesian coordinate systemTerm (mathematics)MathematicsAtomic numberClassical physicsLecture/ConferenceComputer animation
04:54
PlanningSet (mathematics)Software frameworkMathematicsRule of inferenceClassical physicsMobile appPhase transitionQuantificationGroup actionComputer-assisted translationDiagram
05:30
State transition systemBeta functionGezeitenkraftCase moddingCodeDefault (computer science)Euclidean vectorImplementationCodeState transition systemFlagCase moddingProper mapDifferent (Kate Ryan album)Game controllerMultiplication signMereologyStability theoryMoment (mathematics)Connectivity (graph theory)Cartesian coordinate systemBitReal numberComputer fileProjective planeBeta functionRoutingDemo (music)Goodness of fitSocial classScripting languageMobile WebSelf-organizationProcess (computing)Endliche ModelltheorieDiagram
08:18
Module (mathematics)CodeSuite (music)Software testingHuman migrationModule (mathematics)Lecture/Conference
08:43
Electronic visual displayCodeCase moddingEuclidean vectorService (economics)Component-based software engineeringPrice indexTemplate (C++)Installation artLink (knot theory)Human migrationEndliche ModelltheorieSource codeMobile appClassical physicsBitRevision controlFlagMathematicsDefault (computer science)Computer configurationPlanningControl flowAsynchronous Transfer ModeNumberCartesian coordinate systemComputer animation
10:01
ImplementationFile systemMobile appSoftware frameworkComputer fileCycle (graph theory)File formatTraffic reportingPhase transitionMoment (mathematics)Process (computing)Software bugCartesian coordinate systemBeta functionCoprocessorCuboidCommutatorArithmetic progressionImplementationPhysical systemComputer animation
11:08
Module (mathematics)Computer fileComponent-based software engineeringGroup actionPhysical systemSinguläres IntegralEndliche ModelltheorieData modelCloud computingModule (mathematics)MiniDiscFile systemMilitary baseEndliche ModelltheorieComputer fileSoftware testingTransformation (genetics)Directory serviceWhiteboardSoftware developerSource codeProper mapTemplate (C++)Connectivity (graph theory)Rule of inferenceMobile appProjective planeElectronic mailing listCartesian coordinate systemGroup actionCommon Language InfrastructureRevision controlInstance (computer science)NamespaceLevel (video gaming)CodeSuite (music)Social classPhysical systemMereologySerial portMultiplication signLatent heatAdaptive behaviorAtomic numberDoubling the cubeScripting languageSubgroupMUDProcess (computing)Meeting/InterviewComputer animation
14:41
Endliche ModelltheorieSinguläres IntegralInstance (computer science)Service (economics)Game controllerTemplate (C++)Component-based software engineeringEuclidean vectorPartial derivativeConnectivity (graph theory)Electronic mailing listComputer fileLevel (video gaming)Single-precision floating-point formatRule of inferenceSimilarity (geometry)RoutingBitDressing (medical)Greatest elementPhysical systemModule (mathematics)Cartesian coordinate systemRevision controlDefault (computer science)Type theoryHeegaard splittingCausalityDifferent (Kate Ryan album)Partial derivativeService (economics)Endliche ModelltheorieGroup action
16:24
Instance (computer science)Singuläres IntegralAsynchronous Transfer ModeDefault (computer science)Computer fileRule of inferenceType theoryElectric generator
16:49
Component-based software engineeringTemplate (C++)Sheaf (mathematics)Euclidean vectorHash functionProcess (computing)Software testingBuildingTemplate (C++)MereologyConnectivity (graph theory)RoutingModule (mathematics)Directory serviceElectronic mailing listComputer fileLocal ringOrder (biology)Mobile appCartesian coordinate systemFlow separationInterface (computing)Level (video gaming)Different (Kate Ryan album)AbstractionRevision controlRootSummierbarkeitTotal S.A.WritingRight angleCASE <Informatik>Electronic visual display
19:44
CodeTotal S.A.Component-based software engineeringElectronic mailing listModule (mathematics)Euclidean vectorNamespaceTemplate (C++)CodeCASE <Informatik>Point (geometry)Cartesian coordinate systemDirectory serviceConnectivity (graph theory)NamespaceForm (programming)Module (mathematics)Category of beingSoftware developerRevision controlSingle-precision floating-point formatReal numberData conversionClassical physicsBlock (periodic table)WordSource codeMobile appTemplate (C++)Level (video gaming)Scripting languageElectronic mailing listComputer fileLocal ringAbstractionHuman migrationRight angleSystem callPower (physics)Different (Kate Ryan album)Atomic numberSelectivity (electronic)Vector potentialMehrplatzsystemVideo gameLecture/Conference
23:24
CodeEuclidean vectorModule (mathematics)Component-based software engineeringTemplate (C++)Strategy gameHuman migrationMobile appDirectory serviceStrategy gameConnectivity (graph theory)Module (mathematics)Source codeHuman migrationRule of inferenceCycle (graph theory)Classical physicsCartesian coordinate systemAuthorizationDirection (geometry)Asynchronous Transfer ModeOperator (mathematics)Observational studyResolvent formalismDifferent (Kate Ryan album)Computer animation
24:53
Electronic mailing listStrategy gameHuman migrationNamespaceModule (mathematics)Power (physics)Template (C++)NamespacePoisson-KlammerAngleClosed setSelectivity (electronic)Computer animation
25:53
File systemModule (mathematics)Common Language InfrastructureFlagInstallation artFile systemScripting languageModule (mathematics)Classical physicsCartesian coordinate systemCommon Language InfrastructureFlagDifferent (Kate Ryan album)BitInstallation artRevision controlIntegrated development environmentSystem callComputer fileOrder (biology)Configuration spaceMultiplication signAreaVariable (mathematics)NumberMeeting/InterviewComputer animationLecture/Conference
26:55
Installation artHuman migrationModule (mathematics)CASE <Informatik>Content (media)Structural loadBitLink (knot theory)Connectivity (graph theory)Process (computing)Local ringDirectory serviceSoftware bugSource codeNamespaceWeb pageTemplate (C++)Line (geometry)Product (business)Classical physicsGroup actionResolvent formalismInstallation artMobile appLevel (video gaming)Human migrationPoint (geometry)Endliche ModelltheorieTwitterFlagType theoryAsynchronous Transfer ModeRoutingDifferenz <Mathematik>Module (mathematics)
29:50
Broadcast programmingLinear subspaceModule (mathematics)Exploratory data analysisPhase transitionLink (knot theory)Source codeMobile appGreatest elementSinc functionImplementationTrailModule (mathematics)Computer animation
30:34
Module (mathematics)Phase transitionBitPhysical systemFilm editingSoftware bugSource codeLecture/Conference
30:58
Linker (computing)AverageSquare numberDaylight saving timeRSA (algorithm)Coma BerenicesBlock (periodic table)Data typeComputer animationXML
Transcript: English(auto-generated)
00:19
Thanks, everyone, for being here today.
00:21
I'm excited to be back at EmberConf and giving a talk and hopefully talking about something that you're excited to learn a little bit about today, what's been going on. We're going to talk about module unification, our Ember's new file system layout, as probably most like lay people who haven't been paying lots of detailed attention would think of it. Before we do that, I just wanted
00:40
to take a look at the survey really quickly, really just one thing here. My company, 2N Created, has been doing a community survey for about four years now. Tom and Yehuda mentioned it in the keynote, and they said go check the results. You should go check the results. If you go to emberjs.com, there's like a button that sends you a link to it.
01:01
Kind of a cool thing is that the survey last year, we started collecting free text results, so we actually have like lots of data and essays that some people wrote and short quips that other people wrote, and it's actually pretty neat. Cora actually reads all that stuff. Yehuda was flipping through it last night, so like you are speaking truth to power, as it were,
01:23
when you participate in the survey. So thank you, if you did participate in the survey, how many people participated in the survey? Pretty good, awesome, yeah. So yeah, thank you for that, and thank you to our intern, Okonksha, who's here with us in Portland, to my coworkers, Isaac and Corey,
01:41
for putting in a lot of work to make this happen this year, and Tom Zilman, who worked with us last year on the survey and did a bunch of text analysis for us this year, which you can see in there. This particular chart is the upgrade curve chart, which I always really like, because it shows that people actually move forward with Ember. They are able to upgrade to the new versions, and we have a really good story around that.
02:01
So the peak there is like, the red line is 2.18, and then where it goes down a little bit is 3.0, because 3.0 had just been released when we did the survey, so I wasn't really surprised that it wasn't higher than 2.18, I wasn't disappointed either, it's okay. Yeah, but I am happy to announce at EmberConf here
02:20
that I have completed my own upgrade process, it's Ember 3.0, by removing all my deprecated features. It was a hairy process, but, oh, I thought this was gonna be a tough crowd one, that was pretty good, okay, cool. This is another photo of me. So, this is a photo of me in 2016,
02:42
so I had just moved to California. I am in love with my wonderful girlfriend, who I'm going to marry, and I'm thinking, you know what could make this life any better? I'll do a little bit of open source, let me just find a little project to work on. And there was an RFC that Dan Gebhardt
03:00
had been slaving over in the mines for a while, RFC 143, which described module unification, and I was like, yeah, it's like really detailed, so it must be well spec'd, and I can just like, you know, write a little bit of code, and we'll be finished with this thing. As you can probably guess, since the year is 2018,
03:22
didn't really work out that way, but we've made a lot of progress. In 2016, we merged that RFC. 2017, we had a basic implementation. Over the summer at EmberCamp, we did a demo of module unification apps, booting and running add-ons that were from classic mode add-ons. Kind of the last thing that we've been calling the golden spike was the ability
03:41
for a module unification app to invoke a module unification add-on component, and that's kind of like the Rubicon that we've crossed in the last few weeks, and that really sets us up to be focused more on concrete tasks that kind of anyone can participate in in order to get this to a point where it can ship. So, kind of a cool thing about this is that it has not been a fast process,
04:02
but it has been a uniquely Ember process. There is no major corporate backer. There is no like overlord in the sky raining money down upon this project. This is truly people in the community taking a day or two at their company or time on their own to contribute to this effort and make it move forward, and we've still been able to do that, which is, I think, pretty amazing and unique.
04:22
So, I'm gonna kind of run over three things. The first thing I'm gonna talk about here is how Ember does upgrades, because I think when we talk about how we're gonna change the file system of our applications, everyone wants to panic. And you don't need to. It's gonna be okay. Wrap yourself in that blanket. It's gonna be fine.
04:40
We're gonna talk a little bit about the feature of modular unification, the design, and what we get out of it, and then we're also going to talk about, of course, where it is in kind of really concrete terms. So, sit back and relax, and I'll show you how to try some of this stuff on your own at the end of the talk here. So, the first tool that Ember has that we use to get people to move from an API that we want to get rid of,
05:00
like you could say we want to get rid of the classic app folder and we want to move towards something new. How do we make that happen? The first tool is really deprecations. Deprecations in Ember have a couple, they actually have a lot of rules. In the 1.0 days, it seemed like deprecations would just fall fast on your app, and there wasn't really a plan. In the 2.0 phase, we really have stabilized
05:23
around a set of best practices that we have on deprecations. They kind of tell us how we can make changes to the framework and at what pace we can make changes to the framework. There's two big things to remember about deprecations, and one is that there will not be a deprecation until there is a replacement. So, I think a classic example of this
05:40
is routable components and controllers. Everyone's like, when are you going to deprecate controllers? Don't use controllers. They will not be deprecated until we have a thing that you can use instead. So, you should be able to use them with aplomb and feel good about it. And the second thing is that even if you use Ember, you consume Ember at a little bit of a slower pace. You're not keeping up with every single release.
06:02
Everything will be deprecated in at least one LTS. So, even if you are the most conservative of organizations, you're still gonna get all the same warnings that you would if you were keeping up with everything every six weeks. So, don't feel like you're missing out. So, if we wanted to take some API that we wanted to get rid of and we have a major release coming up and we're like, great, just wanna pull it out
06:20
of that major release, the first thing we need to do, of course, is have a new API to replace it. So, we need to RFC and come up with something that we're going to do. After the RFC, these kinds of projects tend to go through a little bit of like a walk in the woods where they might be an add-on, they might be a feature flag in Ember, they might be implemented a couple of different ways
06:40
and we're kinda hunting for what the real implementation of the thing is. Eventually, we'll have a real implementation in a feature flag and then we iterate and eventually, we can go with that feature and going a feature means that we decide it's going into Ember Beta where it will sit for six weeks during the releases and then during the stable release, it'll become part of Ember proper.
07:03
And this also tells us then like, where we can add the deprecation for our project. So, our deprecation has to be around for at least one LTS. So, we actually don't get to release it in the LTS. The way that an LTS release works in Ember is that we have a minor release, that release becomes stable, everyone can use it for six weeks and they're real applications and many people do
07:21
and after six weeks of being used in real applications in stable, that thing is declared in LTS. So, if you're truly on the LTS channels when Ember 2.16 comes out, you don't use 2.16 right away. You wait the six weeks and then you adopt it and so that means we actually need to add our deprecation six weeks before the last moment
07:40
where we have a real LTS. So, where is module unification in this process? It's like so far at the beginning, right? So, there's no need to panic about like when that deprecation is gonna land because you actually still have a good amount of time. A second tool that we use is code mods and I think we've had a couple different demos of code mods and looking at things that code mods can do.
08:02
A pretty common one that people used was the Ember modules code mod which took your JavaScript files that just use the Ember global and turn them into things that use the imports and if you haven't done this, I encourage you to take a look at doing it. Code mods are really easy to use and the Ember community has built a whole bunch of them.
08:20
Ember K gets rid of all those pesky old Ember Ks and turns them into like methods which is pretty great. The Ember native DOM helpers will get rid of a lot of the jQuery usage in your test which is something that you could have mentioned before. That's where there's a lot of jQuery usage. It won't get rid of all of it but it'll knock that problem down to like a manageable size where you can actually then drop jQuery from your test suite.
08:41
And the last one is the Ember module migrator and the Ember module migrator actually moves between the old legacy, I don't like calling it legacy, the classic app style with the app folder and moves it into the source style folders and we're gonna look at this in a little bit more detail later as well. And then kind of the third tool that we have
09:00
that's very new is optional features. Optional features are a way that, we've always been very hesitant in Ember about adding flags or toggles where you're like I wanna turn on this mode because that mode becomes a breaking change and it becomes hard to make sure that everyone actually turns on that little mode. The plan behind optional features
09:20
is that optional features by default when the feature is added to Ember it doesn't do anything at all. You're just able to install this add-on and you can look and you can see oh there's a feature here and by default it acts like it did before the feature was even added. But then you can enable or disable a feature and eventually we can tell people hey the best practice is you want to enable this feature
09:42
or you want to disable this feature and we can bake those things into Ember CLI and at some later date we can go ahead and add deprecations that say okay we're getting to a breaking release we actually want to make these flags the default in that next major version of Ember so it's deprecated to not have this flag enabled.
10:01
And the real idea here is that we do this a lot. We have a lot of tools at our disposal and we're really good mostly at removing stuff from the framework. So I think we can look at some stuff that we want to add to the framework. How are we going to ship this new file system, layouts, it has to go through all these phases
10:20
so we have to get an RFC, we have to get a canary implementation, we have to get that go moment where we can put it in beta and then there's going to be an even longer tail after that deprecation cycle. There's still a community process that has to take place where add-ons need to convert into this new format and applications need to convert into this new format as well and only when all of those things happen
10:41
are we really going to be thinking about when we can deprecate the classic app style. So that's really not going to be going away soon. But we have some progress. We're basically through two of these things and we're at this big pivotal moment where we can worry about the burn down. So don't panic, you're going to be okay but do experiment, try out some of the stuff
11:02
that I'm going to show you and see what it looks like on your app, report bugs and things like that so we can help move the process forward at a good speed. Let's go back to 2016 when we were discussing the original ideas behind module unification
11:22
and what we wanted to do with the file system on disk and why we wanted to make some of these changes and we're going to really focus on the design of things for a minute. So what is module unification going to actually do for you here? How many people use pods?
11:40
Okay, cool. So pods was a project that attempted to do some things similar to module unification and I think pods is really good at one thing in this list which is colocation. Pods lets you put your component JavaScript and your templates in the same folder and that's a thing that we want to bring to all Ember apps across the board by changing to this new file system.
12:02
Pods didn't do so well at some of these other things because it was really just a rearrangement of the existing practices. So it wasn't really good at creating isolation in any way where you could have things that were truly going to be private and were only accessible by one or two consumers and where you didn't have namespaces that were shared in between add-ons
12:20
in your application for instance. So some of the absolute basics for the new file system. I'm going to lie a handful of details like your app.js file turns into something called main.js. I think most of you would, if you were to see an app you would see those things and you'd be like, oh, this looks pretty reasonable and I can navigate this.
12:41
But the big thing to notice at the high level is that your source directory is going to be full of these groupings and we're going to use these folders to group related files and related concepts in the system. So for example, data is actually a directory that has two subgroupings. It has a grouping for models which is a list of all your models and then each model can have co-located
13:01
its model JavaScript adapters and serializers. Transforms are something that don't relate to any one specific model so they get their own directory where they can just list out by name. But we've gotten our similar things co-located and put into one place. There are things not part of Ember proper that we also want to co-locate in the system such as tests.
13:21
So the rule for tests and modular unification is basically as long as you have a dash test you can live anywhere on the file system and we don't really care. Well, anywhere in the source directory and we don't really care. We will find it, we will roll it up into the rest of your test suite and we will execute it. And so that leaves us room to both do things like lint if we don't want you to put tests in certain places
13:42
but also I think gives app developers a lot of freedom to come up with conventions that work for them as to where they want to keep their test files inside of their code bases. Another thing that's commonly going to be co-located is styles. And we have some improvement that modular unification gives us here. Styles themselves, kind of like tests,
14:00
they're almost a layer on top of modular unification. There's no firm rules about how to name them or anything like that or exactly where you have to put them. The thing that changes compared to older versions of Ember or the app directory in particular is that when the source directory is processed by Ember CLI, both the styles and your templates and your JavaScript are all available
14:22
at the same time to any add-on. So if you wanted to make an add-on that would say am I using any styles inside of the template that's in the same directory? Like do I have classes that are not being used in this template or something like that? That's very difficult to do in Ember CLI today with the app folder. It would be pretty trivial to do with the source directory. So that's a pretty nice improvement.
14:43
This is basically just a list of the big map of all the collections that we have. So we have models, which is a grouping, and transforms. The other high-level one is init. So the initializers get thrown into an init folder because having both of those things at the top level would be a little bit silly because we very rarely access them.
15:00
Services go on the top. And then there's a UI folder that contains two things where we've split up how you organize your application. The routes folder, which is such as it sounds, kind of similar to what the, well in pods, I guess what your pod folder looks like. And the components folder, which is very similar to just your components folder that you have in Ember today.
15:21
And we also have, of course, partials, but I'm gonna put them at the bottom of every list until people forget about them. There are kind of two variants up here of how we're naming a file that you might have noticed and might have thought a little bit confusing. So sometimes a file is named with its name, .js. And sometimes a file is named with its name slash type, .js.
15:44
And what are the rules for this system? So it's actually maybe a little bit more elegant than you might think. It's certainly not completely ad hoc. But basically the idea is that if a file is only its name, .js, it should have named exports. And those named exports are the exact same thing
16:01
as a default export from the type .js version of the naming So this allows us, it kind of opens the doors for us to explore things like single file components, where you could just have exports for three different things. You know, I'd dress it up in some kind of DSL, but at a low level, module unification is kind of ready for that kind of system where we can package these things up
16:20
and kind of combine them a little bit. Where you can do that, like where you have that name that you can just use, you have to have something called the default type, and that's available in a couple places. In practice, this is basically just feels correct. And the generators, when you use module unification, do the correct thing for you.
16:41
So you really don't need to think too much about where to put these files in practice. But I think it's good to look at how they were named and what some of the rules are. And this is all with the goal of giving us colocation. And it's similar to like if you're building a kitchen or something, you just want all your tools next to you. You want to know that your test is near your JavaScript and your styles are next to your template and things like that.
17:01
And that's really the goal of this part of work. Another thing that we have colocated, like another way that module unification helps us put things together, we have an app template here on the left-hand side. And on the right-hand side, we have a, which one is this, I'm sorry.
17:20
We have two components which are being called. And so the two components are in a directory called components, and then we're looking at the route template on the left-hand side here. And if this is the only place where these components are used, then we might not want to have them on the top level where all the other templates have to worry about that name. Like what if I want to create several gadget lists because I have several different versions
17:40
of different templates. I might want to isolate this. And so we have a feature that we call local lookup that's built on top of module unification. And local lookup provides a way for a component or a helper nested to be invoked only if it's nested beneath the invoking template. So in this case, we have the gadget template.hbs,
18:02
which is like the bottom file on the right-hand side, and you're able to access those components only from that one file because they're nested in a directory below it. We kind of had to bring the components directory with us when we did this before we had them in UI components, and now they're in this like routes dash components folder, so we had to pull that along with us in order to be able to access them.
18:23
But what if our template here wasn't actually a route? What if our template was a component? What would it look like then? In this case, on the left-hand side, we have the, you know, a component template, not a route template anymore. And on the right-hand side, you can see that we no longer have that dash components folder anymore. Because we're already in the components folder,
18:42
we don't need to bring it along with us. So you basically keep whatever, we call them collection, you're in if you're in the components collection. That's inherited for all of the subdirectories. If you're in the routes collection, the same thing. And if you want to go to components, you have to swap it with that dash components helper. And sometimes you have private components. So this is kind of nice,
19:01
because now our gadget list and gadget show are completely private to gadget display. Nothing else in your application can invoke those two components. They can't be accessed. And you can imagine for small helpers, this is also kind of nice, because you could have different variants of a helper with a really short name, and you don't need to like stomp on each other. But sometimes you actually want to like have those used as private API for that component,
19:22
but you want to be able to yield them out. And of course you can use a contextual component to do that as well. You could have your list and show, and you just close over the local thing from local lookup and yield it out, and now you have a completely private interface in gadget list and gadget show, but you're able to expose some of it to other consumers, say you're writing an add-on or something like that,
19:42
or just an abstraction in your own application. So this is a big improvement for the isolation in application code. It's not just colocation at this point. We actually have like better spots to put things in more discreet places to locate stuff. And in case you're thinking, yeah, but I don't have any components I only use once. I went back and counted some apps
20:00
that we've run through the conversion script for module unification, and it looks like it's almost half in both of them that were single use components or helpers. And the module migrator tool that we use automatically remaps all those things to be these local lookups if they're only used in one spot. And so we're able to see that like this is actually a thing that real world apps will use because we can see it in existing apps today.
20:23
So that's pretty great. Let's take a look at one other form of isolation that module unification gives us, which is isolation for add-ons. So on the left here, we have a classic application template. When I'm talking about a classic app, I'm talking about an app with an app directory. It does not have a source directory, it just has an app directory.
20:41
And on the right, we have a classic add-on, which means it has an add-on directory and an app directory. And a classic add-on looks pretty ridiculous. It has three different gadget list files to like create one component that it's exposing as public API, which is pretty ludicrous.
21:01
And the gadget show gets the same treatment. But you all know how this works. The app directory is basically merged with your application. So if your application, for example, had a thing called gadget list, then the two would be in conflict and one would win over the other. If you had another add-on that also defined a thing called gadget list, all three would be in conflict and one would win.
21:22
And does anyone know which one wins? Maybe Robert knows which one wins, but I don't know which one wins. So it doesn't seem ideal. So what we've created in module unification add-ons, so on the left here, we have a module unification app with a source directory. And on the right, we have a module unification add-on that also has a source directory, is the idea of namespaces for add-ons.
21:42
So on the left, we use the add-on name, gadget-tools. And then colon colon denotes that now I want to talk about a component or a helper that's inside of that add-on namespace. And I basically reach into the source directory that exists for that add-on. So on the right-hand side, you can see that the add-on itself basically just looks like an application.
22:01
It looks the same as when you're writing an application. And I think that's a lot more approachable for developers as they write their first components and should be their first add-ons and should be pretty nice. There are some nice slang benefits that we kind of get from this as well. So it seems like having to write all those dashes is a bummer because we already have the colon colon,
22:21
which is a very specific hint that tells you that this thing is invocable and is not going to be a property path or anything else. So we can drop the dash requirement and we can just name things with single words as long as they're going to always be consumed with that colon colon namespace style. And there's an additional feature called main.
22:40
So if you just invoke something like gadget tools, first modular unification will look to say, do I have a local lookup? And say you don't have a local lookup, it'll look to say, okay, check the components directly, the top level. Do I have anything in the top level? And say you don't have anything in the top level. It'll actually then look to say, do I have an add-on? Do I have a namespace with that name?
23:01
And if I do, does it have a main? And if it does, use that. And what this should enable if you also closed over other APIs, you can imagine that you'd have something like Ember Power Select, where you'd be able to say Ember Power Select as, and then it would yield out its own API as contextual components or as named blocks or some of the other APIs that we have floating around
23:21
for how to deal with those abstractions and templates. So not only do we have improved isolation for apps, but we've got some isolation for add-ons as well, and this seems like a good win. You might be wondering, what does a migration strategy look like? How do we actually, because I talked about these things all upgrading at different paces, where we're gonna have this wild west for a while,
23:40
where some add-ons are upgraded and some apps are upgraded, and how do they all mesh and get along? On the left, this is a classic app, so it has an app folder. On the right, it's a module unification add-on, so it has a source folder. And what we basically do is take the components directory there, and we re-export it through app for you. So we make this module unification add-on
24:00
act like it's a classic mode add-on if your application is not a module unification application. And that gives us a path where an add-on author could migrate their entire add-on to use the new style, but your application could be a legacy classic app and you still have the ability to invoke all their stuff that add-on author doesn't need to abandon you as they do their upgrade cycle.
24:21
And also the opposite. On the left here, we have a module unification app, so it has a source directory. And on the right, we have a classic add-on, so it has an add-on and an app directory. And the way we deal with this is we have a thing called the fallback resolver, which basically uses the module unification rules to do lookup, and then it says, I didn't find anything, let me run all the old rules as well,
24:41
like the rules that we use for applications today. And that means that it'll find the things that add-ons are currently republishing into the app directory. So we have like a migration strategy that works in both directions. Like I said, we're like really good at this. So there are some challenges around NPM scopes
25:01
with the namespace a little bit. Remember I said you just take the name of the NPM package, and then you do colon colon. That sounds so nice. But in reality, NPM has now added scopes, and scopes are not a thing that, NPM scopes are not a thing that Ember seems to be super well-aligned with yet, and we want it to be well-aligned with them,
25:21
because we think that NPM scopes will be popular. If any of you have not used them before, an NPM scope would say at, and then the scope name, and then slash, kind of like at Ember slash. And you can imagine having a template where you have angle bracket at Ember power select, slash, select, colon colon, select,
25:41
close angle is like mind-blowing. So we would like to come up with a, know that we have a pretty good solution for that before we totally tie up this sub RFC that is currently floating around. Okay, so let's go back to 2018 and wrap this up and see what things actually look like today. So Ember's new file system layout.
26:01
What can we do today in 2018? We can generate new applications, we can generate new add-ons, both using module unification, and we can even take an existing classic application and run a script on it that migrates it into the new world. To create a new style application, you need to be running Ember CLI Canary.
26:22
So feature flags in Ember CLI are a little bit different than in Ember. In Ember, you go into that config environments file and you can opt into a feature flag and say I want to turn this on, as long as you have Ember Canary installed. Feature flags in Ember data are such that they're just all enabled all the time if you install the Canary version of Ember CLI.
26:41
So our module unification work is behind a feature flag, so in order to use it, you must install Canary of Ember CLI, and that's the only possible way to get it. So you need to make sure that NPM installed globally, the master, and then you can use this module unification environment variable, call Ember new my app, and get it running. And if we take a quick look at what that looks like, I think it basically looks like this.
27:02
Is this playing? Oh, so it is. Yeah. So we just generated a new app and you can see that it's got a template, that's for our route here, and it's calling welcome page. So remember that fallback resolver? That's the fallback resolver. Welcome page hasn't been updated here. It's using the classic mode welcome page. So I went ahead and created a new component
27:21
that I want to use for local lookup. I want to take this title and I say howdy a lot, so I don't want to have to type howdy over and over again. I'm going to make a component that's going to have this little bit of UI behind southern welcome as a component name. So we've got some templates, and I can go ahead and move my content for that tag into the templates,
27:41
and I can invoke that in the top level. And it's going to find this because it's, in this case, not local lookup, it's just in the components directory. So I just made a top level component. But say later on we go and we add a little bit more content to southern welcome and our southern welcome is getting longer, but no, we really want that title to have its own little bit of UI,
28:02
then I can go ahead and make another component. In this case, because I know I'm only going to use this title in this one place, I'm going to make it a local lookup component. So I'm already in the components collection, so I just need to use slash and then the name of the thing. So in this case, welcome title as the name of the component. And now I can go back and I can go into
28:20
my southern welcome component template, and I can invoke welcome title, and copy that snippet and throw it over into the template and load up. So module unification working in like real apps that you can go ahead and try and start experimenting with this stuff. The other thing you can do is generate, yeah.
28:46
The other thing you can do is generate an add-on. This is something that Miguel Comba actually picked up and like shoved across the finish line this week. So thank you. And yeah, it works the same way. You can take your add-on, it creates a source directory, you can install it into a module unification app
29:01
and play with those namespaces if you want to toy around with that stuff and see what it looks like. Another thing that I think many of us, of course Ember, we have existing apps and we want to make sure that they can get upgraded. So there's an Ember module migrator and the steps here are actually pretty short. The trickiest bit is definitely calling Ember in it because just like any upgrade, you have to go through that diff process
29:21
where there's a couple things that are going on. There's a quest issue that I'm going to link to at the end of this and I can tweet out a link to that specifically says what things to look for when you do that init process in case you're afraid that you might miss one of them during the transition. So this is also very doable for you to do this migration. I won't say that any of this will work
29:41
and you should ship it to prod. That's definitely not the goal, right? Our goal here is that we're in that like find all the bugs and actually address them behind the feature flag and get this shipped because we think we have the correct approach. If you did want to see what a real app looks like and both running and to look at the source code, the simplest thing to do is to go here.
30:00
Scroll to the bottom. There's a link to GitHub. That app is in modular unification. Very quick way for you to get to actually see some stuff. So I encourage you to do that. And so getting to go here. We've had a modular unification strike team since November that has gotten like basically gotten us really focused and back on track. We've been meeting every week.
30:21
So thank you to Gavin and Chris and Isaac and Preston and Robert and Dan and Ilia and Miguel because without them we would not have like all this stuff kind of tied together and we would not have finished the exploration and be at this like new implementation step. So our quest begins. We have a new final cut issue and the exploration phase of this work is really done
30:40
and we're in like the bug fix phase. Like this is like shovel ready stuff if you want to get into making Ember contributions and like learn a little bit of the depth of the system. And I think that's it today. Thank you. Thank you.