From db032dad80fe3d13f4e278ff2cd2d8b902f5675b Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Thu, 5 Sep 2024 17:56:19 +0800 Subject: [PATCH] feat: tarball support gen gz --- README.md | 18 ++++++++--------- __tests__/options.spec.ts | 2 +- __tests__/tarball.spec.ts | 42 +++++++++++++++++++++++++++++++++++---- package.json | 2 +- src/compress.ts | 11 ++++++++-- src/index.ts | 4 ++-- src/interface.ts | 10 ++++++---- yarn.lock | 10 +++++----- 8 files changed, 71 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 8996df9..d27ec32 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,16 @@ export default defineConfig({ ## Options -| params | type | default | description | -| ---------------------- | --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------ | +| params | type | default | description | +| ---------------------- | --------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | | `include` | `string \| RegExp \| Array` | `/\.(html\|xml\|css\|json\|js\|mjs\|svg\|yaml\|yml\|toml)$/` | Include all assets matching any of these conditions. | -| `exclude` | `string \| RegExp \| Array` | `-` | Exclude all assets matching any of these conditions. | -| `threshold` | `number` | `0` | Only assets bigger than this size are processed (in bytes) | -| `algorithm` | `string\| function` | `gzip` | The compression algorithm | -| `compressionOptions` | `Record` | `{}` | Compression options for `algorithm`(details see `zlib module`) | -| `deleteOriginalAssets` | `boolean` | `false` | Whether to delete the original assets or not | -| `skipIfLargerOrEqual` | `boolean` | `true` | Whether to skip the compression if the result is larger than or equal to the original file | -| `filename` | `string` | `[path][base].gz` | The target asset filename | +| `exclude` | `string \| RegExp \| Array` | `-` | Exclude all assets matching any of these conditions. | +| `threshold` | `number` | `0` | Only assets bigger than this size are processed (in bytes) | +| `algorithm` | `string\| function` | `gzip` | The compression algorithm | +| `compressionOptions` | `Record` | `{}` | Compression options for `algorithm`(details see `zlib module`) | +| `deleteOriginalAssets` | `boolean` | `false` | Whether to delete the original assets or not | +| `skipIfLargerOrEqual` | `boolean` | `true` | Whether to skip the compression if the result is larger than or equal to the original file | +| `filename` | `string` | `[path][base].gz` | The target asset filename | ## Q & A diff --git a/__tests__/options.spec.ts b/__tests__/options.spec.ts index 7d485b5..6b25a73 100644 --- a/__tests__/options.spec.ts +++ b/__tests__/options.spec.ts @@ -32,7 +32,7 @@ async function mockBuild( } }, root: path.join(__dirname, 'fixtures', dir), - plugins: [compression(conf)], + plugins: [compression(conf as any)], logLevel: 'silent' }) return id diff --git a/__tests__/tarball.spec.ts b/__tests__/tarball.spec.ts index a9afcbb..443c809 100644 --- a/__tests__/tarball.spec.ts +++ b/__tests__/tarball.spec.ts @@ -15,9 +15,13 @@ const sleep = (delay: number) => new Promise((resolve) => setTimeout(resolve, de const dist = path.join(__dirname, 'dist') const dest = path.join(__dirname, '.dist') -function extract(p: string): Promise> { +function extract(p: string, gz = false): Promise> { const extract = createExtract() - fs.createReadStream(p).pipe(extract.receiver) + if (gz) { + fs.createReadStream(p).pipe(zlib.createUnzip()).pipe(extract.receiver) + } else { + fs.createReadStream(p).pipe(extract.receiver) + } return new Promise((resolve, reject) => { const files: Record = {} extract.on('entry', (head, file) => { @@ -30,12 +34,13 @@ function extract(p: string): Promise> { async function mockBuild( dir = 'public-assets-nest', - options?: ViteCompressionPluginConfig + options?: ViteCompressionPluginConfig, + gz = false ) { const id = getId() await build({ root: path.join(__dirname, 'fixtures', dir), - plugins: [compression(options), tarball({ dest: path.join(dest, id) })], + plugins: [compression(options), tarball({ dest: path.join(dest, id), gz })], configFile: false, logLevel: 'silent', build: { @@ -104,3 +109,32 @@ test('tarball specify output', async () => { const outputs = await extract(path.join(dest, id + '.tar')) expect(Object.keys(outputs).length > 0).toBeTruthy() }) + +test('tarball specify output with gz', async () => { + const id = getId() + await mockBuildwithoutCompression('public-assets-nest', id, { dest: path.join(dest, id), gz: true }) + await sleep(3000) + const outputs = await extract(path.join(dest, id + '.tar.gz'), true) + expect(Object.keys(outputs).length > 0).toBeTruthy() +}) + +test('tarball gz with compression', async () => { + const id = await mockBuild('public-assets-nest', { deleteOriginalAssets: true, skipIfLargerOrEqual: false }, true) + await sleep(3000) + const { bundle } = await mockBuildwithoutCompression('public-assets-nest', getId()) + await sleep(3000) + const outputs = extract(path.join(dest, id + '.tar.gz'), true) + + if (typeof bundle === 'object' && 'output' in bundle) { + for (const chunk of bundle.output) { + if (chunk.fileName in outputs) { + const act = Buffer.from(outputs[chunk.fileName]) + if (chunk.type === 'asset') { + expect(act).toStrictEqual(Buffer.from(chunk.source)) + } else { + expect(act).toStrictEqual(Buffer.from(chunk.code)) + } + } + } + } +}) diff --git a/package.json b/package.json index 18a1614..1852850 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "dependencies": { "@rollup/pluginutils": "^5.1.0", - "tar-mini": "^0.1.1" + "tar-mini": "^0.2.0" }, "resolutions": { "is-core-module": "npm:@nolyfill/is-core-module@^1", diff --git a/src/compress.ts b/src/compress.ts index eecaa3e..4b727ce 100644 --- a/src/compress.ts +++ b/src/compress.ts @@ -50,6 +50,7 @@ export const defaultCompressionOptions: { interface TarballOptions { dests: string[] root: string + gz: boolean } interface TarballFileMeta { @@ -62,7 +63,8 @@ export function createTarBall() { const options: TarballOptions = { dests: [], - root: '' + root: '', + gz: false } const add = (meta: TarballFileMeta) => { @@ -73,7 +75,7 @@ export function createTarBall() { Object.assign(options, tarballOPtions) const promises = options.dests.map(dest => { - const expected = slash(path.resolve(options.root, dest + '.tar')) + const expected = slash(path.resolve(options.root, dest + '.tar' + (options.gz ? '.gz' : ''))) const parent = slash(path.dirname(expected)) if (options.root !== parent) { fs.mkdirSync(parent, { recursive: true }) @@ -83,6 +85,11 @@ export function createTarBall() { w.on('error', reject) w.on('finish', resolve) + + if (options.gz) { + pack.receiver.pipe(zlib.createGzip()).pipe(w) + return + } pack.receiver.pipe(w) }) }) diff --git a/src/index.ts b/src/index.ts index 8fcb4c3..c0b95fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,7 +88,7 @@ async function handleStaticFiles(config: ResolvedConfig, callback: (file: string } function tarball(opts: ViteTarballPluginOptions = {}): Plugin { - const { dest: userDest } = opts + const { dest: userDest, gz = false } = opts const statics: string[] = [] const outputs: string[] = [] let dests: string[] = [] @@ -115,7 +115,7 @@ function tarball(opts: ViteTarballPluginOptions = {}): Plugin { if (!plugin) throw new Error("[vite-plugin-tarball] can't be work in versions lower than vite at 2.0.0") // create dest dir - tarball.setup({ dests, root }) + tarball.setup({ dests, root, gz }) }, async writeBundle(_, bundles) { for (const fileName in bundles) { diff --git a/src/interface.ts b/src/interface.ts index 27e662f..e3ae2aa 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -1,3 +1,4 @@ +/* eslint-disable stylistic/indent */ import type { BrotliOptions, InputType, ZlibOptions } from 'zlib' import type { HookHandler, Plugin } from 'vite' import type { FilterPattern } from '@rollup/pluginutils' @@ -61,14 +62,15 @@ export type ViteCompressionPluginConfig = | ViteCompressionPluginConfigFunction> | ViteCompressionPluginConfigAlgorithm -export type ViteCompressionPluginOption = A extends undefined - ? Pretty - : A extends Algorithm ? Pretty> +export type ViteCompressionPluginOption = + A extends undefined ? Pretty + : A extends Algorithm ? Pretty> : A extends UserCompressionOptions ? Pretty>> - : never + : never export type GenerateBundle = HookHandler export interface ViteTarballPluginOptions { dest?: string + gz?: boolean } diff --git a/yarn.lock b/yarn.lock index 067c920..4e619c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5397,10 +5397,10 @@ __metadata: languageName: node linkType: hard -"tar-mini@npm:^0.1.1": - version: 0.1.1 - resolution: "tar-mini@npm:0.1.1" - checksum: 10/62f69990e6f6c0015653ec62ea271f5ed64e6ae6183ad17d5cfefc53ec5372a492c2c2096a9eac7af14c327ebe74cefd20e6a8a1bcdbbd30dd612273e33239d4 +"tar-mini@npm:^0.2.0": + version: 0.2.0 + resolution: "tar-mini@npm:0.2.0" + checksum: 10/56f1ff01196244c82bbc4a93a5cbb47a075efcbc6f2fdd11d64988fe3405f2660f5fd9bf08e06677e8c64648b7b253e2e38d7288957a199a97a33cee64f53606 languageName: node linkType: hard @@ -5721,7 +5721,7 @@ __metadata: rollup-plugin-dts: "npm:^6.1.1" rollup-plugin-swc3: "npm:^0.11.2" sirv: "npm:^2.0.3" - tar-mini: "npm:^0.1.1" + tar-mini: "npm:^0.2.0" typescript: "npm:^5.3.3" vite: "npm:^5.3.4" vitest: "npm:^2.0.3"