diff --git a/CHANGELOG.md b/CHANGELOG.md
index 457280c245f264d6cb8d8bd8f71081f29b404a9c..8ca74f04d64f98014e4ac25d0b8327d3ef1e6ea6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Fix camera project/unproject when using offset viewport
 - Add support for loading all blocks from a mmcif file as a trajectory
 - Add `Frustum3D` and `Plane3D` math primitives
+- Remove LazyImports (introduced in v3.31.1)
 
 ## [v3.32.0] - 2023-03-20
 
diff --git a/src/examples/image-renderer/index.ts b/src/examples/image-renderer/index.ts
index a4f6961115f7176edac416948bf8e2c924a986f0..ba5b1876b898f9b99b63861223241368d0013254 100644
--- a/src/examples/image-renderer/index.ts
+++ b/src/examples/image-renderer/index.ts
@@ -12,13 +12,16 @@
 import { ArgumentParser } from 'argparse';
 import fs from 'fs';
 import path from 'path';
+import gl from 'gl';
+import pngjs from 'pngjs';
+import jpegjs from 'jpeg-js';
 
 import { Download, ParseCif } from '../../mol-plugin-state/transforms/data';
 import { ModelFromTrajectory, StructureComponent, StructureFromModel, TrajectoryFromMmCif } from '../../mol-plugin-state/transforms/model';
 import { StructureRepresentation3D } from '../../mol-plugin-state/transforms/representation';
 import { HeadlessPluginContext } from '../../mol-plugin/headless-plugin-context';
 import { DefaultPluginSpec } from '../../mol-plugin/spec';
-import { STYLIZED_POSTPROCESSING } from '../../mol-plugin/util/headless-screenshot';
+import { ExternalModules, STYLIZED_POSTPROCESSING } from '../../mol-plugin/util/headless-screenshot';
 import { setFSModule } from '../../mol-util/data-source';
 
 
