67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
import {
|
|
bold,
|
|
red
|
|
} from 'colorette'
|
|
import {
|
|
AsyncZippable,
|
|
zip
|
|
} from 'fflate'
|
|
import { filesize } from 'filesize'
|
|
import {
|
|
readdir,
|
|
readFile,
|
|
writeFile
|
|
} from 'node:fs/promises'
|
|
import { promisify } from 'node:util'
|
|
import { Plugin } from 'vite'
|
|
import { relative } from 'node:path'
|
|
|
|
|
|
async function* traversalDir(path: string): AsyncGenerator<[ string, string, Uint8Array ]> {
|
|
yield [ 'startDir', path, new Uint8Array(1) ]
|
|
let dirents = await readdir(path, {withFileTypes: true})
|
|
for (let dirent of dirents) {
|
|
let subDir = `${path}/${dirent.name}`
|
|
if (dirent.isDirectory()) {
|
|
yield* traversalDir(subDir)
|
|
} else {
|
|
yield [ 'file', subDir, await readFile(subDir) ]
|
|
}
|
|
}
|
|
yield [ 'endDir', path, new Uint8Array(1) ]
|
|
}
|
|
|
|
async function doZip(path: string) {
|
|
let data: AsyncZippable = {}
|
|
for await (const e of traversalDir(path)) {
|
|
if (e[0] === 'file') {
|
|
data[relative(path, e[1])] = e[2]
|
|
}
|
|
}
|
|
return await promisify(zip)(data)
|
|
}
|
|
|
|
export default function zipDist(name?: string, addVersion: boolean = false): Plugin {
|
|
if (!!name && !name.endsWith('.zip')) {
|
|
name = `${name}.zip`
|
|
} else if (!name) {
|
|
let {npm_package_name = 'bundle', npm_package_version} = process.env
|
|
name = !!npm_package_version && addVersion ?
|
|
`${npm_package_name}-${npm_package_version}.zip` : `${npm_package_name}.zip`
|
|
}
|
|
|
|
return {
|
|
name: 'vite-plugin-dist-zip',
|
|
writeBundle: {
|
|
sequential: true,
|
|
order: 'post',
|
|
handler(options, bundle) {
|
|
doZip(options.dir!)
|
|
.then(value => Promise.all([ writeFile(`./dist/${name}`, value), Promise.resolve(value.byteLength) ]))
|
|
.then(value => console.log(red(`\n压缩完成 ${bold(`dist/${name}`)} ${filesize(value[1])}`)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|