pizza-package v2.0.0
- We're going to initialise the repository -
yarn init -y - Next we're gonna add TypeScript and node types -
yarn add -D typescript @types/node - I've taken the liberty of adding some files already - tsconfig with some basic defaults, and a
srcfolder with agetPizzaRecipefunction insideutilsand some interfaces associated with our function. - Now, we could just run
tscand then publish our lib folder, but there's a couple of things wrong with this:- first of all it outputs multiple files and folders - in this case we can see that there's a JS file generated for the types file, which aren't needed. We have to remember that
tscisn't a bundler, just a transpiler. - If the consumer wanted to consume the
Pizzatype, and it wasn't exported from theindex.tsthey would have import from the dist or extract the type from the function, which looks ugly & isn't best practice. Furthermore, often IDEs get confused and import the type from the dist folder, which is not what we want. - We wouldn't be able to exclude types
SecretBaseIngredients.types.tsfrom the consumer - You don't get some of the goodness of a compiler like ESBuild like tree shaking, minification and traspeed
- first of all it outputs multiple files and folders - in this case we can see that there's a JS file generated for the types file, which aren't needed. We have to remember that
To solve some of these issues, I'm going to use a bundler. In this case rollup. It's been the industry standard bundler for a while, and supports a lot of new tooling..including esbuild, which will be my choice of transpiler. Finally, we're also going to add rollup-plugin-dts which allows us to bundle the types we want to expose to the consumer.
- So, let's add these dependencies -
yarn add -D rollup rollup-plugin-esbuild esbuild rollup-plugin-dts - And then create a rollup config file
touch rollup.config.ts
ES Modules has been generally available since Node 14's release in 2020, so there's no reason why we shouldn't be an ESM-first package, but also publish CJS version of our package for compatibility. To do this we need to make some changes to our package.json
- Lets change the package type to
"type": "module" - Replace the
"main"key value pair with"source": "src/index.ts" - Add a
"types"key with"types": "dist/index.d.ts" - Add a
"files"key with"files": ["dist"] Add an exports key with
"exports": { "./package.json": "./package.json", ".": { "require": "./dist/index.js", "import": "./dist/index.mjs", "types": "./dist/index.d.ts" } },The "exports" field allows us to restrict external access to non-exported module files.
Next we're going to add our rollup config. Here's something I prepared earlier:
import esbuild from "rollup-plugin-esbuild";
import { createRequire } from "module";
import dts from "rollup-plugin-dts";
const require = createRequire(import.meta.url);
const pkgjson = require("./package.json");
/**
* @type {import('rollup').RollupOptions[]}
*/
const config = [
{
plugins: [esbuild()],
input: pkgjson.source,
output: [
{
format: "es",
file: pkgjson.exports["."].import,
},
{
format: "cjs",
file: pkgjson.exports["."].require,
},
],
},
{
plugins: [dts()],
input: pkgjson.source,
output: [
{
file: pkgjson.types,
format: "es",
},
],
},
];
export default config- Finally, we're going to add a build script:
"build": "rollup -c"and runyarn buildAnd here's the output adistfolder with 3 filesindex.d.ts,index.jsandindex.mjs, ready to ship. Much better than ourlibfolder.