Skip to content

Commit

Permalink
Improve performance and bundled size (#6)
Browse files Browse the repository at this point in the history
* test the file contents

* use base64 instead of an integer array

* single to double-quoted strings

* consistent semicolons

* make isomorphic

* simple version, but vitest doesn't start

* resolve base64 decode with native module

* decode with `atob` if exists on `self`

* update doc

* fix test

---------

Co-authored-by: Tachibana Shin <[email protected]>
  • Loading branch information
kevlened and tachibana-shin authored Feb 29, 2024
1 parent d694cca commit 32ba3bd
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 3 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ import arrayBuffer from "./typescript.svg?arraybuffer";
import uint8array from "./typescript.svg?uint8array";
```

Reduce compilation size
This module uses the primitive translation method to `int8` which will double the file size after compilation but it runs very fast because it can be copied directly to RAM.

However, for those who want the advantage of packet size there is an additional option called `base64` which will only increase the packet size by `20%` however it will require the browser to decode the base64 before it can be copied. gets into RAM
báe64

```main.ts
import arrayBuffer from "./typescript.svg?arraybuffer&base64";
import uint8array from "./typescript.svg?uint8array&base64";
```

Thanks [@kevlened](https://github.com/kevlened) for the `base64` support work done by



### TypeScript support

This plugin also supports typing for typescript
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script type="module" src="/src/main-web.ts"></script>
</body>
</html>
17 changes: 17 additions & 0 deletions src/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
import arrayBuffer from "./typescript.svg?arraybuffer";
import uint8array from "./typescript.svg?uint8array";
import arrayBufferB64 from "./typescript.svg?arraybuffer&base64";
import uint8arrayB64 from "./typescript.svg?uint8array&base64";
import crypto from "node:crypto";

import { describe, expect, test } from "vitest";

const hash = (buffer: ArrayBuffer) => crypto.createHash("md5").update(Buffer.from(buffer)).digest("hex");

describe("test plugin", () => {
test("?arraybuffer", () => {
expect(arrayBuffer[Symbol.toStringTag]).toBe("ArrayBuffer");
expect(arrayBuffer instanceof ArrayBuffer).toBe(true);
expect(hash(arrayBuffer)).toEqual("7167f7caac27a336c58b0c16cc5003d7");
});
test("?uint8array", () => {
expect(uint8array[Symbol.toStringTag]).toBe("Uint8Array");
expect(uint8array instanceof Uint8Array).toBe(true);
expect(hash(uint8array.buffer)).toEqual("7167f7caac27a336c58b0c16cc5003d7");
});
test("?arraybuffer&base64", () => {
expect(arrayBufferB64[Symbol.toStringTag]).toBe("ArrayBuffer");
expect(arrayBufferB64 instanceof ArrayBuffer).toBe(true);
expect(hash(arrayBufferB64)).toEqual("7167f7caac27a336c58b0c16cc5003d7");
});
test("?uint8array&base64", () => {
expect(uint8arrayB64[Symbol.toStringTag]).toBe("Uint8Array");
expect(uint8arrayB64 instanceof Uint8Array).toBe(true);
expect(hash(uint8arrayB64.buffer)).toEqual("7167f7caac27a336c58b0c16cc5003d7");
});
});
91 changes: 89 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,84 @@ import { promises } from "fs";
// eslint-disable-next-line n/no-extraneous-import
import { PluginOption } from "vite";

const decode64Raw = `function b64ToUint6(nChr) {
return nChr > 64 && nChr < 91
? nChr - 65
: nChr > 96 && nChr < 123
? nChr - 71
: nChr > 47 && nChr < 58
? nChr + 4
: nChr === 43
? 62
: nChr === 47
? 63
: 0
}
function base64ToUint8(sBase64, nBlocksSize) {
const sB64Enc = sBase64.replace(/[^A-Za-z0-9+/]/g, "")
const nInLen = sB64Enc.length
const nOutLen = nBlocksSize
? Math.ceil(((nInLen * 3 + 1) >> 2) / nBlocksSize) * nBlocksSize
: (nInLen * 3 + 1) >> 2
const taBytes = new Uint8Array(nOutLen)
let nMod3
let nMod4
let nUint24 = 0
let nOutIdx = 0
for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4))
if (nMod4 === 3 || nInLen - nInIdx === 1) {
nMod3 = 0
while (nMod3 < 3 && nOutIdx < nOutLen) {
taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255
nMod3++
nOutIdx++
}
nUint24 = 0
}
}
return taBytes
}
function toUint8(b64) {
let bin = atob(b64)
let len = bin.length
let bytes = new Uint8Array(len)
for (let i = 0; i < len; i++) {
bytes[i] = bin.charCodeAt(i)
}
return bytes
}
const decode64 = typeof atob === "function" ? toUint8 : base64ToUint8
export default decode64
`

export default function vitePluginArraybuffer(): PluginOption {
return {
name: "vite-plugin-arraybuffer",
resolveId(id) {
if (id.endsWith("?arraybuffer") || id.endsWith("?uint8array")) {
if (
id.endsWith("?arraybuffer") ||
id.endsWith("?uint8array") ||
id.endsWith("?arraybuffer&base64") ||
id.endsWith("?uint8array&base64") ||
id === "virtual:decode-64"
) {
return id
}

return;
return
},
load(id) {
if (id === "virtual:decode-64") {
return decode64Raw
}
return
},
async transform(_src, id) {
if (id.endsWith("?arraybuffer")) {
Expand All @@ -30,6 +99,24 @@ export default function vitePluginArraybuffer(): PluginOption {
${new Uint8Array(await promises.readFile(file)).join(',')}
])`;
}
if (id.endsWith("?arraybuffer&base64")) {
const file = id.slice(0, -19)
this.addWatchFile(file)

const buffer = await promises.readFile(file)
const b64 = buffer.toString("base64")

return `import decode64 from 'virtual:decode-64'\nexport default decode64("${b64}").buffer`
}
if (id.endsWith("?uint8array&base64")) {
const file = id.slice(0, -18)
this.addWatchFile(file)

const buffer = await promises.readFile(file)
const b64 = buffer.toString("base64")

return `import decode64 from 'virtual:decode-64'\nexport default decode64("${b64}")`
}

return;
},
Expand Down
12 changes: 12 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ declare module "*?uint8array" {

export default value;
}

declare module "*?arraybuffer&base64" {
const value: ArrayBuffer;

export default value;
}

declare module "*?uint8array&base64" {
const value: Uint8Array;

export default value;
}

0 comments on commit 32ba3bd

Please sign in to comment.