npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-v8-bytecode

v1.0.0

Published

A Vite plugin for compiling JavaScript to V8 bytecode for Node.js and Electron applications

Readme

vite-plugin-v8-bytecode

npm version npm downloads

Compile selected Vite CommonJS chunks into runnable V8 cached data for Node.js and Electron. The plugin uses the target runtime and generates the loader and entry shims required to execute the result.

Features

  • No readable copy by default: Remove the original JavaScript and source maps for compiled chunks, or keep them when needed for debugging.
  • Automatic loading: Generate the bytecode loader and entry shims needed to run compiled chunks.
  • Node.js and Electron support: Compile cached data with the runtime that will execute it.
  • Selective compilation: Compile every generated chunk or select chunks by alias.
  • Optional string obfuscation: Prevent selected literals from appearing in basic plaintext scans.
  • Unchanged development workflow: Skip bytecode compilation outside production builds.
  • No package dependencies: Reuse Vite's parser instead of installing separate parsing and source-editing libraries.

Installation

npm install --save-dev vite-plugin-v8-bytecode

Node Usage

Add the plugin to your vite.config.ts:

import { defineConfig } from "vite";
import { bytecodePlugin } from "vite-plugin-v8-bytecode";

export default defineConfig({
  plugins: [bytecodePlugin()],
});

For a standard single-output build, the plugin selects CommonJS automatically when no output format is configured.

Electron Usage

Add the plugin to your vite.config.ts:

import { defineConfig } from "electron-vite";
import { bytecodePlugin } from "vite-plugin-v8-bytecode";

export default defineConfig({
  main: {
    plugins: [bytecodePlugin({ runtime: "electron" })],
  },
});

electron-vite supplies the required main-process build defaults automatically.

When calling Vite directly, configure it for an Electron main-process build:

import { builtinModules } from "node:module";
import { defineConfig } from "vite";
import { bytecodePlugin } from "vite-plugin-v8-bytecode";

export default defineConfig({
  plugins: [bytecodePlugin({ runtime: "electron" })],
  // Raw Vite builds use browser-oriented defaults. Preserve runtime access to
  // environment variables instead of replacing process.env with an empty object.
  define: {
    "process.env": "process.env",
    "global.process.env": "global.process.env",
    "globalThis.process.env": "globalThis.process.env",
  },
  build: {
    rollupOptions: {
      // Leave Electron and Node builtins for the main process to resolve.
      external: (id) =>
        id === "electron" ||
        id.startsWith("electron/") ||
        id.startsWith("node:") ||
        builtinModules.includes(id),
    },
  },
});

The define and external settings preserve runtime process.env access and leave Electron and Node builtins for the main process to resolve. Without them, a client-oriented Vite build [externalizes Node builtins for browser compatibility][vite-node-builtins]. The resulting failure occurs inside the compiled .cjsc, which can make a bundler configuration problem look like a bytecode problem. Do not replace process.env with JSON.stringify(process.env), which would embed the build machine's environment and potentially its secrets in the bundle.

Keep these Electron constraints in mind:

  • Build for each target: Generate bytecode separately for every target platform and CPU architecture, using the same Electron version as the packaged application. V8 cached data is not reliably portable between them.
  • Main process only: Bytecode cannot be used for renderer or preload code:
    • The plugin detects Vite's renderer configuration and disables itself, leaving renderer bundles as ordinary JavaScript.
    • Preload scripts cannot load bytecode. Sandboxed preloads cannot reach the generated loader, while unsandboxed preloads run in the renderer process, where V8 rejects cached data produced by the main process.

Configuration

Selective Compilation

Compile only specific chunks:

bytecodePlugin({
  chunkAlias: ["index", "main"], // Only compile these chunks
});

String Obfuscation

Prevent selected ordinary string literals from appearing verbatim in generated bytecode:

bytecodePlugin({
  obfuscatedStrings: ["internal-protocol-v1", "diagnostic-marker"],
});

Eligible exact matches in obfuscatedStrings are converted to String.fromCharCode() calls before bytecode compilation. This defeats a casual plaintext scan of the bytecode file, but it is reversible obfuscation, not encryption or secret storage. Anyone who can inspect or execute the application can recover the value.

Never use this option for API keys, access tokens, passwords, private keys, connection strings, or other credentials. Supply server-side secrets at runtime through environment variables or a secrets manager. A distributed Electron application cannot safely contain a secret that its users must not recover.

String obfuscation also has deliberate limits:

  • It handles matching ordinary string literals and static untagged template literals. Module paths, property and method keys, computed member properties, and tagged templates are left unchanged where rewriting could affect program behavior.
  • Other strings, identifiers, and metadata can remain visible in the bytecode.
  • Reconstruction happens whenever the transformed expression is evaluated. A few module-level values are inexpensive, but large values or literals in hot functions add bytecode size, allocations, and runtime work.

Limitations

  • CommonJS only: The plugin only supports CommonJS output. ES modules cannot be compiled to bytecode.
  • Production only: The plugin is disabled when NODE_ENV !== "production".
  • Function source is unavailable: Function.prototype.toString() cannot recover the original source of functions loaded from bytecode. Libraries that inspect or recompile functions from their source may not work.
  • Runtime-specific bytecode: Node and Electron bytecode are not interchangeable. Electron applications use runtime: "electron" and do not need a separate Node bytecode build. Node applications use the default runtime and must be built with the Node version that will execute the output.

Security Limits

Bytecode distribution can discourage casual source inspection, but it does not create a security boundary:

  • Not encryption: V8 cached data can be inspected and analyzed with V8-aware tooling.
  • Assume host control: A user who controls the machine running a Node or Electron application can inspect its files and instrument its runtime behavior.

License

MIT