Extremely fast JavaScript minifier, available for Rust and Node.js

Related tags

Utilities minify-js
Overview

minify-js

Extremely fast JavaScript minifier, written in Rust.

Goals

  • Fully written in Rust for maximum compatibility with Rust programs and derivatives (FFI, WASM, embedded, etc.).
  • Maximises performance on a single CPU core for simple efficient scaling and easy compatible integration.
  • Minification of individual inputs/files only; no bundling or transforming.
  • Prefer minimal complexity and faster performance over maximum configurability and minimal extra compression.

Performance

Comparison with esbuild, run on common libraries.

Chart showing speed of JS minifiersChart showing compression of JS minifiers

Features

  • Fast parsing powered by SIMD instructions and lookup tables.
  • Data is backed by a fast reusable bump allocation arena.
  • Supports JSX.
  • Analyses scopes and variable visibilities.
  • Minification of identifiers.
  • Omits semicolons, spaces, parentheses, and braces where possible.
  • Transforms functions to arrow functions when new, this, arguments, and prototype aren't used.
  • Moves repeated usages of constants to one shared variable.
  • Transforms if statements to expressions.

Usage

CLI

Precompiled binaries are available for Linux, macOS, and Windows.

Linux x64 | macOS x64 | Windows x64

Use the --help argument for more details.

minify-js --output /path/to/output.min.js /path/to/src.js

Rust

Add the dependency:

[dependencies]
minify-js = "0.5.6"

Call the method:

use minify_js::{Session, TopLevelMode, minify};

let mut code: &[u8] = b"const main = () => { let my_first_variable = 1; };";
let session = Session::new();
let mut out = Vec::new();
minify(&session, TopLevelMode::Global, code, &mut out).unwrap();
assert_eq!(out.as_slice(), b"const main=()=>{let a=1}");

Node.js

Install the dependency:

npm i @minify-js/node

Call the method:

import {minify} from "@minify-js/node";

const src = Buffer.from("let x = 1;", "utf-8");
const min = minify(src);

In progress

  • Combine and reorder declarations.
  • Evaluation and folding of constant expressions.
  • Parse and erase TypeScript syntax.
  • Removal of unreachable, unused, and redundant code.
  • Inlining single-use declarations.
  • Replacing if statements with conditional and logical expressions.
  • Returning an explicit error on illegal code e.g. multiple declarations/exports with identical names.
  • Much more inline, high level, and usage documentation.
  • Support import and export string names e.g. import { "a-b" as "c-d" } from "x".
  • Simplify pattern parsing and minification.
  • Micro-optimisations:
    • Unwrap string literal computed members, then identifier or number string members.
    • Replace x === null || x === undefined with x == null, where x is side-effect free.
    • Replace typeof x === "undefined" with x === undefined.
    • Using shorthand properties.
    • Replace void x with x, undefined.
    • Replace return undefined with return.
    • Replace const with let.
    • Hoist let and const.
    • Unwrapping blocks.
    • Unwrapping paretheses, altering expressions as necessary.
    • if (...) return a; else if (...) return b; else return c => return (...) ? a : (...) ? b : c.
