Optimization

Bundle analysis and performance optimization

Optimization

Packem ships several built-in mechanisms for keeping bundles small and fast: minification, tree shaking, and bundle analysis. This guide covers how to enable each one.

Minification

The minify option toggles minification of the JavaScript output:

import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'

export default defineConfig({
  transformer,
  minify: true,
})

Or from the command line:

packem build --minify

When --minify is passed and --sourcemap is not specified, source maps are enabled by default. When building with --production (or NODE_ENV=production), minification is enabled automatically.

Condition-driven minification

If your package.json defines production and development export conditions, Packem minifies the matching outputs automatically:

  • A file ending in *.production.* for the production condition is minified.
  • A file ending in *.development.* for the development condition is not minified.
{
  "exports": {
    "development": "./dist/index.development.mjs",
    "production": "./dist/index.production.mjs"
  }
}

See Multi-Runtime for the full conditional-exports behavior and the Minify option for details.

Tree shaking

Dead-code elimination is handled by Rollup. You can tune its behavior with rollup.treeshake, which is passed straight through to Rollup's treeshake option:

export default defineConfig({
  transformer,
  rollup: {
    treeshake: {
      moduleSideEffects: 'no-external',
      propertyReadSideEffects: false,
    },
  },
})

Marking your package as side-effect free in package.json lets consumers' bundlers shake it harder:

{
  "sideEffects": false
}

Removing dead code with environment variables

Pass compile-time environment variables with the --env flag. Packem replaces matching references and lets Rollup strip the now-unreachable branches:

packem build --env.NODE_ENV=production

This replaces process.env.NODE_ENV with 'production' and removes the code guarded by other values.

Bundle analysis

Pass --analyze to generate a visual report of your bundle makeup as packem-bundle-analyze.html:

packem build --analyze

The report includes gzip and brotli sizes for each module. You can also set the option in config:

export default defineConfig({
  transformer,
  analyze: true,
})

--analyze enables source maps so the analyzer can attribute bytes accurately.

Metafile

For machine-readable build metadata, pass --metafile. Packem writes a JSON file per bundle (for example metafile-<name>-cjs.json and metafile-<name>-es.json) that you can feed to analysis tools such as bundle buddy:

packem build --metafile

Unbundle mode

For some libraries, preserving the source file structure (one output file per module) produces better tree shaking for consumers than a single bundled file. Enable it with unbundle:

export default defineConfig({
  transformer,
  unbundle: true,
})

Or via the CLI:

packem build --unbundle

See Unbundle for details.

Next steps

Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues