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 🙏

© 2025 – Pkg Stats / Ryan Hefner

obfuscator-webpack-plugin

v1.0.0

Published

Webpack plugin that obfuscates JavaScript code using javascript-obfuscator.

Readme

obfuscator-webpack-plugin

A webpack plugin for obfuscating JavaScript code using javascript-obfuscator.

Overview

This plugin differs from the first-party webpack-obfuscator plugin in the following ways:

  • Obfuscation can be done in the optimization phase instead of the emit phase, this allows running the obfuscator on the final optimized assets.
  • Obfuscated identifier names cache is consistent across the chunks, to reduce the chance of breaking code.
  • Automatic configuration of the obfuscator for Node.js and browser environments with sensible defaults for each that reduce the chance of breaking code.
  • Initial reserved-keywords preset to reduce the chance of breaking code by default.
  • Custom pre and post hooks for allowing customization of the obfuscation process per chunk.
  • Custom done hook for allowing post-processing of the obfuscated assets and shared identifier names cache.
  • Indicators in the webpack stats output to show which assets were obfuscated, for fast visual inspection.

Installation

To install the plugin, you can use npm or another package manager. Make sure to install the obfuscator package as well.

npm install -D javascript-obfuscator obfuscator-webpack-plugin

Usage

Add the plugin to the optimization.minimizer array in the webpack configuration:

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin(),
    ],
  },
};

Options

The plugin accepts an options object with the following properties:

  • assumptions:
    • csp (boolean): Indicates whether Content Security Policy is enabled.
    • hmr (boolean): Indicates whether Hot Module Replacement is enabled.
    • nodeEnv (string): Specifies the target environment mode (development/production).
    • target (string): Specifies the target environment (browser/node).
  • cache (boolean): Indicates whether to enable caching of the obfuscated code.
  • exclude ((RegExp | string)[]): An array of regular expressions to exclude assets from obfuscation.
  • options (object): The options object to pass to the obfuscator.
  • setupHooks (function): A function to register hooks for customizing the process.
  • stage (number): Stage at which the plugin will be run (default: PROCESS_ASSETS_STAGE_DEV_TOOLING).
  • test ((RegExp | string)[]): An array of regular expressions to include assets for obfuscation (default: /\.[cm]?js[x]?(?:\?.*)?$/iu).

See the javascript-obfuscator documentation for more information on the options.

This example demonstrates how to specify the obfuscator options:

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

const domain = "example.com";
const domainLockRedirectUrl = `https://${domain}`;

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin({
        options: {
          domainLock: [domain],
          domainLockRedirectUrl,
        },
      }),
    ],
  },
};

See the following sections for more information on the options.

Assumptions

The plugin attempts to make intelligent decisions about how to obfuscate the code, but it may not always make the best choices. The following sections describe the assumptions the plugin makes and how to override them.

Content Security Policy (CSP)

When the target option is not defined explicitly and the plugin detects that the target is a browser environment, it also checks that if a trusted-types policy is specified in the webpack configuration. If so, the plugin configures the obfuscator to generate code that does not contain eval calls.

This behavior can be overridden by setting one of the csp or target assumptions explicitly.

Hot Module Replacement (HMR)

Unless the cache option is defined explicitly, the plugin enables the caching of the obfuscated codes to reduce build times if the plugin detects that HMR is enabled.

This behavior can be overridden by setting the hmr assumption explicitly.

Node environment

The plugin tries to determine if the NODE_ENV is development or production based on the webpack configuration.

  • If the mode is set in the configuration, the plugin uses that value to determine the mode.
  • If the optimization.nodeEnv is set, the plugin uses that value as the fallback.
  • If neither is set, the plugin defaults to process.env.NODE_ENV || "development".

This behavior can be overridden by setting the nodeEnv assumption explicitly.

Target environment

If the target option is not defined explicitly in the obfuscator options, the plugin tries to determine the target environment based on the webpack configuration, aiming to define sensible defaults for the obfuscator accordingly, to reduce the chance of breaking code.

The plugin assumes that the target is a browser environment if one of the following is true:

  • target key in the webpack configuration is set to either web or webworker.
  • Either web or webAsync flag in the externalsPresets webpack configuration is set to true.

The plugin assumes that the target is a Node.js environment if one of the following is true:

  • target key in the webpack configuration is set to node.
  • One of the node, electron, electronMain, electronPreload, electronRenderer, nwjs flags in the externalsPresets webpack configuration is set to true.

If none of the above conditions are met, before defaulting to browser target, the plugin checks if any browserslist query is provided in the webpack configuration. If exists, the plugin evaluates the query to determine the target environments. If the results contain node, the plugin chooses node as the target. Otherwise, the choosen value is browser.

The target assumption can be overridden manually if necessary.