Comments
  • Support for module imports and exports

    Support for module imports and exports

    Hey! I came across this project from a panic stacktrace I got when trying to use https://github.com/adamchainz/django-minify-html. Following that, I found that import and the different variants of export statements are still left as todo!(): https://github.com/wilsonzlin/minify-js/blob/eb27a22535a3bbef7c568a597bb7e470f1bc3797/rust/src/emit/mod.rs#L795

    I wanted to ask whether support for these statements is planned anytime soon. Are there any particular problems, or has just no one come around to implementing it yet? In that case, I could also try to file a PR myself, it may take some time though. Until then, I already found the option to disable js minification when using minify-html

    Looking forward to using your library. Thanks!

    opened by niklasmohrin 7
  • 'failed to find top-level export `initSync`'

    'failed to find top-level export `initSync`'

    Having trouble parsing wasm-bindgen output again, this time it's about exports. File in question:

    https://gist.github.com/Carlrs/67035c2639f0df5d4eca13e47f64a2ea

    opened by Carlrs 4
  • fails to minify lambda with parenthesis

    fails to minify lambda with parenthesis

    The algorithm is removing the parenthesis on lambda expressions. It breaks the code in some cases.

    For instance :

    let fns = [ x => (1, 2) ]

    is compressed as

    let fns = [ x => 1, 2 ]

    The original code creates an array with a single function returning 2. The compressed code creates an array with a lambda returning 1 and with an additional entry 2.

    opened by florentbr 2
  • Feature Request : macro to embed js inside binaries

    Feature Request : macro to embed js inside binaries

    Nice lib.

    I would like to suggest the addition of a new feature:

    What about creating a macro, such as minify!(...), so we can embed js inside the binaries. With this feature we will be able to use it with projects such as Tauri, and web servers.

    It could use something like include_bytes!, and include_str!.

    Thanks.

    opened by felipetesc 1
  • Unable to recognize arrow function IIFE

    Unable to recognize arrow function IIFE

    https://developer.mozilla.org/en-US/docs/Glossary/IIFE

    (function () {
      let foo = 'bar';
    })();
    
    (() => {
      let foo = 'bar';
    })();
    
    (async () => {
      let foo = 'bar';
    })();
    
    (function(){let a='bar'})();()=>{let a='bar'}();async()=>{let a='bar'}()
    
    Uncaught SyntaxError: unexpected token: '('      debugger eval code:1:45
    

    Should be:

    (function(){let a='bar'})();(()=>{let a='bar'})();(async()=>{let a='bar'})()
    //                          ^                 ^   ^                      ^
    
    opened by Rongronggg9 1
  • Crash on parsing private methods

    Crash on parsing private methods

    This minimal code:

    class Foo {
       #Bar() {
          console.log("Compress me!");
       }
    }
    

    outputs this error: thread 'main' panicked at 'minify: Syntax(ExpectedNotFound [position=16 token=None] around ```class Foo { #Bar() { console.log("Compress m```)', cli\src\main.rs:33:41

    opened by KacperZielinski-Intel 1
  • Unable to parse `for await...of`

    Unable to parse `for await...of`

    Trying to minify

    for await (const chunk of stream) {
      // ...
    }
    

    results in

    Error: RequiredTokenNotFound(ParenthesisOpen) [token=Some(KeywordAwait)] around ```await```
    
    opened by samueledellavedova 0
  • Unable to parse tagged template

    Unable to parse tagged template

    I get an error trying to minify a tagged template literal.

    // tagged_template.js 
    const noop = (raw, ...keys) => keys.length === 0 ? raw[0] : String.raw({ raw }, ...keys)
    template = noop`a`
    console.log(template)
    
    $ ./minify-js --mode global tagged_template.js 
    thread 'main' panicked at 'minify: ExpectedSyntax("expression operator") [token=Some(LiteralTemplatePartStringEnd)] around ```a```', cli/src/main.rs:38:52
    

    I get the same error with other examples at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates.

    opened by migonzalvar 0
  • Failed to parse the

    Failed to parse the "import" function

    import('file.js');
    

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import

    import can be used with a function syntax instead of a keyword. For both Global and Module, it results in the parse error result:

    Error: RequiredTokenNotFound(ParenthesisClose) [token=Some(Semicolon)] around ```;```
    
    opened by sgkoishi 0
  • Added to minification-benchmarks

    Added to minification-benchmarks

    Hey, just wanted to give you a heads up that we started benchmarking your minifier here: https://github.com/privatenumber/minification-benchmarks

    Thanks for your project and good luck!

    opened by privatenumber 2
  • Avoid panic on `export` of top-level variable when used in global mode

    Avoid panic on `export` of top-level variable when used in global mode

    In global mode, top-level variables are not added to any scope, so a statement like export a or export { a } will panic due to not finding the symbol if accidentally invoked with TopLevelMode::Global instead of TopLevelMode::Module.

    opened by wilsonzlin 1
Owner
Wilson Lin
Wilson Lin
A list of publicly available STUN servers, refreshed every hour.

Always Online: STUN servers Have you ever thought: Gosh, why isn't there a regularly updated, comprehensive list of publicly available STUN servers? W

