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

@dynamic-framework/vite-plugin-transform-dynamic-imports

v0.2.0

Published

Vite plugin that transforms dynamic imports to use runtime-configurable base paths for widget delivery

Readme

Dynamic Imports Vite Plugin

A Vite/Rollup plugin that transforms dynamic and static imports in built chunks to use a runtime-configurable base path. Useful when widget assets are hosted under per-widget URLs and need to resolve chunk paths at runtime (e.g., window['resourceBasePath-{{widget.wid}}']).

Features:

  • Rewrites import("./file.chunk.js") in entry chunks to prefix with a runtime base path.
  • Rewrites from "./main.js" inside chunk files to a templated URL for widget manager delivery.
  • SSR-safe window access using typeof guards.
  • Optional source map regeneration via MagicString.
  • Fully configurable via options.

Installation

Install as a dev dependency alongside Vite:

npm install -D @dynamic-framework/dynamic-imports-vite-plugin

Peer dependency: vite ^7.2.6

Quick Start

Add the plugin to your vite.config:

// vite.config.ts
import { defineConfig } from 'vite';
import transformDynamicImports from '@dynamic-framework/dynamic-imports-vite-plugin';

export default defineConfig({
  build: {
    // Ensure code-split chunks are produced
    rollupOptions: {
      // Your inputs/outputs as usual
    },
  },
  plugins: [
    transformDynamicImports({
      // optional configs shown below
    }),
  ],
});

How it works

During generateBundle, the plugin scans built chunks and applies two transformations:

  1. Entry chunks: import("./file.chunk.js") -> import(((typeof window !== 'undefined' && window) ? window['resourceBasePath-{{widget.wid}}'] : '') + "file.chunk.js").
  2. Chunk files: from "./main.js" -> from "{{site.url}}/widget_manager/{{widget.wid}}/{{widget.version}}.js".

Both patterns respect single, double, or backtick quotes and whitespace. The default entry chunk detection uses Rollup's chunk.isEntry.

Options

transformDynamicImports({
  // Builds window accessor for the runtime base path using the widget placeholder
  resourceBaseVar: (widPlaceholder) => `window['resourceBasePath-${widPlaceholder}']`,

  // Predicate to determine whether a chunk is treated as an entry (default: chunk.isEntry)
  entryNamePredicate: (chunk) => chunk.isEntry ?? false,

  // Regenerate source maps for transformed chunks
  enableSourceMap: false,

  // Placeholder inserted into resourceBaseVar
  widgetPlaceholder: '{{widget.wid}}',

  // Pattern to match code-split chunks (used in dynamic import detection)
  chunkFilePattern: '.chunk.js',

  // The entry file name referred by chunk files' static imports
  entryFileName: 'main.js',

  // URL template to replace static imports from main.js inside chunk files
  staticImportUrlTemplate: '{{site.url}}/widget_manager/{{widget.wid}}/{{widget.version}}.js',
});

Simple Example

Assume your app produces an entry chunk containing:

// in entry chunk
import('./users.chunk.js');

At runtime, define a global base path (e.g., per widget):

<script>
  window['resourceBasePath-{{widget.wid}}'] = 'https://cdn.example.com/widgets/123/';
</script>

The plugin turns the import into:

import(((typeof window !== 'undefined' && window) ? window['resourceBasePath-{{widget.wid}}'] : '') + 'users.chunk.js');

Practical Use Cases

  • Multi-tenant widgets: Serve chunks from tenant-specific base URLs or widget versions.
  • CMS-delivered widgets: Main file resolved via {{site.url}}/widget_manager/... while chunks load from runtime base.
  • SSR-capable builds: The plugin wraps window access with a typeof guard to avoid SSR crashes.

Requirements and Considerations

  • Code-splitting: Ensure Vite/Rollup generates chunk files (e.g., dynamic imports present and chunkFilePattern matches your chunk naming).
  • Chunk naming: Default matcher expects names ending with .chunk.js. If your output differs (e.g., -abc123.js), adjust chunkFilePattern.
  • Entry detection: Defaults to chunk.isEntry. If your build produces multiple entries or non-standard entries, provide entryNamePredicate.
  • Global variable: You must set the runtime base path variable before the entry chunk executes. By default: window['resourceBasePath-{{widget.wid}}'].
  • Static import rewrite: Only affects chunk files containing from "./main.js". If your main file name or path differs, update entryFileName.
  • Security: If the global base can be user-influenced, consider sanitization, path normalization, and CSP to prevent traversal/injection. The plugin includes a TODO comment for hardening.
  • Source maps: Set enableSourceMap: true if you need maps after transformation.
  • SSR: The transform uses typeof window !== 'undefined' to avoid errors, but on server-side it will prefix with an empty string, so dynamic chunk loading paths resolve to just the file name.

Testing

Run unit tests (if present):

npm run test

Build

npm run build

This produces the transformed plugin in dist/ with types.

License

MIT