@pika/pack - Publish great npm packages.
Tags: pika, npm, javascript, webdev
Published: 2019-08-02 16:03:59

*Note: This piece was originally published to [pika.dev](https://www.pika.dev/blog/introducing-pika-pack/).*

If you've recently published a package to npm, you know how much work goes into a modern build process. Transpile JavaScript, compile TypeScript, convert ES Module syntax (ESM) to Common.js, configure your package.json manifest... and that's just the basics.

What about web browsers and bundlers? Is your [package optimized for them](https://github.com/marmelab/react-admin/issues/2204)? Can users load your package from [UNPKG](https://unpkg.com/)? Does it include [type definitions](https://codeburst.io/https-chidume-nnamdi-com-npm-module-in-typescript-12b3b22f0724) for VSCode & TypeScript users? Has it been [stripped of all unnecessary files](https://medium.com/@jdxcode/for-the-love-of-god-dont-use-npmignore-f93c08909d8d) to be as small as possible? Your users care about these optimizations, but they all require even more knowledge, configuration, tooling, time and effort to get right.

### @pika/pack builds amazing packages without the hassle:

- **Simple** ⚡️ Use pre-configured plugins to build your entire package.
- **Flexible** 🏋️‍♀️ Choose plugins and optimizations that match your needs.
- **Holistic** ⚛️ Let us handle your code, assets, ***and*** package.json config.


## The Package Build Pipeline

[@pika/pack](https://github.com/pikapkg/pack) connects pre-configured plugins to build and optimize your package for you. Plugins wrap already-popular tools like [Babel](https://babeljs.io/) and [Rollup](https://rollupjs.org/) with options already optimized for npm. This lets @pika/pack build your package without much (if any) configuration required on your part.

***@pika/pack even creates and configures a package.json manifest for your package, automatically.***

This works because [@pika/pack](https://github.com/pikapkg/pack) builds your entire package: code, assets, and even package.json manifest. By building the entire package, you end up with a fully-built `pkg/` directory, ready to publish. Entry points like "main", "module", "umd:main", "types", "unpkg", and even advanced options like "sideEffects" and "files" are all handled by your build plugins.

Getting started is easy:

```js
// 1. Install @pika/pack!
$ npm install -g @pika/pack
// 2. Add this to your package.json manifest:
"@pika/pack": {"pipeline": []},
// 3. Run @pika/pack!
$ pack build
```

<span style="font-size: 3rem">😎 🆒</span>

So now what? If you run `pack build` with an empty pipeline, you'll get an empty package. That's not very useful.

To get you started, here are our five favorite things to do with [@pika/pack](https://github.com/pikapkg/pack):

### 1. Publish Modern, ES2018 JavaScript By Default (1 Line)

```js
"@pika/pack": {
    "pipeline": [
        ["@pika/plugin-standard-pkg", {"exclude": ["__tests__/**/*"]}]
    ]
}
```

The first plugin that most packages will use is [@pika/plugin-standard-pkg](https://github.com/pikapkg/builders/tree/master/packages/plugin-standard-pkg). This is our standard ["source" builder](https://github.com/pikapkg/builders#source-builders) that builds any JavaScript & TypeScript source code to the latest ES2018 language spec.  TypeScript is supported by default, and any custom Babel plugins in your local `.babelrc` will be used automatically (the plugin is powered by Babel internally).

This gives the rest of our pipeline a standard ES2018 target to build from. BONUS: some of your users may support modern JavaScript, and can leverage this ES2018 distribution directly for a smaller, faster, less-bloated package.


### 2. Publish Node.js & Web-Optimized Builds (1 Line Each)

```js
"@pika/pack": {
    "pipeline": [
        ["@pika/plugin-standard-pkg"],
        ["@pika/plugin-build-node"],
        ["@pika/plugin-build-web"]
    ]
}
```

After creating your modern ES2018 build, it becomes trivial to add Node.js- and web-optimized distributions to your package. [@pika/plugin-build-node](https://github.com/pikapkg/builders/tree/master/packages/plugin-build-node) will transpile a Node.js-ready distribution to run on any supported Node.js version. [@pika/plugin-build-web](https://github.com/pikapkg/builders/tree/master/packages/plugin-build-web) will build a more modern, ES module (ESM) distribution: optimized for bundlers and compiled to run on all browsers that support ESM syntax natively.

Both plugins use Rollup internally, but you don't have to configure any bundler logic yourself. With just three lines of JSON you get a package that is fully optimized for the two most popular JS platforms. And because [@pika/pack](https://github.com/pikapkg/pack) builds your entire package, your package.json manifest is automatically configured for you with "main", "module", and "esnext" entry points.


### 3. Automatically Generate TypeScript Definitions (1 Line)

```js
"@pika/pack": {
    "pipeline": [
        ["@pika/plugin-standard-pkg"],
        ["@pika/plugin-build-node"],
        ["@pika/plugin-build-web"],
        ["@pika/plugin-build-types"]
    ]
},
```

With [@pika/pack](https://github.com/pikapkg/pack), every package automatically gets `.d.ts` TypeScript definition files thanks to the [@pika/plugin-build-types](https://github.com/pikapkg/builders/tree/master/packages/plugin-build-types) plugin. Even if you're writing JavaScript, this plugin will use TypeScript to automatically generate type definitions from your JavaScript & JSDoc!


### 4. Publish WASM! Or Reason, or Rust, or C++, or... (1-2 Lines)

```js
"@pika/pack": {
    "pipeline": [
        ["@pika/plugin-wasm-assemblyscript"],
        ["@pika/plugin-wasm-bindings"]
    ]
},
```

The pipeline concept is simple AND flexible. So flexible that your package source doesn't even need to be JavaScript:

- [@pika/plugin-source-bucklescript](https://github.com/pikapkg/builders/tree/master/packages/plugin-source-bucklescript) - Compile Reason or OCaml to ES2018 JavaScript via BuckleScript
- [@pika/plugin-wasm-assemblyscript](https://github.com/pikapkg/builders/tree/master/packages/plugin-wasm-assemblyscript) - Compile TypeScript to WASM via AssemblyScript
- [@pika/plugin-wasm-emscripten](https://github.com/pikapkg/builders/issues/1) - Compile C/C++ to WASM via Emscripten (Coming Soon!).
- [@pika/plugin-wasm-bindings](https://github.com/pikapkg/builders/tree/master/packages/plugin-wasm-bindings) - Add simple JavaScript bindings for any generated WASM.


### 5. Automatically Enhance Your Package (1 Line)

```js
"@pika/pack": {
    "pipeline": [
        ["@pika/plugin-standard-pkg"],
        ["@pika/plugin-build-node"],
        ["@pika/plugin-simple-bin", {"bin": "my-cli"}]
    ]
}
```

Build plugins can also enhance existing builds in some really exciting ways. Our favorite enhancement right now is [@pika/plugin-simple-bin](https://github.com/pikapkg/builders/tree/master/packages/plugin-simple-bin), which injects a simple CLI wrapper into any package and configures your package.json to point to it automatically.

We use @pika/pack to build @pika/pack, and we use this plugin specifically to [add a command-line interface](https://unpkg.com/@pika/pack@0.3.0/dist-node/index.bin.js) with none of the package.json configuration and setup hassle.

We can't wait to see what's possible with this wrapping concept, especially for CLIs: Automatically restart your program on failure, check for package updates after running, log usage statistics... [the possibilities are endless!](https://github.com/pikapkg/builders)


## Publishing Your Package

<p style="text-align: center; margin-bottom: 0rem;">
  <video autoplay muted playsinline  style="width: 100%">
    <source src="https://www.pika.dev/static/img/publish-demo.mp4" type="video/mp4">
    <img alt="Demo" src="https://www.pika.dev/static/img/publish-demo.gif">
  </video>
</p>

Publishing your package should be as easy as building it. So we brought our favorite parts of [np](https://github.com/sindresorhus/np) (a self-described "better npm publish") into [@pika/pack](https://github.com/pikapkg/pack). With the `publish` command there's no need to worry about how to publish your built package. Just run `pack publish` in your top-level project and @pika/pack will walk you through cutting a new version and publishing your package.

It even includes a handy [unpkg.com](https://unpkg.com/) at the end so that you can immediately view your new package.


## Try @pika/pack Today!

```shell
npm install -g @pika/pack
```

Don't wait, try [@pika/pack](https://github.com/pikapkg/pack) in your next package (or any old ones that could a 2019 upgrade). And when you do, [please let us know how it went!](https://twitter.com/pikapkg)

[Pika](/about) is a project to move the JavaScript ecosystem forward. Pika's mission is to make modern JavaScript more approachable by making it easier to find, publish, install, and use modern packages on npm. Hopefully @pika/pack moves us one step closer towards that goal.

- [Learn more about the Pika project →](/about)
- [Follow us on Twitter for updates →](https://twitter.com/pikapkg)


## Projects Already Using @pika/pack

- [react-async](https://github.com/ghengeveld/react-async) - Flexible promise-based React data loader.
- [hookuspocus](https://github.com/michael-klein/hookuspocus) - hooks for all the functions!
- [foundationjs](https://github.com/jvdsande/foundationjs) - Full-featured NodeJS framework.
- [graphql-rest-proxy](https://github.com/acro5piano/graphql-rest-proxy) - Turn your REST API into GraphQL.
- [custom-attributes](https://github.com/matthewp/custom-attributes) - Define custom attributes the same way you define custom elements.
- [@pika/pack](https://github.com/pikapkg/pack) & [@pika/web](https://github.com/pikapkg/web) - yes, we even [use @pika/pack](https://github.com/pikapkg/pack/blob/1034a2f5a36ee8664ee139508f8726892534f65d/package.json#L6-L27) to [build @pika/pack!](https://unpkg.com/@pika/pack/package.json) 🤯
- And hundreds more! [Check out our full set of example & starter projects →](https://github.com/pikapkg/examples)
- Have you used @pika/pack in a package? [Let us know](https://twitter.com/pikapkg) and we'll add your package to the list!