@@ -45,7 +48,8 @@ async function main() {
     console.log('Outputs:', args.outDirectory);
 
     // Create a headless plugin
-    const plugin = new HeadlessPluginContext(DefaultPluginSpec(), { width: 800, height: 800 });
+    const externalModules: ExternalModules = { gl, pngjs, 'jpeg-js': jpegjs };
+    const plugin = new HeadlessPluginContext(externalModules, DefaultPluginSpec(), { width: 800, height: 800 });
     await plugin.init();
 
     // Download and visualize data in the plugin
diff --git a/src/mol-plugin/headless-plugin-context.ts b/src/mol-plugin/headless-plugin-context.ts
index 0d547a13425f47726caf49e1697f603958cfc6a8..151a3d76f8db9529a8895556161f69a3d8e92b7c 100644
--- a/src/mol-plugin/headless-plugin-context.ts
+++ b/src/mol-plugin/headless-plugin-context.ts
@@ -5,33 +5,55 @@
  */
 
 import fs from 'fs';
+import { type PNG } from 'pngjs'; // Only import type here, the actual import must be provided by the caller
+import { type BufferRet as JpegBufferRet } from 'jpeg-js'; // Only import type here, the actual import must be provided by the caller
+
 import { Canvas3D } from '../mol-canvas3d/canvas3d';
 import { PostprocessingProps } from '../mol-canvas3d/passes/postprocessing';
 import { PluginContext } from './context';
 import { PluginSpec } from './spec';
-import { HeadlessScreenshotHelper, HeadlessScreenshotHelperOptions } from './util/headless-screenshot';
+import { HeadlessScreenshotHelper, HeadlessScreenshotHelperOptions, ExternalModules, RawImageData } from './util/headless-screenshot';
 
 
 /** PluginContext that can be used in Node.js (without DOM) */
 export class HeadlessPluginContext extends PluginContext {
     renderer: HeadlessScreenshotHelper;
 
-    constructor(spec: PluginSpec, canvasSize: { width: number, height: number } = { width: 640, height: 480 }, rendererOptions?: HeadlessScreenshotHelperOptions) {
+    /** External modules (`gl` and optionally `pngjs` and `jpeg-js`) must be provided to the constructor (this is to avoid Mol* being dependent on these packages which are only used here) */
+    constructor(externalModules: ExternalModules, spec: PluginSpec, canvasSize: { width: number, height: number } = { width: 640, height: 480 }, rendererOptions?: HeadlessScreenshotHelperOptions) {
         super(spec);
-        this.renderer = new HeadlessScreenshotHelper(canvasSize, undefined, rendererOptions);
+        this.renderer = new HeadlessScreenshotHelper(externalModules, canvasSize, undefined, rendererOptions);
         (this.canvas3d as Canvas3D) = this.renderer.canvas3d;
     }
 
-    /** Render the current plugin state to a PNG or JPEG file */
+    /** Render the current plugin state and save to a PNG or JPEG file */
     async saveImage(outPath: string, imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>, format?: 'png' | 'jpeg', jpegQuality = 90) {
         this.canvas3d!.commit(true);
         return await this.renderer.saveImage(outPath, imageSize, props, format, jpegQuality);
     }
 
+    /** Render the current plugin state and return as raw image data */
+    async getImageRaw(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>): Promise<RawImageData> {
+        this.canvas3d!.commit(true);
+        return await this.renderer.getImageRaw(imageSize, props);
+    }
+
+    /** Render the current plugin state and return as a PNG object */
+    async getImagePng(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>): Promise<PNG> {
+        this.canvas3d!.commit(true);
+        return await this.renderer.getImagePng(imageSize, props);
+    }
+
+    /** Render the current plugin state and return as a JPEG object */
+    async getImageJpeg(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>, jpegQuality: number = 90): Promise<JpegBufferRet> {
+        this.canvas3d!.commit(true);
+        return await this.renderer.getImageJpeg(imageSize, props);
+    }
+
     /** Get the current plugin state */
-    getStateSnapshot() {
+    async getStateSnapshot() {
         this.canvas3d!.commit(true);
-        return this.managers.snapshot.getStateSnapshot({ params: {} });
+        return await this.managers.snapshot.getStateSnapshot({ params: {} });
     }
 
     /** Save the current plugin state to a MOLJ file */
diff --git a/src/mol-plugin/util/headless-screenshot.ts b/src/mol-plugin/util/headless-screenshot.ts
index 668b48899770ee3063808e8a45a1c6199fb40739..3ae8332e73ab580f93734b335baa797d7fb1dae2 100644
--- a/src/mol-plugin/util/headless-screenshot.ts
+++ b/src/mol-plugin/util/headless-screenshot.ts
@@ -10,8 +10,8 @@
 
 import fs from 'fs';
 import path from 'path';
-import { type BufferRet as JpegBufferRet } from 'jpeg-js'; // Only import type here, the actual import is done by LazyImports
-import { type PNG } from 'pngjs'; // Only import type here, the actual import is done by LazyImports
+import { type BufferRet as JpegBufferRet } from 'jpeg-js'; // Only import type here, the actual import must be provided by the caller
+import { type PNG } from 'pngjs'; // Only import type here, the actual import must be provided by the caller
 
 import { Canvas3D, Canvas3DContext, Canvas3DProps, DefaultCanvas3DParams } from '../../mol-canvas3d/canvas3d';
 import { ImagePass, ImageProps } from '../../mol-canvas3d/passes/image';
@@ -22,16 +22,14 @@ import { AssetManager } from '../../mol-util/assets';
 import { ColorNames } from '../../mol-util/color/names';
 import { PixelData } from '../../mol-util/image';
 import { InputObserver } from '../../mol-util/input/input-observer';
-import { LazyImports } from '../../mol-util/lazy-imports';
 import { ParamDefinition } from '../../mol-util/param-definition';
 
 
-const lazyImports = LazyImports.create('gl', 'jpeg-js', 'pngjs') as {
+export interface ExternalModules {
     'gl': typeof import('gl'),
-    'jpeg-js': typeof import('jpeg-js'),
-    'pngjs': typeof import('pngjs'),
-};
-
+    'jpeg-js'?: typeof import('jpeg-js'),
+    'pngjs'?: typeof import('pngjs'),
+}
 
 export type HeadlessScreenshotHelperOptions = {
     webgl?: WebGLContextAttributes,
@@ -51,11 +49,11 @@ export class HeadlessScreenshotHelper {
     readonly canvas3d: Canvas3D;
     readonly imagePass: ImagePass;
 
-    constructor(readonly canvasSize: { width: number, height: number }, canvas3d?: Canvas3D, options?: HeadlessScreenshotHelperOptions) {
+    constructor(readonly externalModules: ExternalModules, readonly canvasSize: { width: number, height: number }, canvas3d?: Canvas3D, options?: HeadlessScreenshotHelperOptions) {
         if (canvas3d) {
             this.canvas3d = canvas3d;
         } else {
-            const glContext = lazyImports.gl(this.canvasSize.width, this.canvasSize.height, options?.webgl ?? defaultWebGLAttributes());
+            const glContext = this.externalModules.gl(this.canvasSize.width, this.canvasSize.height, options?.webgl ?? defaultWebGLAttributes());
             const webgl = createContext(glContext);
             const input = InputObserver.create();
             const attribs = { ...Canvas3DContext.DefaultAttribs };
@@ -93,14 +91,20 @@ export class HeadlessScreenshotHelper {
 
     async getImagePng(imageSize?: { width: number, height: number }, postprocessing?: Partial<PostprocessingProps>): Promise<PNG> {
         const imageData = await this.getImageRaw(imageSize, postprocessing);
-        const generatedPng = new lazyImports.pngjs.PNG({ width: imageData.width, height: imageData.height });
+        if (!this.externalModules.pngjs) {
+            throw new Error("External module 'pngjs' was not provided. If you want to use getImagePng, you must import 'pngjs' and provide it to the HeadlessPluginContext/HeadlessScreenshotHelper constructor.");
+        }
+        const generatedPng = new this.externalModules.pngjs.PNG({ width: imageData.width, height: imageData.height });
         generatedPng.data = Buffer.from(imageData.data.buffer);
         return generatedPng;
     }
 
     async getImageJpeg(imageSize?: { width: number, height: number }, postprocessing?: Partial<PostprocessingProps>, jpegQuality: number = 90): Promise<JpegBufferRet> {
         const imageData = await this.getImageRaw(imageSize, postprocessing);
-        const generatedJpeg = lazyImports['jpeg-js'].encode(imageData, jpegQuality);
+        if (!this.externalModules['jpeg-js']) {
+            throw new Error("External module 'jpeg-js' was not provided. If you want to use getImageJpeg, you must import 'jpeg-js' and provide it to the HeadlessPluginContext/HeadlessScreenshotHelper constructor.");
+        }
+        const generatedJpeg = this.externalModules['jpeg-js'].encode(imageData, jpegQuality);
         return generatedJpeg;
     }
 
diff --git a/src/mol-util/lazy-imports.ts b/src/mol-util/lazy-imports.ts
deleted file mode 100644
index 774e9a4d110f2761a58928b69f24353f11a4c2d4..0000000000000000000000000000000000000000
--- a/src/mol-util/lazy-imports.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright (c) 2019-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Adam Midlik <midlik@gmail.com>
- *
- * Manage dependencies which are not listed in `package.json` for performance reasons.
- */
-
-
-const _loadedExtraPackages: { [dep: string]: any } = {};
-
-/** Define imports that only get imported when first needed.
- * Example usage:
- * ```
- * const lazyImports = LazyImports.create('gl', 'jpeg-js', 'pngjs') as {
- *     'gl': typeof import('gl'),
- *     'jpeg-js': typeof import('jpeg-js'),
- *     'pngjs': typeof import('pngjs'),
- * };
- * ...
- * lazyImports.pngjs.blablabla("I'm being imported now");
- * lazyImports.pngjs.blablabla("I'm cached :D");
- * ```
- */
-export class LazyImports {
-    static create<U extends string>(...packages: U[]): { [dep in U]: any } {
-        return new LazyImports(packages) as any;
-    }
-    private constructor(private packages: string[]) {
-        for (const p of packages) {
-            Object.defineProperty(this, p, {
-                get: () => this.getPackage(p),
-            });
-        }
-    }
-    private getPackage(packageName: string) {
-        if (!_loadedExtraPackages[packageName]) {
-            try {
-                _loadedExtraPackages[packageName] = require(packageName);
-            } catch {
-                const message = `Package '${packageName}' is not installed. (Some packages are not listed in the 'molstar' package dependencies for performance reasons. If you're seeing this error, you'll probably need them. If your project depends on 'molstar', add these to your dependencies: ${this.packages.join(', ')}. If you're running 'molstar' directly, run this: npm install --no-save ${this.packages.join(' ')})`;
-                throw new Error(message);
-            }
-        }
-        return _loadedExtraPackages[packageName];
-    }
-}