null 210 Dec 30, 2022
Github mirror of codeberg repo. Monitor live bandwidth usage/ network speed on PC. Native version also available for Android, separately.

Netspeed Monitor Netspeed is a cross-platform desktop application that shows the live upload speed, download speed and day's usage as an overlay. Feat

Vishnu N K 16 May 3, 2023
Blazing fast linter for JavaScript and TypeScript written in Rust

deno_lint A Rust crate for writing fast JavaScript and TypeScript linters. This crate powers deno lint, but is not Deno specific and can be used to wr

Deno Land 1.3k Dec 29, 2022
An n-tuple pendulum simulator in Rust + WebAssembly (and JavaScript)

An n-tuple pendulum simulator in Rust + WebAssembly (and JavaScript) Remaking this n-tuple pendulum simulator moving the math to Rust ?? and WebAssemb

Travis Taylor 27 Feb 19, 2022
Adapter plugin to use Ruff in dprint's CLI and with JavaScript via Wasm

dprint-plugin-ruff Adapter for Ruff for use as a formatting plugin in dprint. Formats .py and .pyi files. Note: For formatting .ipynb files, use the J

null 3 Nov 28, 2023
🎓 My journey from JavaScript to Rust

Rusty Days My journey from JavaScript to Rust I'm a web3 dev looking for higher performance. Enticed that Rust was voted the most loved programming la

Dawson Botsford 19 Apr 17, 2022
Node/Electron library for global key listening.

GlobalKey Building cargo install nj-cli nj-cli build --release Calling from node npm i globalkey # or yarn add globalkey const globalkey = require(

Will 20 Dec 15, 2022
notify Node.js binding via napi-rs.

@napi-rs/notify notify Node.js binding via napi-rs. Install this package yarn add

LongYinan 9 Jun 6, 2022
swc node binding use wasm

node_swc swc node binding use wasm Build Make sure you have rust wasm-pack installed. $ yarn build # build wasm, node Usage import { parseSync, printS

伊撒尔 23 Sep 8, 2022
Another attempt at creating a wrapper for fastcdc in node.js

Another attempt at creating a wrapper for fastcdc in node.js. This time using wasmbindgen instead of neon.

Mikola Lysenko 5 Jul 28, 2022
A fresh FRAME-based Substrate node, ready for hacking

A substrate-based chain that runs in a single node, but simulates the existence of a large set of validators and nominators.

Kian Paimani 3 Aug 24, 2022
Pegasus: A Multi-Node Command Runner

Run a list of commands on a set of SSH nodes. With a bit of optional parametrization.

Jae-Won Chung 19 Dec 7, 2022
Node.js bindings for feed_rs

Description Node.js bindings for feed_rs. Installation npm install @nooptoday/feed-rs Usage import { parse } from '@nooptoday/feed-rs' const response

null 5 Nov 17, 2023
Fusion is a cross-platform App Dev ToolKit build on Rust . Fusion lets you create Beautiful and Fast apps for mobile and desktop platform.

Fusion is a cross-platform App Dev ToolKit build on Rust . Fusion lets you create Beautiful and Fast apps for mobile and desktop platform.

Fusion 1 Oct 19, 2021
⚡️ Fast MagicString port driven by Rust and N-API

magic-string-rs 100% API compatible (port) MagicString by Rich-Harris implementation for Node and modern browsers, also, for rust, of course. Installa

Hana 35 Nov 21, 2022
Fast, compact and all-around subdomain enumeration tool written in Rust

Fast, compact and all-around subdomain enumeration tool written in Rust, which uses dns bruteforce, internet search and recursive http content search.

foreseon 16 Dec 10, 2022
Czkawka is a simple, fast and easy to use app to remove unnecessary files from your computer.

Multi functional app to find duplicates, empty folders, similar images etc.

Rafał Mikrut 9.2k Jan 4, 2023
Fast, initializable, and thread safe static variables

tagged_cell Fast, initializable, and thread safe static variables Overview Borrows the excellent ZST based tagging implementation (linked below) to gu

David Schwarz 8 Nov 10, 2022
Simple and fast git helper functions

Simple and fast git helper functions

LongYinan 126 Dec 11, 2022