We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Building Custom Apps with Ember CLI

00:00

Formal Metadata

Title
Building Custom Apps with Ember CLI
Title of Series
Number of Parts
22
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
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Not long ago, the JavaScript world lacked a good Rails equivalent. Ember CLI is quickly filling this void, and consistently improving thanks to its extensibility. The tool can be easily tailored to build for custom environments by creating new add-ons and leveraging existing ones. This presentation will highlight how to extend Ember CLI through add-ons, explaining example use-cases, how to create one, and the hooks available for developers to build into.
Absolute valueMobile appBuildingCommon Language InfrastructureTwitterIntegrated development environmentOvalWide area networkQuantum stateAsynchronous Transfer ModeCross-site scriptingFluxDisk read-and-write headComponent-based software engineeringInterface (computing)Function (mathematics)Core dumpInstallation artTime zoneCodeRule of inferenceData structurePhysical systemEvent horizonCartesian coordinate systemComputer fileWeb 2.0DivisorFunctional (mathematics)Single-precision floating-point formatSubject indexingElectric generatorConnectivity (graph theory)SynchronizationCore dumpCategory of beingSoftware developerPattern languageMultiplication signCodeOvalStandard deviationOcean currentProcess (computing)Order (biology)Point (geometry)Slide ruleDirectory serviceCASE <Informatik>LogicLink (knot theory)BitData structureControl flowRule of inferenceInstallation artRadical (chemistry)Atomic numberDefault (computer science)Context awarenessProjective planeTime zoneMereologyBookmark (World Wide Web)Electronic mailing listRevision controlComputer fontDifferent (Kate Ryan album)Selectivity (electronic)Network topologyCommon Language InfrastructureBuildingIntegrated development environmentTwitterMusical ensembleWeb applicationQuicksortSign (mathematics)Interface (computing)Inheritance (object-oriented programming)Real numberChainSelf-organizationShared memoryGoodness of fitMobile appText editorConfiguration spaceJSONXMLComputer animation
Common Language InfrastructureBuildingMobile appChi-squared distributionRevision controlBeta functionEvent horizonPhysical systemComponent-based software engineeringInstallation artPrice indexDirectory serviceNetwork topologyProcess (computing)Distribution (mathematics)Right angleSampling (statistics)BitMultiplication signComputer fileCartesian coordinate systemMobile appPoint (geometry)Category of beingTemplate (C++)Arithmetic progressionConnectivity (graph theory)LogicDependent and independent variablesCircleMereologyTotal S.A.Power (physics)Functional (mathematics)Interface (computing)Software repositoryDescriptive statisticsNumberProjective planeDifferent (Kate Ryan album)Subject indexingSoftware developerRevision controlChemical equationTask (computing)AreaSurgeryEvent horizonArithmetic meanVariable (mathematics)WordType theoryMachine codePattern languageInstallation artCorrespondence (mathematics)HookingData structureMiniDiscSynchronizationKeyboard shortcutAttribute grammarBuildingComputer animation
Mobile appBuildingCommon Language InfrastructureMaizeoutputBulletin board systemMeta elementComponent-based software engineeringInstallation artTime zoneComputer fileLogicEuclidean vectorSet (mathematics)InformationConnectivity (graph theory)Multiplication signTime zoneLogicCartesian coordinate systemComputer filePower (physics)Link (knot theory)Menu (computing)Template (C++)Computer animation
Common Language InfrastructureBuildingMobile appEuclidean vectorComponent-based software engineeringTemplate (C++)Control flowRevision controlBeta functionEvent horizonPhysical systemCartesian coordinate systemModule (mathematics)Digital filterSoftware testingComputer configurationGamma functionLink (knot theory)Moment (mathematics)Finite element methodRhombusVideoconferencingService (economics)Coma BerenicesConnectivity (graph theory)Computer configurationValidity (statistics)Integrated development environmentProduct (business)Software developerComputer fileFunctional (mathematics)Hash functionFlagDefault (computer science)Mobile appBitWebsiteCartesian coordinate systemPoint (geometry)Local ringOnline helpCore dumpCommon Language InfrastructureCategory of beingSubject indexingData structureInformationCodeMessage passingComputer clusterRadical (chemistry)Time zoneKeyboard shortcutAliasingCASE <Informatik>Goodness of fitType theoryElectronic mailing listMultiplication signLibrary (computing)Object (grammar)HookingDifferent (Kate Ryan album)Key (cryptography)Game controllerDirectory serviceSynchronizationTask (computing)WordRight angleFood energyPattern languageProjective planeLogicDescriptive statisticsComputer animation
Transcript: English(auto-generated)
country of New Jersey, and I've been having a super great time here so far. Hope everyone else is as well, and I definitely hope I get to meet some more of you before the end of the conference. In the case that I don't, you can always find me on Twitter or GitHub at BritneyStorros, and I'll also be tweeting out a link to my slides
as soon as I'm done up here. So I work on the apps engineering team at Mozilla, and one thing that we've been working on a lot is creating Firefox OS applications with Ember CLI. And I know we've all heard a little bit about Ember CLI so far during the course of this conference, which is, Ember CLI is everyone's favorite
command line tool for creating Ember applications really quickly and keeping them super organized. Before Ember CLI came along, there was a huge void in the tool set for JavaScript developers. There were things like Rails for Ruby apps,
and we were just really missing this core piece of our tool chain when we were developing our JavaScript applications. So a couple months back, my team at Mozilla was actually trying to fill this void by creating our own command line tool. And it was cute, it was called Rec Room, and it definitely catered towards Firefox OS applications.
You could scaffold any kind of applications with it, but we really wanted to focus and cater towards Firefox OS developers as well. And as we were building this, I would come across some features that I wanted to implement, and I would run into a problem where I would struggle through creating some sort of feature,
and I would find myself creeping on the Ember CLI code base to see how they solved it. And when you find yourself doing that, when you catch yourself doing that often enough, it might be a sign that you're building a tool that already exists. And maybe you should stop.
So we did, and we decided to leverage Ember CLI instead. But the problem now was that Ember CLI didn't care about Firefox OS. We had this custom environment that we wanted to build for, that we wanted other developers to be able to build for. And Ember CLI didn't know anything about it.
So we had to make Ember CLI care about our environment that we wanted to build for. And what exactly were our requirements? What were our needs? Firefox OS applications are actually just built using current standard web technologies. I actually couldn't have asked for a better person
to speak after because Brian did a great job showing everybody how far the web has come and how great it is and how powerful you can do, how many powerful things you can do with it now. So Firefox OS applications are built completely with web technologies, which makes our requirements just a handful of modifications.
The first one is that we need a manifest file. This is the same concept as a packaged JSON file. They are gonna share a lot of the same properties and values. You're probably very familiar with this kind of concept. So we need Ember CLI to generate and validate this file for us.
We also need some kind of UI components that kind of mimic the Firefox OS interface. We want our web apps to look and feel like they belong in Firefox OS. And we wanted a way to publish to the Firefox marketplace. So those were all of the requirements that we had. And each of these examples is a great use case
for creating an Ember CLI add-on. And Ember CLI add-ons are the way that you extend the core functionality of Ember CLI. They're basically just NPM packages, so they follow all the standard NPM conventions that you're already familiar with. They'll have a packaged JSON file
that will point to an index file as its entry point. So that's where you'll be able to add all of your custom logic and really modify the way that Ember CLI works for you. And they're super easy to create and install. In order to create one, you can just run Ember add-on,
name of your add-on, and then to install one within an existing Ember CLI project, you can run Ember install add-on, and then the name of the add-on that you want to install. Okay? So the first requirement that we had, we wanted to create, sorry, one second,
I'm gonna back up, and we're actually gonna use an application to demo a couple things with this. So I have an application, an Ember CLI application running here just on the desktop. It's super simple. It just shows you your local time, and then you also have the ability
to select different time zones to display and compare against the local time. So you'll always know what time it is in any given country. I don't have New Jersey in there yet, but I will put that up at the top of the list as soon as I'm done here, okay?
So we're gonna kind of walk through creating an add-on. What would an add-on look like that turns this application into a Firefox OS application? And if we think about our first requirement that we had, we wanted to create a manifest file.
So we need Ember CLI to generate this file for us, and we also mentioned that it's gonna share some common values with the package.json file. So not only do we wanna create this file, we want to keep it in sync with our package.json so that we don't have to have our developers updating the same values in two different places, right?
So we want Ember CLI to do that. We're gonna create blueprints to do this. Blueprints are basically just rules for generating common code and file structures. Ember CLI has a lot of these built in by default, and you can also add your own with a simple command, ember generate blueprint, and the name of your blueprint.
So in the context of an add-on, when we create a blueprint, there's a concept of a default blueprint for add-ons. And what this is gonna do, if we name our blueprint the same as our add-on, it's gonna tell Ember CLI to install whatever files we specify
as soon as the user installs our add-on. So if we go to the terminal really quick, I stubbed out a practice add-on that has some of this stuff implemented already. And let's say we ran our ember generate blueprint command.
This is gonna generate some files and folders for us. See if you guys can see this. So if we run that blueprint command, we have this folder here called blueprints, and underneath it we have a blueprint called ember-cli-fx-os, and that's also the name of our add-on.
Within here we have an index file where we'll be able to add some custom logic to the blueprint and modify the way that it works. And then we also have this files directory. And what this files directory does is within it, we want to kind of mimic the directory
of the consuming application. So if we want to create a manifest file in the public directory of the consuming application, we're gonna create a manifest file in a public directory in this files directory. If we wanted to create a file in the config folder, we would create a config folder here,
and we would put the manifest file in there. So what ember-cli is gonna do when it installs this blueprint is it's gonna kind of merge these trees, the files from your consuming application, with whatever you specify in your blueprint. So here we have our manifest file stubbed out
with some of the default values, some of the required mandatory properties, and then you'll also notice some of these values are prefixed with at signs. And what we're gonna do with those is replace them with package JSON values so that our developers don't even have to touch those,
they don't have to think about them at all. So we have our blueprint set up in our add-on, and we have our application running, our ember-cli application running. So I've already installed the add-on in this application that I'm gonna be working in,
but for the sake of demoing how this manifest gets generated, we could run ember generate, ember-cli fxos, and we should be able to see there that it created public manifest.webapp.
Is everyone able to read this code? Is that, yes? Okay, good. So let's just open this in our text editor real quick, and we can see in our directory structure, we have public, and then there's our manifest folder. There's our manifest file, so it got copied over into our public directory
just as we expected. So now how do we implement the part where we want to replace these variables with package JSON values? If we were to run ember-build right now, this manifest file would get copied into our dist directory as is, and obviously these variables don't mean much. Version number is not a version number,
and app name is not an app name. So let's take a look at the logic for implementing that. Okay, as I mentioned, in your add-ons, you're gonna have your package JSON file
point to an index file, that's your entry point. This is where you have all your custom logic for your add-on and how you're gonna modify ember-cli's behavior. And from this index file, ember-cli provides us with some basic hooks that we can play into so that we can modify things at certain points
in the build process, or we can add different properties and values to our application. So one hook that's available to us is called post-process-tree. And it's a little bit obscure, or it sounds a little bit obscure, but what happens here is this hook
is gonna run every time you run ember-build. It runs towards the end of the build process when you have access to the trees that you can modify right before they go into the distribution directory. So we're gonna say whenever we run ember-build, we wanna take our manifest from the public directory
and also grab the values from our package JSON, which are available within this method at this project package, and we're gonna replace them. So I've already required in a function
called sync manifest. We're not gonna go over the logic for that, but the logic in that function is what is gonna do the replacement for us. I just wanted to show you guys the hook and how this winds up affecting the way that ember runs its build command.
So if we go back to our application and we run ember-build, we should see in our disk directory a manifest file,
and now we see that the version number was updated, the name of our application was updated, and the description was updated. All of these values were pulled from our package JSON at build time so that the developers never have to touch this manifest file. They never have to know that it even exists.
Okay, so the next requirement that we had was UI components, and we want developers to be able to create applications that look and feel like they belong in Firefox OS,
like they're native applications. We want them to mimic that. The interface layer of Firefox OS is called GAIA, and there's a repo with a bunch of different GAIA components. They have tabs and switches and menus galore, but it's very much a work in progress, so this is gonna be a little bit of a contrived example.
But say we wanted to create a tabs component, which would be available as a power package, GAIA components slash GAIA tabs. And creating a component off of this is a two-step process. You have two main responsibilities when you're creating a component.
The first is to include your dependencies and actually create your add-on. So we want to include this power package for our GAIA tabs, and then we also want to write any kind of setup logic or teardown logic for our add-on. The second responsibility is making sure that both of these things, the dependencies
and your add-on, are available to the consuming application, and this is the part that kind of muddies down creating components. It's not difficult, but there's a lot of different steps, and it's easy to miss something, or it's easy to forget to do a particular one of them. So we're gonna walk through an example really quickly.
Don't worry if it's a little tough to follow. I'll circle back and review all the steps that we went over before I move on.
Okay, so we're in our add-on right now, and say we already did our Bower install of the GAIA tabs component. If we look in our Bower components, I have this folder structure right here, GAIA tabs, so we have that available in our add-on,
because our component is gonna depend on this Bower package, but it's not enough that our add-on has this Bower package. We need to tell the consuming application that it's gonna need this Bower package too. So when we were creating our Blueprint file,
I mentioned that there's an index file there where we could add some custom logic, and I also mentioned that this Blueprint gets generated automatically after you install your add-on to an application. So this would be a great time to tell your application,
hey, you're gonna need this Bower package too. You might as well install it now. So just like in our index file of our add-on, we also have a couple different hooks for Blueprints, one of which is after install. And what we can do here in this after install hook
is just return this built-in method, this add-bower-package-to-app GAIA tabs, and that will tell our consuming application you need to do a Bower install of this package, of these GAIA tabs. And our application will do that.
Now that makes the Bower package available for our consuming application, but we still have the JavaScript file and the CSS file from this Bower package that we need to include into our application. We need to not just make the Bower package available for use, we need to actually use it.
So in the index.js file of our add-on, we have another hook here that was sitting here earlier and I didn't mention anything about it, but this included hook is another one of the hooks that runs during the Ember build process, and this is a great place to import
any of the dependencies that you need for your consuming application. So one of the things we can do here is run an app import, and then we're gonna grab the directories, the paths of our JavaScript file,
and the CSS file that we need. That has never happened to me before. That's funny. Okay, so we have our dependencies.
We took care of creating, installing Bower, the Bower package in our add-on, and we also gave our consuming application access to this Bower package. Now we still have to actually create our add-on. So what we're gonna do here is we want an add-on directory with a corresponding components directory underneath it,
and we're gonna have a file named after our component that we're creating. So we're creating gaia-tabs, and this is where you can, this is the meat of your component. This is where you can define your tag name or set up attribute bindings and do any setup or teardown logic. And now we have a component in our add-on,
but just like we did with our dependencies, we have to tell our consuming application about it. We have to tell the application that wants to use this that it's available for the application to use. So the way we wanna do that is by creating an app directory.
And under the app directory, we're gonna have another components directory and another file called gaia-tabs. But literally all this file is gonna do is import our component that we just created and export it back out so that our consuming application knows that it exists.
And then finally, we need a template for our component. So again, under the app directory, we have a templates folder with components underneath and a handlebars file that simply defines the template for our gaia-tabs.
So in our application that's using this add-on, that's using this component, if we look at our application template file,
we see I have this already implemented in here. So I have gaia-tabs, and then I'm setting the menu tabs that we need to populate our tabs component. And that's what's controlling the clock and the timezones links back and forth.
Okay, so that was a decent amount of information. And like I said, I promised I would review what we just did, because it's a little confusing. There are a lot of files involved. What do we do with dependencies?
We Bower installed our gaia-tabs dependency into our add-on. We told our consuming application that it needs that Bower dependency as well. And then we actually included the dependency files so that they can get processed at build time.
The component logic, we created our component, we did our setup logic, we did our tear-down logic, we gave it a name, we created this component in our add-on. We exported the component to the consuming application
so that the application can actually use it. And we defined a component template. So there's six steps, basically, in creating a component. This is one of those things that hopefully in the future, it will get a little bit easier to do. Even if it's still a little hard to follow right now,
I promise the documentation on Ember CLI's website goes through every single one of these steps, so you just have to not miss one of them. And there's a lot of good example add-ons out there that you can use to follow and you can learn from to create components.
So we have one more, or two more things on our to-do list, validation and publishing. We wanted to validate that manifest file, and we also wanna be able to publish to the marketplace. And unlike our syncing of our manifest file with our package.json file, we wanna have more control over when these things are run.
We don't wanna be publishing to the marketplace every time we build our application. So this makes them really good candidates for being commands, for creating commands. So just like you might run ember new or ember serve, we wanna be able to run something like ember fxos validate,
or fxos publish. So let's look at what a command looks like in Ember. Ember CLI, sorry.
So I have a lib directory with a commands directory underneath, and an index file here. And this index file is just exporting an object where the keys are the names of your commands, and the values are the actual commands.
And if we look at this validate file, our validate command, we can kinda see the basic structure of what a command should look like. It should have a name, which is gonna be what you type in the terminal to run the command. It can have aliases in case it's super long and you want some shortcuts. It should have a description, and we should be able to tell
that it works inside of the project, inside of an Ember CLI project. And it also has a run method, and this is where all the magic is gonna happen. This is where we're gonna actually write our validation logic. I've already imported a validate manifest file function so that we don't have to look at the code for that because it's not relevant exactly to you guys.
So we're just gonna return this. We're gonna validate our manifest file, and that's what's gonna happen when we run our validate command. But Ember CLI doesn't know that we put these commands in here. It doesn't know about these yet, so we need to tell it that these commands exist and that the application can use them. If we go back to our index.js file,
again, this is another one where we're gonna add another hook that Ember CLI has built in for us to utilize. This one is a lot simpler to understand. It's just included commands, and all I'm gonna do there is return my object of commands. So I already required that in at the top of this file,
and we're just gonna return that object of the validate command and the publish command. And now if we go to our terminal and we try to run one of these from our application, let's do validate,
we see that it validated our manifest for us. The validation passed. We have a warning message, but we don't care about that right now. And we know that our command was there, and it works. It's doing what it's supposed to do. Another way we could have told if this command was available to us
is by running ember help. And besides just running the core commands and information about Ember CLI, what it's also gonna do is list out information about the available commands from your add-ons. So that's a super helpful thing when you have add-ons that are incorporating commands.
Your ember help command will also list those. And we see that we have a validate and a publish command here. The publish command I'm not gonna go too much into. We're actually still editing this, but I have it set up locally. One thing I just wanna point out
is another property of commands is that you can specify available options. So if you want to throw in a flag when you're running a command, you can throw in one of these options. You can define a name, type, and set default values for these.
And these options that get passed in are gonna be available to you through this options hash in the run method. So when we wanna run publish, say we wanna publish to the developer marketplace, the development marketplace versus the production Firefox marketplace, we could pass in an environment option
that says development. If we're ready to publish to production, we could set environment to production, and it would publish to the production marketplace. So I have my development marketplace opened up here. I'm logged in. And if I click on my submissions, I see that I don't have any applications right now.
But if I run my publish command from my application, I should get an app ID back.
Yep, so we have app successfully created, and we have an app ID to reference. And now if we look over at our marketplace submissions and we refresh, we should see our application time zone clock right there, okay?
So those were just a couple of different ways that you could use add-ons to extend the functionality of Ember CLI. There's a lot more use cases, and there's a lot more examples out there.
I encourage you to look at the documentation, because there's a lot of information that we did not cover here right now. And like I said, there's a lot of good add-ons out there that you can learn from, that you can follow by example. You can really get Ember CLI to do almost anything that you want. It's kind of a pushover like that. But it's a really great tool,
so definitely take a look at it if you haven't. Start working with it if you haven't. Also, if you're interested in learning more about creating Firefox OS applications, you can take a look at this add-on that we walked through on GitHub. You can take a look at the MDN App Center, or you can find me and my team on IRC in the apps channel of nuzilla.org, okay?
I don't believe I left time for questions, but if you have any, feel free to tweet at me or find me before the end of the day, and I would be happy to talk more about this with you. Thank you.