NPM package development with Vite
Tags: npm, vite, typescript, javascript
Published: 2022-06-16 05:51:30

## Why `vite` is awesome

Before, when we developed `npm` packages, it involved A LOT of manual configuration, development steps and testing to ship out a `npm` package.

We were dealing with `webpack` and `rollup` and more, the templating or boilerplate open-source repos that provides rapid-development for our `npm` package(s) - these were valuable to shortening our development & testing time.

Thankfully, `vite` is here and it is awesome! And the attractive feature here, is that `vite` pre-bundles dependencies with `esbuild` [[1][1]]. There are more features we will get to play with, which we will explore in this article.

## Let's build our first `npm` package!

First, let's create with `yarn create vite`.
![yarn create vite](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijlkn4p7m6pc6fp3b2hc.png)

Now, our new project has been scaffolded, and let's see our  `package.json` file. 
```json
{
  "name": "awesome-vite-module",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "typescript": "^4.5.4",
    "vite": "^2.9.9"
  }
}
```

Next, new goal is to configure our project with `rollup` config and `vite` config together.

First, let's install new package dependencies we will need - we want to use the built-in `rollup` features in `vite`.
```json
{
  "name": "awesome-vite-module",
  "private": true,
  "version": "0.0.0",
  "exports": {
    ".": {
      "import": "./dist/main.es.js",
      "require": "./dist/main.cjs.js"
    }
  },
  "main": "./dist/main.cjs.js",
  "module": "./dist/main.es.js",
  "typings": "./dist/main.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "tsc && vite build",
    "build:watch": "tsc && vite build --watch",
    "dev": "vite",
  },
  "dependencies": {},
  "devDependencies": {
    "@rollup/plugin-typescript": "^8.2.1",
    "@types/node": "^17.0.35",
    "prettier": "2.6.2",
    "rollup-plugin-typescript-paths": "^1.3.0",
    "tslib": "^2.4.0",
    "typescript": "^4.7.2",
    "vite": "^2.9.9",
  }
}
```

Next, let's set up our `tsconfig.json` file [[2][2]].
```json
{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "types": ["vite/client", "node"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "baseUrl": "./",
    "paths": {
      "~/*": ["src/*"]
    }
  },
  "include": ["./src"],
  "exclude": ["node_modules"]
}
```

We will need to set up a new `vite.config.ts` [[3][3] [4][4]] (also because this tutorial is `typescript` scaffolded).
```typescript
// vite.config.ts
import { defineConfig } from "vite";

import typescript from "@rollup/plugin-typescript";
import path from "path";
import { typescriptPaths } from "rollup-plugin-typescript-paths";

export default defineConfig({
  plugins: [],
  resolve: {
    alias: [
      {
        find: "~",
        replacement: path.resolve(__dirname, "./src"),
      },
    ],
  },
  server: {
    port: 3000,
  },
  build: {
    manifest: true,
    minify: true,
    reportCompressedSize: true,
    lib: {
      entry: path.resolve(__dirname, "src/main.ts"),
      fileName: "main",
      formats: ["es", "cjs"],
    },
    rollupOptions: {
      external: [],
      plugins: [
        typescriptPaths({
          preserveExtensions: true,
        }),
        typescript({
          sourceMap: false,
          declaration: true,
          outDir: "dist",
        }),
      ],
    },
  },
});
```

And let's clean up `main.ts`, to declare a simple demo feature, a function called `hello`.
```typescript
// main.ts
const hello = (name: string) => {
  return `Hello there, ${name}!`;
};

export { hello };
```

## Almost done, some cleaning up

Lastly, let's get rid of files we don't need at this time:
1. `style.css`
2. `index.html`

## Rapid testing (without unit testing)

Looks like our first `npm` package is ready for testing. But how do we do a quick test, without `jest` or `vitest`?

> There are two module testing suggestions, using [`yalc`](https://github.com/wclr/yalc) or `npm link` (`yalc` is preferred).

We execute `npm link` in our `awesome-vite-module` project.

```bash
npm link
```

Then, we are now able to use it, in another project. Let's quick scaffold a demo project, with another `vite` based framework, called `solidjs` [[5][5]].

```bash
npx degit solidjs/templates/js my-app
cd my-app
npm i
npm run dev
```

Once created and have dependencies installed, run `npm link awesome-vite-module` in it.

Lastly, modify the `App.tsx` file like example below
```typescript
import type { Component } from "solid-js";

import logo from "./logo.svg";
import styles from "./App.module.css";

import { hello } from "awesome-vite-module";

const App: Component = () => {
  return (
    <div class={styles.App}>
      <header class={styles.header}>
        <img src={logo} class={styles.logo} alt="logo" />
        <p>{hello("Brian")}</p>
      </header>
    </div>
  );
};

export default App;
```

Awesome, it's working!
![example solidjs project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2i0syktlhs6e9qsvxh0.png)

> When you're done, execute `npm unlink awesome-vite-module`.



## That's it!

That's the end of this article, eventually you're able to `npm login` and later `npm publish` your first `npm` package.

> Did some sections not work, or returned errors? Debugging will be part of the learning journey - and if you learn better from examples, see the `vite` boilerplate of `vanilla-ts` here at https://github.com/entwurfhaus/vite-vanilla-ts-module.

I hope this article / tutorial was helpful, and enjoy using `vite` as much as I do these days! Thanks, and happy coding!

## References

1. [Vite | Slow Server Start][1]
2. [Vite | Features > Client Types][2]
3. [Vite | Building for Production > Customising the build][3]
4. [Vite | Config File > Config Intellisense][4]
5. [SolidJS | Getting Started][5]

[1]: https://vitejs.dev/guide/why.html#the-problems
[2]: https://vitejs.dev/guide/features.html#client-types
[3]: https://vitejs.dev/guide/build.html#customizing-the-build
[4]: https://vitejs.dev/config/#config-intellisense
[5]: https://www.solidjs.com/guides/getting-started