cover.jpg

Use nanoid in WeChat Mini Program

2 min read

Developing WeChat mini program

Want to use nanoid to generate unique id or something like that

npm i nanoid

“node:crypto” is not defined, “crypto” is not defined

Surpise! nanoid is relying on Web Crypto API

WeChat don’t have Web Crypto API

What to do now?

Peek the source code

50
51
52
export let nanoid = (size = 21) =>
	crypto.getRandomValues(new Uint8Array(size)).reduce(/* ... */);
// ...

Oh, it just need only crpyto.getRandomValues. Don’t require entire crypto API

Fortunately, WeChat mini program has built-in wx.getRandomValues!

Let’s try to port this

First, change cryto.getRandomValues() to wx.getRandomValues

export let nanoid = (size = 21) =>
	wx.getRandomValues({
		length: size,
		succes: res => new Uint8Array(res.randomValues
	})
	.reduce(/* ... */)

wx.getRandomValues it not immediately return value, instead it is a callback style so can’t just simple call .reduce

Need to move reduce into the success callback function

Don’t like that way

Make it promise!

export let nanoid = async (size = 21) => {
	const randomValues = await new Promise((resolve) => {
		wx.getRandomValues({
			length: size,
			success: res => resolve(new Uint8Array(res.randomValues))
		}
	})

	return randomValues.reduce(/* ... */)
};

It work!

Copy and paste it some where in the project

npm remove nanoid. No need it in node_modules any more

Here the final code

I’m not security expert. Use this at your own risk

export default async function nanoid(size = 21) {
	const randomValues = await new Promise((resolve) => {
		wx.getRandomValues({
			length: size,
			success: (res) => resolve(new Uint8Array(res.randomValues)),
		});
	});

	return randomValues.reduce((id, byte) => {
		byte &= 63;
		if (byte < 36) {
			id += byte.toString(36);
		} else if (byte < 62) {
			id += (byte - 26).toString(36).toUpperCase();
		} else if (byte > 62) {
			id += "-";
		} else {
			id += "_";
		}
		return id;
	}, "");
}

Usage

const id = await nanoid();
Support me on Ko-fi
Share
Twitter Tweet