archive-creator
Packs every file of the stream into one zip, tar or tar.gz archive with archiver and emits only the archive. Entries keep their paths relative to file.base, and their modification time and mode when the files came from disk. The archive is built in memory.
npm install --save-dev @zilero/gulp-archive-creatorUsage
import { dest, src } from 'gulp';
import archiveCreator from '@zilero/gulp-archive-creator';
export const release = () =>
src('dist/**', { encoding: false })
.pipe(archiveCreator({ name: 'site.zip' }))
.pipe(dest('releases'));The format comes from the name, or from format:
archiveCreator({ name: 'site.tar.gz' }); // tgz, from the extension
archiveCreator({ name: 'releases/site', format: 'tgz' }); // releases/site.tar.gz
archiveCreator({ name: 'site.zip', archiverOptions: { zlib: { level: 9 } } }); // passed to archiverOptions
| Option | Type | Default | Description |
|---|---|---|---|
name | string | 'archive' | The archive's path relative to the output folder: site.zip, releases/site.tar.gz. Without an extension the format's own is added. |
format | 'zip' | 'tar' | 'tgz' | from name | Inferred from the extension of name (.zip, .tar, .tgz, .tar.gz), else zip. When both are given they must agree. |
archiverOptions | ZipOptions & TarOptions | — | Passed to archiver: zlib.level or store for zip, gzipOptions for tgz. Must be an object (Expected an object). |
emptyArchive | boolean | false | Emit an empty archive when the stream had no files. By default nothing is emitted. |
directories | boolean | false | Add an entry for each directory in the stream (src('**') without nodir). |
modifiedTime | Date | — | The modification time of every entry, for reproducible archives. Default: each file's stat.mtime, else 1980-01-01. |
All options are optional, and unknown keys are an error. name must stay inside the output folder: an absolute path or one that leaves it, such as '../site.zip', is an error (Expected a path inside the output folder). So is a format that contradicts the extension of name: { name: 'a.zip', format: 'tar' } throws a.zip is a zip name, but format is tar: change one of them or drop format. Options are checked when the plugin is created.
The package also exports the types ArchiveCreatorOptions, ArchiveFormat and ArchiverOptions.
Notes
- Read files with
src(…, { encoding: false }): gulp 5 reads files as UTF-8 by default, which breaks images, fonts and other binary files. - The archive is placed relative to the
baseof the first file, sodest('releases')writesreleases/site.zip. formatis useful with a name without a known extension ({ name: 'releases/site', format: 'tgz' }writesreleases/site.tar.gz); with a known extension it must agree with it. Extensions are matched case-insensitively.- The archive is built in memory: every entry is compressed into a Buffer that is emitted at the end of the stream, so the archive must fit in memory. Streamed contents (
buffer: false) are read entry by entry, but the result is still one Buffer. - Files read with
buffer: falseare archived from their stream. - Files without contents that are not directories (
read: false, symbolic links) are skipped. Directories are skipped too unlessdirectoriesis set. Withdirectories, the base folder itself (src('dist')matchesdistwith an empty relative path) gets no entry, since it has no path inside the archive. - An error while reading streamed contents, or an error from archiver, fails the task with a
PluginErrornamed after this plugin; it is reported on the next file or at the end of the stream, and the process does not crash. archiver's warnings (a missing file, for example) fail the archive the same way rather than being ignored. After a failure, archiver is aborted, so the remaining entries are not read. - An empty stream emits nothing unless
emptyArchiveis set; the empty archive is then named relative to the current folder.
Reproducible archives
The same files give the same archive on every build, byte for byte, as long as the dates are stable:
- files read from disk keep their
stat.mtime, so they change the archive only when they change; - files without a stat (made by other plugins, such as a concatenated bundle) get a fixed 1980-01-01, the earliest date zip can store, instead of the time of the build;
modifiedTimegives every entry the same date, ignoringstat.mtime, for archives that depend only on the contents (CI builds from a fresh checkout, where every mtime is the checkout time).
zip stores dates in local time, so a zip is reproducible across machines in the same time zone; tar stores UTC.
archiveCreator({ name: 'site.tar.gz', modifiedTime: new Date('2026-01-01T00:00:00Z') });Migrating
From gulp-zip, gulp-tar and gulp-gzip
| gulp-zip, gulp-tar + gulp-gzip | archive-creator |
|---|---|
zip('site.zip') | archiveCreator({ name: 'site.zip' }) |
zip(name, { compress: false }) | archiverOptions: { store: true } |
zip(name, { modifiedTime }) | modifiedTime |
zip(name, { buffer: false }) | not needed: the archive is one Buffer |
tar('site.tar'), then gzip() | archiveCreator({ name: 'site.tar.gz' }) |
From 1.x
- Options are flat:
{ name, format, archiverOptions, emptyArchive, directories }instead offormat,archiveOptionsandpluginOptions: { archiveName, createDirectory, createEmptyArchive }. formatis no longer required: it is inferred from the extension ofname.- tar.gz (
tgz) is supported. - archiver 8 is used, streamed contents are supported and entries keep their modification time and mode.
- After 2.0.0:
modifiedTimeis new, files without a stat get a fixed date instead of the build time, and aformatthat contradicts the extension ofnameis an error (2.0.0 wrote a tar nameda.zip).
See migrating from 1.x for every package.