Geek Culture
Published in

Geek Culture

Step by Step Guide to Build and Publish a Real World Npm Package

Yet another guide to how to build an npm package? Yes and no. I will cover a bunch of things, but not npm commands and package.json fields neither to publish some stupid helloworld on npm. I believe npm is somewhere people publish something useful to others, maybe you want to publish something useful too, I hope this article can bring you some idea

Things I will cover

  • define the problem and solve it
  • abstract and parameterize it for general use
  • choose language, framework and build tool
  • code, test and back to code
  • document and publish to npm

Really recommand have a look at npm commands and package.json fields if you havn’t

If you need the codes/docs of water mask lib I use as example in this article, you can find it here.

Define the problem and solve it

Suppose the issue is to put some text as watermask on a page

to solve it, I choose to use a div overlay on top of the page, and it uses a svg as it’s background and it doesn’t block user inter-actions with page content, this needs the browser support

abstract and parameterize it for general use

If we want to make it useful to others, the div and css might well not help, so let’s make it a function. By instinct it come like this, add Mask to some element, with maskOptions you can config how the mask looks like

function addMaskTo(element,maskOptions){}

But how can you remove it once it’s added? So I changed it to just return an element

function getMask(maskOptions){}
let el = getMask()
document.body.appendChild(el)
// el.remove() // when you nolonger need it

There are points you need to consider

  • is it a pure function?(don’t modify the input arguments)
  • global namespace polution(when this can not be avoided, make sure the key is unique)
  • memory leak(when you bind listeners and use closer together, take care)
  • counterintuitive(people see the name and know how to use it)

Choose language, framework and build tool

When you write a lib, I recommand TypeScript, it’s more convenient, the IDEs will fill codes or let you choose instead of forcing developer to type all, but TypeScript has it’s cost, you need to learn and at times you find it not mature enough. Here I choose TypeScript.

You may write a lib for some frame work like React, yet maybe some other or not any. Here I choose both React and function in plain JavaScript

For bundle tool, TypeScript already can compile es5, I add webpack for UMD bundle

Create a repo on github, checkout repo, run commands init this project with TypeScript, webpack and React

npm init -y
npm i typescript webpack webpack-cli react -D

Here adds more to consideration list

  • developer experience
  • project complexity
  • support frame works

Code, test and back to code

I use a structure look like this

and default export a function, added support when developer need only to change the text

export default function getWaterMask(config: Config | string): HTMLElement {
...
}

and when test, I find when " or 'appears in svg styles, it stoped working because conflict so I use base64 encoded svg instead of plain xml svg

export function getBackgroundImageStr(text: string, svgProps: Props, textProps: Props): string {  
return `url("data:image/svg+xml;base64,${base64.encode(`<svg ${props2str(svgProps)}>${`<text ${props2str(textProps)}>${text}</text>`}</svg>`)}")`
}

use base64 lib or use window.btoa ? you need to consider if it works both in Node and browser, and importing libs might well enlarge the final bundle size, so still more considerations.

  • isomorphic(window is not defined in Node)
  • package size(which means end user experience)

I use examples as well as tests

<script src="../../dist/text-water-mask.umd.js"></script>
<script>document.body.appendChild(TextWaterMask.default({ text: 'hello world!!' }))</script>

Document and publish to npm

write a README.md to tell peple about your lib, and use github pages to make a live demo would be great! I generated demo with next export and html-inline , it looks like this

Then only left two things, publish and test the published, hope your package works fine.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store