Here is an example of how to override the assumptions:

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin({
        assumptions: {
          csp: true,
          hmr: false,
          nodeEnv: "production",
          target: "browser-no-eval",
        },
      }),
    ],
  },
};

Cache

Enabling the cache can reduce build times by reusing the obfuscated code from the previous build. By default, unless the hmr assumption is set to true, the cache option is disabled.

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin({
        cache: true,
      }),
    ],
  },
};

Excluding assets

To exclude assets from obfuscation, the exclude option can be set to an array of regular expressions that match the asset names.

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin({
        exclude: [
          /\.no-obfuscation\.js$/i,
        ]
      }),
    ],
  },
};

Setting up hooks

The plugin provides custom hooks for customizing the obfuscation process per chunk. The setupHooks option can be used to register hooks for customizing the process.

The setupHooks function receives two arguments:

  • compilation (object): The webpack compilation object.
  • hooks (object): An object containing the hooks.

The hooks object contains the following properties:

  • preObfuscation: A tapable hook that is called before obfuscation.
  • postObfuscation: A tapable hook that is called after obfuscation.
  • done: A tapable hook that is called after all assets are obfuscated.

Note: Because of that each compilation will have its own set of hooks, the provided setupHooks function will be called for each compilation.

The following example demonstrates how to use the setupHooks option:

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new ObfuscatorPlugin({
        setupHooks(
          compilation,
          hooks,
        )
        {
          hooks.preObfuscation.tap(
            // Handler name can be anything,
            // just keep it unique per hook type to avoid conflicts.
            "pre-obfuscation-handler-1",
            (
              assetName,
              obfuscatorOptions,
            ) =>
            {
              // Pre-process the obfuscator options.
              // E.g., customize them per asset.
              obfuscatorOptions.renameGlobals = true;
            },
          );

          hooks.postObfuscation.tap(
            "post-obfuscation-handler-1",
            (
              assetName,
              source,
              sharedIdentifierNamesCache,
            ) =>
            {
              // Post-process the obfuscated source.
            },
          );

          hooks.done.tap(
            "done-handler-1",
            (sharedIdentifierNamesCache) =>
            {
              // Post-process all the obfuscated assets or shared identifier names cache.
              // E.g., dump the shared identifier names cache to a file or memory,
              // then re-use it in the next build by reading it back and passing it
              // to the plugin.
              compilation.emitAsset(
                "identifier-names-cache.json",
                new compilation.compiler.webpack.sources.RawSource(
                  JSON.stringify(
                    sharedIdentifierNamesCache,
                    null,
                    2,
                  ),
                ),
              );
            },
          );
        },
      }),
    ],
  },
};

Accessing hooks from other plugins

ObfuscatorPlugin class provides a public method named as setupHooks that can be used to access the hooks from other plugins.

By design, to avoid memory leaks and other similar issues, the hooks cannot be accessed directly from the plugin instance. Because the hooks are created per compilation, and they are not stored in the scope of the plugin instance, intentionally. The same is also true for the current compilation object. So, it is necessary to pass the current compilation object to the setupHooks method in order to access the corresponding hooks.

For example, in your plugin's apply method, you can access the hooks like this:

apply(
  compiler,
)
{
  compiler.hooks.compilation.tap(
    PLUGIN_NAME,
    (compilation) =>
    {
      const obfuscatorPlugin = compilation.options.plugins.find(
        (plugin) =>
        {
          return plugin instanceof ObfuscatorPlugin;
        },
      );

      obfuscatorPlugin.setupHooks(
        compilation,
        (hooks) =>
        {
          // Use the hooks here.
        },
      );
    },
  );
}

Using with other minimizers

The plugin can be used in conjunction with other minimizers, such as Terser Plugin.

Example:

const ObfuscatorPlugin = require("obfuscator-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin(),
      new ObfuscatorPlugin(),
    ],
  },
};

Examples

The e2e directory in the repository contain sample packages that use the plugin. As a more sophisticated example, e2e/apps/nextjs basically demonstrates how to use the plugin with a Next.js application where both the server and client code are obfuscated.

Troubleshooting

The plugin may not work out of the box for all projects. If the obfuscator cannot obfuscate the code, the plugin cannot do much about it neither.

If you encounter issues, it could be likely due to the wild nature of the obfuscation in a dynamic language like JavaScript. For a solution, you may consider the following steps:

  • Tune the obfuscator options to see if that resolves the issue.
  • Write your code in a way that is more obfuscation-friendly.
  • Disable options that are causing the issue.

Hints: It is recommended to keep the renameGlobals and renameProperties options as false unless you are sure that the code can handle the renaming of the global variables and properties. You may try setting transformObjectKeys to true, since it is less likely to break the code. However, no guarantees can be given here.

License

This project is licensed under the MIT License.

See the LICENSE file for more information.