|
| 1 | +# Addons |
| 2 | + |
| 3 | +The modern web developer has an incredible selection of open source code that they can use through the npm ecosystem, plus great tools for writing their own modules. Ember developers are free to use regular npm packages in their apps, but there are also thousands of packages that are made specifically for the Ember ecosystem. We call such packages "addons." |
| 4 | + |
| 5 | +Addons are often JavaScript code, reusable UI components, compiling tools, deployment pipelines, templates, stylesheets, and more. Think of addons as node.js libraries with superpowers. In addition to the usual functionality of an npm package, addons can also help with generating new files, preprocessing, file fingerprinting, and more. |
| 6 | + |
| 7 | +In this guide, we'll cover: |
| 8 | +- Finding and using community addons |
| 9 | +- Addon file structure |
| 10 | +- Writing your addon within an app |
| 11 | +- Writing an addon that can be shared |
| 12 | +- Turning a regular npm package into an addon |
| 13 | +- Testing addons |
| 14 | +- Managing assets |
| 15 | +- and more |
| 16 | + |
| 17 | +## Finding and using community addons |
| 18 | + |
| 19 | +[Ember Observer](https://www.emberobserver.com/) is the definitive way to explore community addons. Although addons can be found by [searching the npm repository directly](https://www.npmjs.com/search?q=ember), Ember Observer has ranked lists of the most popular addons and ratings to help developers choose between them. Most are made to drop right into your app with zero configuration. Many addons are backwards-compatible to earlier versions of Ember too! |
| 20 | + |
| 21 | +To install an addon, use: |
| 22 | + |
| 23 | +```bash |
| 24 | +ember install <addon-name> |
| 25 | +``` |
| 26 | + |
| 27 | +To be safe, it's a good idea to restart the local server after installing new dependencies, and especially before trying to debug an addon that isn't working. |
| 28 | + |
| 29 | +The `ember install` command is similar to the `npm install` you might already be familiar with. It creates an entry in the app's `package.json` and downloads the addon and its dependencies into a `node_modules` directory. However, `ember install` does even more than `npm`. Some addons create new files or make modifications to your app when they are installed via `ember install`. |
| 30 | + |
| 31 | +### Choosing an addon |
| 32 | + |
| 33 | +The [top 100 list](https://www.emberobserver.com/lists/top-addons) is an important first stop for new developers. Many Ember users have a personal set list of addons that they include in all their apps, and this is the best way to find out what those addons might be. Some addons are totally unique to Ember, while others exist to make it easier to use features of regular npm packages within an app. |
| 34 | + |
| 35 | +For example, these community-authored addons bring in familiar functionality from regular npm packages: |
| 36 | + |
| 37 | +- Stylesheet tooling like [ember-cli-sass](https://www.emberobserver.com/addons/ember-cli-sass), which provides [SASS](https://sass-lang.com/) as an alternative to plain CSS |
| 38 | +- JavaScript utilities like [ember-moment](https://www.emberobserver.com/addons/ember-moment), which offers some Ember conveniences to the base [moment library](https://www.npmjs.com/package/moment) |
| 39 | +- Full UI frameworks and design kits like [ember-bootstrap](https://www.emberobserver.com/addons/ember-bootstrap), [semantic-ui-ember](https://www.emberobserver.com/addons/semantic-ui-ember), and [ember-paper](https://www.emberobserver.com/addons/ember-paper). These offer easier, more reliable, more performant functionality than just using the npm packages directly. |
| 40 | + |
| 41 | +Here are just a few examples of popular community-maintained addons unique to Ember, in no particular order: |
| 42 | + |
| 43 | +- A wealth of UI component libraries, like [ember-power-select]() and [ember-basic-dropdown](https://www.emberobserver.com/addons/ember-basic-dropdown) |
| 44 | +- Tools to automate deployment, like [ember-cli-deploy](https://www.emberobserver.com/categories/deployment) and its own ecosystem of plugins |
| 45 | +- Testing tools like [ember-test-selectors](https://www.emberobserver.com/addons/ember-test-selectors), to make DOM assertions in testing easier and clearer, and [ember-a11y-testing](https://www.emberobserver.com/addons/ember-a11y-testing) to check for accessibility |
| 46 | +- Authentication libraries and plugins, like [torii](https://www.emberobserver.com/addons/torii) and [ember-simple-auth](https://www.emberobserver.com/addons/ember-simple-auth), and [ember-oauth2](https://www.emberobserver.com/addons/ember-oauth2) |
| 47 | +- Async and state management tools like [ember-concurrency](https://www.emberobserver.com/addons/ember-concurrency) and [ember-lifeline](https://www.emberobserver.com/addons/ember-lifeline). Don't let a user's impatient clicks kick off 100 API requests. |
| 48 | +- [liquid-fire](https://www.emberobserver.com/addons/liquid-fire), for animating things like route transitions to provide a smooth, native-app-like experience. |
| 49 | +- and so many more! |
| 50 | + |
| 51 | +Open Source projects like these addons rely on community members helping out. Some addons are sponsored by companies, but many are maintained on 100% volunteer time. If something doesn't work the way you expect, could be better documented, has a bug, or could be added as a new feature, please speak up and pitch in! |
| 52 | + |
| 53 | +## Writing an addon |
| 54 | + |
| 55 | +Writing an addon is a great way to organize code, share it with others, or get the foundational knowledge to contribute to Open Source addons. By separating features into an addon instead of leaving it as an in-app component, more developers can work in parallel and breaking changes can be managed independently. Maintainability goes up, and testing becomes easier. |
| 56 | + |
| 57 | +Since the Ember community has so many addons, one of the best ways to learn more advanced addon development is to study existing addons. If we get stuck or need to see some examples in action, [Ember Observer's code search](https://www.emberobserver.com/code-search) can be very helpful. |
| 58 | + |
| 59 | +Although an addon looks and feels a lot like an Ember app, it is important to work in small steps and validate that each piece is working before writing more code. Developers who are very comfortable with Ember apps might otherwise make a lot of changes and walk into some common pitfalls that can be hard to debug in unison. |
| 60 | + |
| 61 | +### Generating the addon |
| 62 | + |
| 63 | +Use the ember-cli to create the file structure for the addon. Run this command in a fresh directory, not inside an existing Ember app: |
| 64 | + |
| 65 | +```bash |
| 66 | +ember addon <addon-name> [options] |
| 67 | +``` |
| 68 | + |
| 69 | +The result is the creation of a directory called `<addon-name>`, which has many files and looks a bit like an Ember app. We won't need to use all the files to make a useful addon. By convention, _most_ Ember addons start with `ember` in the name, like `ember-basic-dropdown`. This will help other developers find our addon. |
| 70 | + |
| 71 | +<!-- Should we cover in-repo addons at all??? --> |
| 72 | +<!-- |
| 73 | +If the addon is just meant to be used in a single project, an "in-repo" addon could be created instead. The benefit is that it is lightweight, but there are some major limitations; an in-repo addon can't be shared between apps, versioned independently, or published to npm. From within an existing Ember app, use: |
| 74 | +
|
| 75 | +```bash |
| 76 | +ember generate in-repo-addon <addon-name> [options] |
| 77 | +``` |
| 78 | +
|
| 79 | +This generates a folder called `lib/<addon-name>` that contains its own `package.json` and an `index.js` file. |
| 80 | +--> |
| 81 | + |
| 82 | +### Addon file structure |
| 83 | + |
| 84 | +In some ways, an addon is like a mini Ember app. It has a very similar file structure, uses a lot of the same API methods, and can do most things that components are able to do. |
| 85 | + |
| 86 | +<!-- add a file tree table and explanations --> |
| 87 | +<!-- include difference between app and addon namespace folders --> |
| 88 | + |
| 89 | +### Creating an addon component template |
| 90 | + |
| 91 | +To create a component template that can be shared between apps, the process is a lot like creating a normal app component: |
| 92 | + |
| 93 | +```bash |
| 94 | +ember generate component <addon-name> |
| 95 | +``` |
| 96 | + |
| 97 | +However, in the context of an addon, this creates more files than we would see in an app: |
| 98 | + |
| 99 | +``` |
| 100 | + create addon/components/<addon-name>.js |
| 101 | + create addon/templates/components/<addon-name>.hbs |
| 102 | + create tests/integration/components/<addon-name>-test.js |
| 103 | + create app/components/<addon-name>.js |
| 104 | +
|
| 105 | +``` |
| 106 | + |
| 107 | +Some files go in the `app` directory, while others go into the `addon` directory. We'll start by looking at the addon directory. At this stage, whatever we put in the `<addon-name>.hbs` file is what could be used immediately in an app. |
| 108 | + |
| 109 | +Let's say that our addon should wrap some content in a button tag. The addon template looks like this: |
| 110 | + |
| 111 | +```hbs |
| 112 | +<!-- addon/templates/components/<addon-name>.hbs --> |
| 113 | +
|
| 114 | +<button>{{buttonLabel}}</button> |
| 115 | +``` |
| 116 | + |
| 117 | +Our goal is to be able to pass the `buttonName` value to the addon, just like we'd pass it to a normal component within an app: |
| 118 | + |
| 119 | +```hbs |
| 120 | +<!-- This is a handlebars file in the app using the addon --> |
| 121 | +
|
| 122 | +{{addon-name buttonLabel="Register"}} |
| 123 | +``` |
| 124 | + |
| 125 | +### Trying out the addon template in an app |
| 126 | + |
| 127 | +There are several options to see the addon in action. We could use `npm link` or `yarn link` to try it out locally or publish the addon online. We'll use `link` while we are still developing and testing. |
| 128 | + |
| 129 | +1. Since our addon uses a template, we need the template precompiler to be a `dependency` and not a `devDependency`. In the addon's `package.json`, move the entry for `ember-cli-htmlbars` into the `dependencies` listing. If this step is missed, there is a clear error message when we try to start the app that uses our addon. |
| 130 | +2. From within the addon directory, `yarn install` or `npm install` |
| 131 | +3. From within the main addon directory, run the command `yarn link` or `npm link` |
| 132 | +4. In the Ember app that should use the addon, do `yarn link <addon-name>` or `npm link <addon-name>`. |
| 133 | +5. In the Ember app's `package.json`, add an entry for your addon, like `"addon-name": "*"`. The `*` means that it will include all version numbers of our addon. |
| 134 | +6. Run `yarn install` or `npm install` |
| 135 | +7. Add a reference to your addon somewhere in an app template, like `{{addon-name buttonLabel="Register"}}` |
| 136 | +8. Run a local server with `ember serve` |
| 137 | + |
| 138 | +We should now see our addon in action! |
| 139 | + |
| 140 | +**Having problems?** |
| 141 | +Check to make sure that your `package.json` is valid, looking for missing commas or trailing commas. "Template precompiler" errors mean that we forgot Step One. `404 not found` means we forgot to `yarn` or `npm install`. Other errors are likely due to file naming problems. For example, trying to rename an addon or component after it has been created is prone to mistakes. And of course, we need to make sure we saved all the files that we changed along the way. The author of this guide did not make every single mistake in this list while writing it. They learned the hard way not to rename files a long time ago, therefore they made every mistake but that one ;) |
| 142 | + |
| 143 | +### Block form component template |
| 144 | + |
| 145 | +### Adding JavaScript functionality |
| 146 | + |
| 147 | +### Including stylesheets |
| 148 | + |
| 149 | +### Providing multiple components in one addon |
| 150 | + |
| 151 | +## Writing an npm package wrapper |
| 152 | + |
| 153 | +## Documenting addons |
| 154 | + |
| 155 | +## Testing an addon |
| 156 | + |
| 157 | +## Advanced addon configuration |
0 commit comments