> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/02-package.md).

# 02. Package Development

## Creating package

* [ ] [Checklist for your new Open Source JavaScript Project](https://ericdouglas.github.io/2015/09/27/checklist-for-your-new-open-source-javascript-project/)
* [ ] [Чеклист для новых npm-модулей](https://github.com/paulradzkov/checklist-for-new-npm-module)
* [ ] [npm-module-checklist](https://github.com/bahmutov/npm-module-checklist)
* [ ] [Reference for How to Write an Open Source JavaScript Library](https://github.com/sarbbottam/write-an-open-source-js-lib)
* [ ] [Notes and personal embleshments from Kent C. Dodds egghead.io course "How to write a Javascript Library"](https://github.com/bradleybossard/how-to-write-an-open-source-javascript-library)

## package.json

* [package.json specification ](<https://docs.npmjs.com/files/package.json >)

```javascript
{
  /* Name of the project */
  "name": "react-component-boilerplate",

  /* Brief description */
  "description": "Boilerplate for React.js components",

  /* Who is the author + optional email + optional site */
  "author": "Juho Vepsäläinen <email goes here> (site goes here)",

  /* Version of the package */
  "version": "0.0.0",

  /* Do not allow publishing, useful for apps or private packages */
  "private": true,
  
  "license": "MIT",

  /* Keywords related to package. */
  /* Fill this well to make the package discoverable. */
  "keywords": ["react", "reactjs", "boilerplate"],
  
  /* Links to homepage, repository, and issue tracker */
  "homepage": "https://<organization/user>.github.io/<project>/",
  "repository": {
    "type": "git",
    "url": "https://github.com/<organization/user>/<project>.git"
  },
  "bugs": {
    "url": "https://github.com/<organization/user>/<project>/issues"
  }

  /* Files to include to npm distribution. */
  /* Relative patterns like "./src" fail! */
  "files": ["lib/", "esm/", "bin/"]
  
  // ------------------------------------------------------------
  /* `npm run <name>` - `npm run` to get the available commands */
  "scripts": {
    /* You don’t need to write node_modules/.bin/catalog, npm will */
    /* automatically call locally-installed package. */
    "start": "catalog start docs",

    /* Namespacing (namespace:task) is a convention used for */
    /* grouping. */
    "test": "jest",
    "test:coverage": "jest --coverage",
    "test:watch": "jest --watch",
    "test:lint": "eslint . --ignore-path .gitignore",

    "gh-pages": "catalog build docs",
    "gh-pages:deploy": "gh-pages -d docs/build",

    "build": "npm run build:esm && npm run build:cjs",
    "build:esm": "babel --delete-dir-on-start -d esm/ src/",
    "build:cjs": "babel --delete-dir-on-start --env-name cjs -d lib/ src/",

    "preversion": "npm run test",
    "prepublishOnly": "npm run build",
    "postpublish": "npm run gh-pages && npm run gh-pages:deploy",

    /* If your library is installed through Git, compile it */
    "postinstall": "node lib/post_install.js"
  }
  
  // ------------------------------------------------------------
  /* Entry point for command line interface. */
  /* Don't set this unless you intend to allow command line usage */
  "bin": "bin/index.js",

  /* Main entry point (defaults to index.js) */
  "main": "lib/",

  /* ESM-based entry point for bundlers. */
  "module": "esm/"
  
  // ------------------------------------------------------------
  /* Dependencies required to use the package. */
  "dependencies": {
    /* ... */
  },

  /* Dependencies needed to develop/compile the package. */
  "devDependencies": {
    /* ... */
  },

  /* Package peer dependencies. The consumer chooses exact versions. */
  "peerDependencies": {
    "lodash": ">= 3.5.0 < 4.0.0",
    "react": ">= 0.14.0 < 17.0.0"
  }
}
```

## Project Structure

* [Setting up multi-platform npm packages](http://2ality.com/2017/04/setting-up-multi-platform-packages.html)
* [Transpiling dependencies with Babel](http://2ality.com/2017/04/transpiling-dependencies-babel.html)
* [Delivering untranspiled source code via npm](http://2ality.com/2017/06/pkg-esnext.html)

Folders:

* src: (uncompiled)&#x20;
* lib: compiled-node&#x20;
* dist: compiled-browser

## Deployment of JS code

You can only deliver source code for a single platform via an npm package. Property `engines` of `package.json` lets you specify exactly what platform that is:

```javascript
{ "engines" : { "node" : ">=0.10.3 <0.12" } }
{ "engines" : { "npm" : "~1.0.20" } }
```

However, that doesn’t help you with the following use cases, where you need source code for multiple platforms per package:

* *Browsers*: deliver both a native version (e.g. in ES5 via CJS) and a “bleeding edge” version (e.g. latest ECMAScript version via an ES module), to be transpiled by Babel.
* *Node.js*: deliver the same module for several versions of Node.js.
* *Browsers*: allow new libraries to age gracefully – transpile only as long your target platforms don’t support the features, yet. We want the same convenience that `babel-preset-env` affords us.

There are two dimensions at play here:

* On one hand, there is a distinction between code that is to be transpiled and “native” code.
* On the other hand, native code may have to run on platforms with different capabilities.

Three properties in `package.json` currently let you deliver multiple versions of the same code:

* `main`: points to a CommonJS module (or UMD module) with JavaScript as modern as Node.js can currently handle.
* `browser`: swaps out some of the main code so that it works in browsers.
* `module`: the same code as main, but in ES modules.
* `es2015`: untranspiled ES6 code. Introduced by Angular.
* `unpkg`: entry point if your code is loaded from unpkg.

If you publish your lib on npm it will be available over `unpkg`. It's a CDN so people can pull your scripts into their scripts without installing them over npm `https://unpkg.com/package@version/file`. Most of the time, it is a good practice to define the minified version of your lib there.

Then Babel introduced `preset-env`, which lets you adapt the code you generate to the platforms it will run on. Now, the best approach would be:

* App code: transpiled via Babel and `preset-env`:
  * Input: JavaScript with stage 4 features or older, in ES modules.
  * Output: whatever JavaScript runs best on the target platforms.
* Dependencies: must be delivered as both...
  * Transpiled code that runs natively on Node.js (meaning CommonJS modules, at the moment).
  * Untranspiled code that is transpiled along with your own code.

The benefits of this new approach are:

* ES modules enable tree-shaking.
* The output is upgraded automatically as the target platforms evolve (thanks to `preset-env`).

## Developing a JavaScript package

* <https://auth0.com/blog/developing-npm-packages>&#x20;
* <https://github.com/stereobooster/package.json>&#x20;

### Books

* [ ] [Survive.JS - Maintainance Book](https://survivejs.com/maintenance/introduction/)

### Articles

* [ ] [Modern Modules](https://medium.com/@mikeal/modern-modules-d99b6867b8f1)
* [ ] [Deploying ES2015+ Code in Production Today](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/)

## Publish `npm` module

* [ ] [`np`](https://github.com/sindresorhus/np) - better npm publish
* [ ] [`package.json` public files](https://docs.npmjs.com/files/package.json#files)
* [ ] [`npm` for developers](https://docs.npmjs.com/misc/developers)
* [ ] [Publishing what you mean to publish](http://blog.npmjs.org/post/165769683050/publishing-what-you-mean-to-publish)
* [ ] <https://codeburst.io/how-to-create-and-publish-your-first-node-js-module-444e7585b738>

### Prepare for publishing

<https://github.com/typicode/pkg-ok>

1. Prepare source code for release (compile).
2. Add information about entry point:
3. `"main"`
4. `"browser"`
5. `"module"`
6. `"unpkg"`
7. Add description of included files on publish.
8. `"files"`
9. `.gitignore`
10. `.npmignore`
11. Check `version`, probably bump it.
12. Publish package, probably with a release tag.
13. [egghead.io: Publish JavaScript packages on npm](https://egghead.io/courses/publish-javascript-packages-on-npm)

### Scoped packages

Scoped packages are private by default. However, public scoped modules are free and don’t require a paid subscription. To publish a public scoped module, set the access option when publishing it. This option will remain set for all subsequent publishes.

## JS Dev Tools

### Editors

* [`snippet-generator`](https://pawelgrzybek.com/snippet-generator/)

### Package size

* [ ] [`bundlesize`](https://github.com/siddharthkp/bundlesize)
* [ ] [`size-limit`](https://github.com/ai/size-limit)

### Code coverage

* [ ] [`codecov.io`](https://codecov.io/)

## Documentation

* <https://jsdoc.app/>
* <http://speakingjs.com/es5/ch29.html>&#x20;
* <https://www.docz.site/>
