# Overview

Editions are the best way to produce and consume the JavaScript packages you care about. With Editions you can produce packages beautifully, and consume packages perfectly.

Editions is [a backwards compatible standard](/#defining-editions) for describing the ways in which your project has been produced to accelerate manual consumption, as well as automatic consumption through [Ecosystem Tooling](/ecosystem).

{% embed url="<https://youtu.be/IAB8_UlcNWI>" %}
Watch the 2016 introductory talk to the Editions ecosystem.
{% endembed %}

## Why use Editions?

JavaScript production and consumption has gotten difficult over the years.

Production use to be as easy as publishing your source code, which worked across all environments, with a few minor tweaks. Consumption was as easy as including the package, and you are done.

However, these days, code may be run anywhere, in all sorts of browsers, desktop environments, and devices, of varying capabilities, not always known by the producer. JavaScript has also evolved, incorporating a lot of modern features that save developers time, but not supported across all possible environments - either requiring abstinence of time saving features, or eliminating environment support, or compilation on either the producer or consumer side - [this is all complex and difficult to manage](/comparisons/alternative-approaches).

Editions comes in to solve this problem, elegantly, and [in a standardised way](/#how-do-i-define-an-edition), that works with current environments and development setups. Producers are able to produce their packages in their ideal configurations, then publish the package with multiple editions for the consumers to consume at their digression. Consumers are made aware of this through [automated README updates](/#documenting-editions), and can [select the exact edition that meets their exact needs](/#manually-require-a-specific-edition) - and by default, [the best edition for the environment can be automatically loaded](/#best-edition-for-the-environment). All the complexity of modern JavaScript publishing is solved, for the consumer and publisher.

If you wish to delve further, refer to the [Alternative Approaches](/comparisons/alternative-approaches) document for a complete understanding of the problem space and why editions is a superior solution in it.

{% content-ref url="/pages/-LRuB-JPgbgU60cxrcxS" %}
[Alternative Approaches](/comparisons/alternative-approaches)
{% endcontent-ref %}

## Defining Editions

An edition is each variation of your code. Usually this comes in the form of your source edition, as well as compiled editions for each environment you wish to support.

### How do I define an Edition?

Practically, editions are specified in descending order of preference in the `editions` field of your `package.json` , with each edition being composed of the following fields:

* a `description` field to describe the edition
* a `directory` field for where the edition is located
* a `entry` field for the default file inside the `directory` to be loaded
* an optional `tags` field for [common keywords](/tags) to describe the edition that tooling can utilise

You can find the full technical specification here:

{% content-ref url="/pages/-LRuBbOorrQgkIBUQWSY" %}
[Specification](/specification)
{% endcontent-ref %}

### Example Editions Definition

For a project that has a source edition written in ESNext using `require('some-package')` syntax, with a compiled edition for the default browsers, as well as a compiled edition for older node versions, then a compatible editions definition for it would look like so:

{% code title="package.json" %}

```javascript
{
  "editions": [
    {
      "description": "esnext source code with require for modules",
      "directory": "source",
      "entry": "index.js",
      "tags": [
        "javascript",
        "esnext",
        "require"
      ],
      "engines": {
        "node": ">=6",
        "browsers": false
      }
    },
    {
      "description": "esnext compiled for browsers with require for modules",
      "directory": "edition-browsers",
      "entry": "index.js",
      "tags": [
        "javascript",
        "require"
      ],
      "engines": {
        "node": false,
        "browsers": "defaults"
      }
    },
    {
      "description": "esnext compiled for node.js >=0.8 with require for modules",
      "directory": "edition-node-0.8",
      "entry": "index.js",
      "tags": [
        "javascript",
        "require"
      ],
      "engines": {
        "node": ">=0.8",
        "browsers": false
      }
    }
  ]
}
```

{% endcode %}

### Automatic Creation of Editions

Tools like [Boundation](https://github.com/bevry/boundation) can automatically create for you the editions definition as well as the editions themselves.

{% embed url="<https://github.com/bevry/boundation>" %}
Automatically create your Editions with Boundation
{% endembed %}

## Consuming Editions

Editions can be consumed in multiple ways, here are the options:

### A Specified Edition

For producers who only want one edition to be used by default, they can specify the default edition to be loaded via the standard `main` property of the `package.json` file:

{% code title="package.json" %}

```javascript
{
  "main": "edition-node-0.8/index.js"
}
```

{% endcode %}

### Best Edition for the Environment

For producers who want consumers to automatically load the best edition for the consumers particular environment, you can make use of the [Editions Autoloader](https://github.com/bevry/editions) package.

1. Inside your project, install the Editions Autoloader package via `npm install --save editions`
2. Create a root `index.js` file that uses the Editions Autoloader to load the best edition from our available compatible editions.

   <pre class="language-javascript" data-title="index.js"><code class="lang-javascript">'use strict'
   /** @type {typeof import("./source/index.js") } */
   module.exports = require('editions').requirePackage(__dirname, require)
   </code></pre>
3. Set the `package.json` property `main` to point to the `index.js` file above, instead of a specfic edition.

   <pre class="language-javascript" data-title="package.json"><code class="lang-javascript">{
     "main": "index.js"
   }
   </code></pre>

#### Custom Entry Points

For binary executables or testing, we then we would want to specify a non-default entry to load for the editions. We can do this by passing the custom entry point as an extra argument to the `requirePackage` function.

&#x20;To specify a `bin.js` custom entry, then we would perform the following.

1. Create a root `bin.js` file that uses the Editions Autoloader to load the best `bin.js` script from our available compatible editions.

   <pre class="language-javascript" data-title="bin.js"><code class="lang-javascript">#!/usr/bin/env node
   'use strict'
   /** @type {typeof import("./source/bin.js") } */
   module.exports = require('editions').requirePackage(__dirname, require, 'bin.js')
   </code></pre>
2. Set the `bin` property in our `package.json` file to point to the root  `bin.js` file we just created.

   <pre class="language-javascript" data-title="package.json"><code class="lang-javascript">{
     "bin": "bin.js"
   }
   </code></pre>

To specify a `test.js` custom entry, then we would perform the following.

1. Create a root `test.js` file that uses the Editions Autoloader to load the best `test.js` script from our available compatible editions.

   <pre class="language-javascript" data-title="bin.js"><code class="lang-javascript">'use strict'
   /** @type {typeof import("./source/test.js") } */
   module.exports = require('editions').requirePackage(__dirname, require, 'test.js')
   </code></pre>
2. Set the `scripts.test` property in our `package.json` file to point to the root  `test.js` file we just created.

   <pre class="language-javascript" data-title="package.json"><code class="lang-javascript">{
     "scripts": {
       "test": "node ./test.js"
     }
   }
   </code></pre>

### Manually Require a Specific Edition

For consumers who [are informed about the particular editions that an editioned package offers](/#displaying-editions), they can opt into a non-standard edition by specifying it manually in their consumption.

```javascript
// using require
require('a-editioned-package/a-custom-edition/')

// using import
import blah from 'a-editioned-package/a-custom-edition/'
```

### Browser Edition

For our [Example Editions Definition from earlier](/#example-editions-definition), we would define the `browser` field in our `package.json` like so:

{% code title="package.json" %}

```javascript
{
  "browser": "edition-browsers/index.js"
}
```

{% endcode %}

This usage of the `browser` field tells most tools like Browserify, WebPack, and Rollup to specifically use the edition that we precompiled for the browsers we target for.

You can find more information about the `browser` field and its equivalents here:

{% content-ref url="/pages/-LRu7dPvaSa17\_4VBCim" %}
[Fields Comparison](/comparisons/comparison)
{% endcontent-ref %}

You can find tooling that already has builtin support for the Editions specification here:

{% content-ref url="/pages/-LRu6NdepnbYZ5Gm2d-o" %}
[Ecosystem](/ecosystem)
{% endcontent-ref %}

## Documenting Editions

If producers wish to inform consumers of the editions they provide, which is not necessary for consumption, but useful to the consumer, then producers can utilise [Projectz](https://github.com/bevry/projectz) to inject the appropriate editions information into your `README.md` file via the HTML comment `<!-- INSTALL -->` .

### Automatic Editions Rendering without the Editions Autoloader

If we partner our [Example Editions Definition from earlier](/#example-editions-definition) with the following `package.json` fields:

{% code title="package.json" %}

```javascript
{
  "main": "editions-node-0.8/index.js"
}
```

{% endcode %}

&#x20;This will have Projectz turn the `<!-- INSTALL -->` comment in our `README.md` file into the following rendered output:

> #### [Editions](https://editions.bevry.me)
>
> * `require('project')` aliases `require('project/edition-node-0.8')`
> * `require('project/source')` is [ESNext](https://babeljs.io/docs/learn-es2015/) source code with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)
> * `require('project/edition-browsers')` is [ESNext](https://babeljs.io/docs/learn-es2015/) compiled for browsers with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)
> * `require('project/edition-node-0.8')` is [ESNext](https://babeljs.io/docs/learn-es2015/) compiled for [Node.js](https://nodejs.org/en/) >=0.8 with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)

### Automatic Editions Documentation with the Editions Autoloader

If we partner our [Example Editions Definition from earlier](/#example-editions-definition) to [make use of the Editions Autoloader](/#best-edition-for-the-environment), then Projectz will turn the `<!-- INSTALL -->` comment in our `README.md` file into the following rendered output:

> #### [Editions](https://github.com/bevry/editions)
>
> * `require('project')` aliases `require('project/index.js')`which uses the [Editions Autoloader](https://github.com/bevry/editions) to automatically select the correct edition for the consumers environment
> * `require('project/source')` is [ESNext](https://babeljs.io/docs/learn-es2015/) source code with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)
> * `require('project/edition-browsers')` is [ESNext](https://babeljs.io/docs/learn-es2015/) compiled for browsers with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)
> * `require('project/edition-node-0.8')` is [ESNext](https://babeljs.io/docs/learn-es2015/) compiled for [Node.js](https://nodejs.org/en/) >=0.8 with [require for modules](https://nodejs.org/dist/latest-v10.x/docs/api/modules.html)


# Ecosystem

Editions ecosystem is already made up of projects of high utility.

## Editions Autoloader for Node.js

You can use the [Editions Autoloader](https://github.com/bevry/editions) to autoload the appropriate edition for your consumers environment. It is currently [achieving](https://npm-stat.com/charts.html?package=editions) 3 million downloads a month, and 800 thousand downloads a week.

{% embed url="<https://github.com/bevry/editions>" %}
The Editions Autoloader for Node.js
{% endembed %}

## Projects using the Editions Autoloader

There are even [more than 100 projects](https://www.npmjs.com/browse/depended/editions) that make use of the Editions Autoloader. Including projects of ESNext, ES5, TypeScript, CoffeeScript, and JSON types.

{% embed url="<https://www.npmjs.com/browse/depended/editions>" %}
Projects using the Editions Autoloader
{% endembed %}

## ESLint Configuration

You can use [`eslint-config-bevry`](https://github.com/bevry/eslint-config-bevry) to automatically adjust your eslint configuration based on your editions.

{% embed url="<https://github.com/bevry/eslint-config-bevry>" %}
Automatic ESLint Configuration for your Editions
{% endembed %}

## Scaffolding

You can use [Boundation](https://github.com/bevry/editions) to automatically create new projects, and update existing projects, to conform with the latest wider ecosystem changes, including automatic generation of editions to meet the target environments that you specify.

{% embed url="<https://github.com/bevry/boundation>" %}
Generate your Editions automatically using Boundation
{% endembed %}

## Documentation

You can use [Projectz](https://github.com/bevry/projectz) to automatically generate and update the installation information in your readme file with what is appropriate based on your editions.

{% embed url="<https://github.com/bevry/projectz>" %}
Document your Editions automatically using Projectz
{% endembed %}


# Specification

You can find the latest Editions Specification over at the Editions Autoloader API Documentation website.

{% embed url="<http://master.editions.bevry.surge.sh/docs/interfaces/edition.html>" %}
View the latest Editions Specification
{% endembed %}

You can find common tags that people use in their `tags` field over at the Tags page.

{% content-ref url="/pages/-LRu87yDsqQrV8tsjl23" %}
[Tags](/tags)
{% endcontent-ref %}


# Tags

A listing of tags that people are using within their editions.

### Languages

* `javascript` - for JavaScript
* `coffeescript` - for [CoffeeScript](http://coffeescript.org)
* `typescript` - for [TypeScript](http://www.typescriptlang.org)

### JavaScript

#### Versions

* `esnext` - for anything newer than the babel 2015 preset
* `es2015` - for the babel 2015 preset
* `es5` - for code that will run in node 0.10 and IE8 (no feature syntaxes)

#### Modules

* `import` - for `import`/`export` module syntax, aka the CommonJS/Node Module System
* `require` - for `require`/`module.exports` module syntax, aka the ES/ES6/JS Module System

#### Features

* `arrows`
* `await`
* `classes`
* `const`
* `defaults`
* `destructuring`
* `forof`
* `generators`
* `getset`
* `let`
* `map`
* `promises`
* `proxies`
* `reflect`
* `rest`
* `set`
* [`shorthand`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions)
* `spread`
* `symbols`
* `template strings`

#### Proposals

* `decorators`

#### Custom

* `jsx`
* `flow type inline` - for [Flow Type](http://flowtype.org) inline syntax, `let greeting:string = 'hello'`
* `flow type comments` - for [Flow Type](http://flowtype.org) comment syntax, `let greeting /*:string*/ = 'hello'`


# FAQ

Frequently asked questions about Editions and their answers.

#### What is the `editions` property inside `package.json`?

It is the property used to define the [Editions](/) that the package provides.

#### Do I need to use the [Editions Autoloader](https://github.com/bevry/editions) to use editions?

No. You do not have to use the auto loader to use editions.

Editions can be considered in the following parts:

1. A standardised `editions` property inside your `package.json` file used for defining the editions a package provides
2. This standardised property can then be utilised by optional things due to its standardisation, such as an auto loader that can automatically include the correct edition for the current runtime, or renderers that render the available editions for the consumers awareness. These latter parts are entirely optional, and should not detract or distract from the promotion of the valuable by itself `editions` property.

#### Are there other ways of doing this without making use of editions?

Yes, but they are all terrible, hence why editions exists.

{% content-ref url="/pages/-LRuB-JPgbgU60cxrcxS" %}
[Alternative Approaches](/comparisons/alternative-approaches)
{% endcontent-ref %}

{% content-ref url="/pages/-LRu7dPvaSa17\_4VBCim" %}
[Fields Comparison](/comparisons/comparison)
{% endcontent-ref %}

### How does the Editions Autoloader work?

Refer to the [Editions Autoloader API Documentation](http://master.editions.bevry.surge.sh/docs/global.html#requirePackage) as well as the [Editions Autoloader Changelog](https://github.com/bevry/editions/blob/master/HISTORY.md) for the most up to date information on its operation.

### How can I debug the auto loading process?

You can set the environment variable `EDITIONS_VERBOSE` to `yes`, this will output to stderr the relevant failure and stack trace for why editions are failing to load.


# Alternative Approaches

Here is a precise comparison between the alternative approaches that have been practised over the years.

## Comparison Table

| Publishing Legacy Code                                                 | Publishing Modern Code                                   | Publishing Compiled Code                                                   | Publishing Editions                            |                                                                                    |
| ---------------------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------- |
| Published source code                                                  | **Yes**                                                  | **Yes**                                                                    | No                                             | **Yes**                                                                            |
| Published compiled code                                                | No                                                       | No                                                                         | **Yes**                                        | **Yes**                                                                            |
| Source and compiled code is published                                  | No                                                       | No                                                                         | Yes, however is difficult and non-standardised | **Yes**                                                                            |
| Producers can make use of modern features (e.g. esnext, babel)         | No                                                       | Yes, however at the cost of environments that don’t support those features | **Yes**                                        | **Yes**                                                                            |
| Consumers can make use of modern features (e.g. es modules, flow type) | No                                                       | Yes, however at the cost of consumers that don’t support those features    | Yes, however is difficult and non-standardised | **Yes**                                                                            |
| Consumption always runs latest compatible code                         | No, legacy code always used, even on modern environments | No, modern code may not be compatible with legacy environments             | Yes, however is difficult and non-standardised | **Yes, loaders can automatically load appropriate edition for target environment** |
| Legacy bloat consumed on modern environments                           | Yes                                                      | **No**                                                                     | No, however is difficult and non-standardised  | **No**                                                                             |
| Modern features could break legacy consumption                         | **No**                                                   | Yes                                                                        | **No**                                         | **No**                                                                             |
| Fixing legacy consumption breaks is easy                               | No, likely requires manual code changes or polyfill      | No, likely requires code rewrite or compilation                            | **Yes, change is a compiler flag**             | **Yes, change is a compiler flag**                                                 |
| Consumers informed about this                                          | Yes, however is difficult and non-standardised           | Yes, however is difficult and non-standardised                             | Yes, however is difficult and non-standardised | **Yes, renderers automatically inform consumers of their options**                 |

###


# Fields Comparison

Before editions, we had to make use of the following package.json fields due to the fragmentation of the ecosystem.

## Comparison Table

| field                               | expectation                                                       | module system      | mainstream consumers              | recommendation                                                       |
| ----------------------------------- | ----------------------------------------------------------------- | ------------------ | --------------------------------- | -------------------------------------------------------------------- |
| `main`                              | Generally JavaScript for node, but could be anything for anything | either             | node, rollup, webpack, browserify | *edition autoloader*                                                 |
| `module` (previously `jsnext:main`) | ES2015 and above, for bundlers targeting modern web browsers      | ES Module `import` | rollup                            | [babel-preset-latest](http://babeljs.io/docs/plugins/preset-latest/) |
| `browser`                           | ES2015 and below, for bundlers targeting legacy web browsers      | CommonJS `require` | rollup, webpack, browserify       | [babel-preset-2015](http://babeljs.io/docs/plugins/preset-es2015)    |

### Explanation

* The `main` field is the standard target for `package.json` files and is flagshipped by Node.
  * While flagshipped by Node, its use is now widespread among many different systems, environments, and consumers.
  * Environment capabilities are whatever the consumers environment supports.
  * Tooling can be implemented by the producer at the runtime or install time of the consumer to add support for incompatible consumer environments, at the cost of CPU cycles, complexity, less consumer control.
  * Tooling can be implemented by the consumer at their runtime or compile time to add support for their incompatible environment, however this is time intensive and they are most likely to look elsewhere.
  * To reduce runtime, install, and consumer complexity, producers should publish their package with at least 2 editions of their code, the first being their source code, and the other targetting the lowest possible common denominator the consumers could share - intermediate editions for intermediate environments may also be published at the producers digression.
  * With multiple editions published for the highest to lowest supported environments, an *edition autoloader* can be used to by default quickly and intellegently select the best edition for the consumers environment at their runtime. If the consumer wishes to manually select which edition they use, they can sidestep the autoloader by requiring their desired edition directly, or by configuring the autoloader to select their preferred edition instead of their identified edition.
  * This approach allows minimal overheads for the producer in using their optimum tech while supporting legacy environments, while also allows for minimal overheads for the spectrum of consumers they support. And for edge cases, this approach also allows minimal overheads by allowing the consumer the power and information to override their edition selection and control their consumption in the ways they best see fit.
* The `module` field (formally the `jsnext:main` field) is flagshipped by rollup.
  * While flagshipped by rollup, it has also seen adoption in other bundlers and is a centerpoint for a proposal of ES Modules in Node.js.
  * The flagship use case is to provide a field for ES2015+ compliant code that uses the ES Modules syntax (aka the `import` syntax rather than the `require` syntax). The benefit to bundlers is that the explicit and static exporting and importing within ES Modules allows bundlers to build smaller and faster bundles that have more used code and less unused code in them. The bundle can then be compiled down to the lowest possible common demonator of features that the web browsers of the consumers audience supports.
  * A secondary use case is for node.js end-user applications (where the entire app and dependencies rather being across thousands of files, are in one minified file, speeding up load time for consumers of the node.js app).
  * In all common use cases the intention is for the target to be code that uses the ES Module `import` syntax for use in environments that only support ratified ES features, to which degree is unknown. Adding staging or alternative features (e.g. JSX) to this target increases complexity for the consumers of your package, as their environments, tooling or configurations may not support non-ratified features.
  * As the degree of supported ES features by our consumer is unknown, given this field targets modern standardised environments with ES Modules, we recommend setting this field to an edition that uses the ES Module `import` syntax and only uses ratified ES features. Compiler presets such as [babel-preset-latest](http://babeljs.io/docs/plugins/preset-latest/) will do the job. We do not currently recommend publishing an edition for this field if your source code did not originally use the ES Module syntax.
* The `browser` field is flagshipped by browserify.
  * While originally flagshipped by browserify, this field is now somewhat standardised and used by rollup and webpack too.
  * The flagship use case, as established by browserify, was to convert code that was written for Node 0.10 and 0.12 to target web browsers such as Internet Explorer 10 and Google Chrome 35. Browserify would also shim builtin Node libraries with browser compatible versions, as well as analyse the Node Module System (aka the `require` and `module.exports` syntax) to combine all the files across different modules into a single bundle file, for use in the web browser.
  * As it was intended for code in the Node 0.10 era as well as browsers like Internet Explorer 10, the flagship use case of targeting older environments has not changed. For newer environments and workflows, the `module` field has been introduced, as seen earlier.
  * As the degree of supported ES features by these older environments is unknown, we recommend targetting an edition that uses no later than ES2015 features, and of course it must use the Node Module `require` syntax. Compiling ES2015 and newer features down to ES5 is difficult as operational parity may not exist, causing such conversions to be error prone. Compiling other features or other languages may not have this issue. Consumer polyfills to emulate any missing ES2015 features are also an option. As such:
    * If you are using ES2015 features or newer, use the [babel-preset-2015](http://babeljs.io/docs/plugins/preset-es2015) to obtain near operational parity with your source edition and ES2015 edition. On the edge case the consumers target may be missing any ES2015 features, consumers can be instructed using the [babel polyfill](http://babeljs.io/docs/usage/polyfill/) will offer them better operational parity - our recommended *meta builder* [projectz](https://npmjs.com/package/projectz) will provide such instructions automatically in your README along with the automatic edition instructions for you.
    * If you are using other languages, check which ES version they compile down to, before using this field for result. The official [CoffeeScript](http://coffeescript.org) compiler for example compiles CoffeeScript into valid ES5 code.
    * Alternatively, you could just write ES5 or ES3 code, however, in that case, why even use editions if you wish to continue to write code for the lowest possible denominator.


