Skip to content

Latest commit

 

History

History
149 lines (96 loc) · 6.88 KB

README.md

File metadata and controls

149 lines (96 loc) · 6.88 KB

µcompress

Build Status Coverage Status

compressed umbrellas

Social Media Photo by Kevin Borrill on Unsplash

A micro, all-in-one, compressor for common Web files, resolving automatically JavaScript imports, when these are static.

📣 Community Announcement

Please ask questions in the dedicated forum to help the community around this project grow ♥


As CLI

Due amount of dependencies, it's recommended to install this module via npm i -g ucompress. However you can try it via npx too.

# either npm i -g ucompress once, or ...
npx ucompress --help

If --source and --dest parameter are passed, it will do everything automatically.

ucompress --source ./src --dest ./public

Check other flags for extra optimizations, such as .json headers files and/or .br, .gzip, and .deflate versions, which you can serve via NodeJS or Express, using µcdn-utils.

As module

import ucompress from 'ucompress';
// const ucompress = require('ucompress');

// define or retrieve `source` and `dest as you like

// automatic extension => compression
ucompress(source, dest).then(dest => console.log(dest));

// explicit compression
ucompress.html(source, dest).then(dest => console.log(dest));

// handy fallback
ucompress.copy(source, dest).then(dest => console.log(dest));

Options

The optional third options object parameter can contain any of the following properties:

  • createFile, a boolean property, false by default, that will automatically pre-compress via brotli, gzip, and deflate, compatible files, plus it will create a .json file with pre-processed headers details per each file
  • maxWidth, an integer property, that if provided, it will reduce, if necessary, the destination image width when it comes to JPG or PNG files
  • maxHeight, an integer property, that if provided, it will reduce, if necessary, the destination image height when it comes to JPG or PNG files
  • preview, a boolean parameter, false by default, that creates JPG counter .preview.jpg files to be served instead of originals, enabling bandwidth saving, especially for very big pictures (example: with-preview)
  • noImport, a boolean parameter, false by default, that skips automatic ESM import resolution, in case the site provides imports maps by itself
  • noMinify, a boolean parameter, false by default, that keeps the .js, .css, and .html source intact, still performing other changes, such as .js imports

As Micro CDN

If you'd like to use this module to serve files CDN like, check µcdn out, it includes ucompress already, as explained in this post.

Compressions

Following the list of tools ued to optimized various files:

  • css files via csso
  • gif files via gifsicle as optional dependency
  • html files via html-minifier
  • jpg or jpeg files via sharp
  • js or mjs files via terser and html-minifier
  • json files are simply parsed and stringified so that white spaces get removed
  • md files are transformed into their .md.preview.html version, if the preview is enabled, through marked
  • png files via pngquant-bin
  • svg files via svgo
  • xml files via html-minifier

About Automatic Modules Resolution

If your modules are published as dual-module, or if you have a module field in your package.json, and it points at an ESM compatible file, as it should, or if you have a type field equal to module and a main that points at an ESM compatible, or if you have an exports field which import resolves to an ESM compatible module, µcompress will resolve that entry point automatically.

In every other case, the import will be left untouched, eventually warning in console when such import failed.

Dynamic imports are resolved in a very similar way, but composed imports will likely fail:

// these work if the module is found in the source path
// as example, inside source/node_modules
import 'module-a';
import('module-b').then(...);

// these work *only* if the file is in the source path
// but not within a module, as resolved modules are not
// copied over, only known imports, eventually, are
import(`/js/${strategy}.js`);

// these will *not* work
import(condition ? 'condition-thing' : 'another-thing');
import('a' + thing + '.js');

About ucompress.createHeaders(path[, headers])

This method creates headers for a specific file, or all files within a folder, excluding files that starts with a . dot, an _ underscore, or files within a node_modules folder (you know, that hole that should never fully land in production).

ucompress.createHeaders(
  // a folder with already optimized files
  '/path/static',
  // optional headers to set per folder
  {'Access-Control-Allow-Origin': '*'}
);

Brotli, Deflate, GZip, and Headers

If the third, optional object, contains a {createFile: true} flag, each file will automatically generate its own related .json file which includes a RFC-7232 compliant ETag, among other details such as last-modified, content-type, and content-length.

The following file extensions, available via the ucompress.encoded Set, will also create their .br, .deflate, and .gzip version in the destination folder, plus their own .json file, per each different compression, but only when {createFile: true} is passed.

  • .css
  • .html
  • .js
  • .mjs
  • .map
  • .json
  • .md
  • .svg
  • .txt
  • .woff2
  • .xml
  • .yml

Incompatible files will fallback as regular copy source into dest when the module is used as callback, without creating any optimized version, still providing headers when the flag is used.