Command Palette

Search for a command to run...

Migration Guide

Step-by-step guide for migrating from lottie-js to dotlottie-js

Migration Guide: lottie-js to dotlottie-js

This guide provides detailed instructions for migrating from the legacy lottie-js library to the modern @lottiefiles/dotlottie-js library.

Prerequisites

Before starting the migration:

  • Node.js 14.x or higher

  • Basic understanding of async/await patterns

  • Familiarity with ES modules (if using ESM)

Step 1: Update Dependencies

Remove Old Package

First, uninstall the legacy lottie-js package:

npm uninstall lottie-js
yarn remove lottie-js
pnpm remove lottie-js

Install New Package

Install the modern dotlottie-js package:

npm install @lottiefiles/dotlottie-js
yarn add @lottiefiles/dotlottie-js
pnpm add @lottiefiles/dotlottie-js

Step 2: Update Import Statements

The module name and import patterns have changed.

Old Pattern (lottie-js)

// CommonJS
const lottie = require("lottie-js");

// ES Modules (if supported)
import lottie from "lottie-js";

New Pattern (dotlottie-js)

// ES Modules (recommended)
import { DotLottie } from "@lottiefiles/dotlottie-js";

// CommonJS (also supported)
const { DotLottie } = require("@lottiefiles/dotlottie-js");

Step 3: API Migration

Loading Animations

The way you load animations has changed from callbacks to promises.

const lottie = require('lottie-js');

// Callback-based loading
lottie.loadAnimation({
path: 'animation.json',
callback: (animation) => {
console.log('Loaded:', animation);
// Work with animation
},
error: (err) => {
console.error('Failed:', err);
}
});
import { DotLottie } from '@lottiefiles/dotlottie-js';

// Promise-based loading
const dotLottie = new DotLottie();

try {
  await dotLottie.fromURL('animation.json');
  console.log('Loaded successfully');
  // Work with animation
} catch (err) {
  console.error('Failed:', err);
}

Creating DotLottie Files

The API for creating .lottie files has been redesigned.

const lottie = require('lottie-js');

lottie.createDotLottie({
animations: [
{
id: 'animation1',
data: animationData1,
loop: true,
autoplay: true
},
{
id: 'animation2',
data: animationData2,
loop: false
}
],
assets: {
'image1.png': imageBuffer
},
callback: (dotLottieFile) => {
// Save or use the file
fs.writeFileSync('output.lottie', dotLottieFile);
},
error: (err) => {
console.error('Failed:', err);
}
});
import { DotLottie } from '@lottiefiles/dotlottie-js';
import fs from 'fs/promises';

const dotLottie = new DotLottie();

// Add animations
await dotLottie.addAnimation({
  id: 'animation1',
  url: 'https://example.com/animation1.json',
  loop: true,
  autoplay: true
});

await dotLottie.addAnimation({
  id: 'animation2',
  data: animationData2,
  loop: false
});

// Add assets
await dotLottie.addImage({
  id: 'image1',
  data: imageBuffer
});

// Build and save
const arrayBuffer = await dotLottie.build();
await fs.writeFile('output.lottie', Buffer.from(arrayBuffer));

Loading from Buffer

const lottie = require('lottie-js');
const fs = require('fs');

const buffer = fs.readFileSync('animation.lottie');

lottie.loadFromBuffer({
buffer: buffer,
callback: (dotLottie) => {
const animations = dotLottie.getAnimations();
console.log('Animations:', animations);
},
error: (err) => {
console.error('Failed:', err);
}
});
import { DotLottie } from '@lottiefiles/dotlottie-js';
import fs from 'fs/promises';

const buffer = await fs.readFile('animation.lottie');

const dotLottie = new DotLottie();
await dotLottie.fromArrayBuffer(buffer.buffer);

const manifest = dotLottie.manifest;
console.log('Animations:', manifest.animations);

Working with Manifest

lottie.loadFromBuffer({
  buffer: buffer,
  callback: (dotLottie) => {
    const manifest = dotLottie.getManifest();
    console.log('Version:', manifest.version);
    console.log('Author:', manifest.author);
    console.log('Animations:', manifest.animations);
  }
});
const dotLottie = new DotLottie();
await dotLottie.fromArrayBuffer(buffer);

// Access manifest directly
console.log("Version:", dotLottie.manifest.version);
console.log("Author:", dotLottie.manifest.author);
console.log("Animations:", dotLottie.manifest.animations);

// Or get as JSON
const manifestJson = dotLottie.getManifest();

Extracting Animations

lottie.loadFromBuffer({
  buffer: buffer,
  callback: (dotLottie) => {
    const animation = dotLottie.getAnimation('animation1');
    if (animation) {
      const jsonData = animation.data;
      console.log('Animation JSON:', jsonData);
    }
  }
});
const dotLottie = new DotLottie();
await dotLottie.fromArrayBuffer(buffer);

// Get animation as JSON
const animationJson = await dotLottie.getAnimation("animation1");
if (animationJson) {
  console.log("Animation JSON:", animationJson);
}

Step 4: Breaking Changes

1. No More Callbacks

All async operations now use Promises. You must use async/await or .then()/.catch().

Migration Pattern:

// Old callback pattern
lottie.someMethod({
  param: value,
  callback: (result) => {
    /* success */
  },
  error: (err) => {
    /* error */
  },
});

// New promise pattern
try {
  const result = await dotLottie.someMethod(param);
  // success
} catch (err) {
  // error
}

2. Constructor Changes

The library no longer uses static methods. Create an instance first.

// Old: Static methods
lottie.loadAnimation({ ... });
lottie.createDotLottie({ ... });

// New: Instance methods
const dotLottie = new DotLottie();
await dotLottie.fromURL(...);
await dotLottie.addAnimation(...);

3. Method Naming

Many methods have been renamed for clarity:

Old MethodNew Method
loadAnimation()fromURL() or fromArrayBuffer()
createDotLottie()new DotLottie() + addAnimation()
loadFromBuffer()fromArrayBuffer()
getAnimations()manifest.animations
getManifest()manifest property or getManifest()
getAnimation(id)getAnimation(id)
addAsset()addImage()

4. Data Structure Changes

The manifest structure has been updated:

// Old manifest structure
{
  version: "1.0",
  author: "Author Name",
  animations: [{ id, loop, autoplay }]
}

// New manifest structure
{
  version: "1.0",
  author: "Author Name",
  animations: [
    {
      id: "animation1",
      loop: true,
      autoplay: true,
      speed: 1,
      mode: "forward"
    }
  ]
}

5. Asset Handling

Assets now require explicit types:

// Old: Generic assets
lottie.addAsset("image1.png", buffer);

// New: Typed assets
await dotLottie.addImage({
  id: "image1",
  data: buffer,
});

Step 5: Common Migration Patterns

Pattern 1: Simple Animation Loading

const lottie = require('lottie-js');

function loadAnimation(url) {
return new Promise((resolve, reject) => {
lottie.loadAnimation({
path: url,
callback: resolve,
error: reject
});
});
}

// Usage
loadAnimation('animation.json')
.then(anim => console.log('Loaded'))
.catch(err => console.error(err));
import { DotLottie } from '@lottiefiles/dotlottie-js';

async function loadAnimation(url) {
  const dotLottie = new DotLottie();
  await dotLottie.fromURL(url);
  return dotLottie;
}

// Usage
loadAnimation('animation.json')
  .then(anim => console.log('Loaded'))
  .catch(err => console.error(err));

Pattern 2: Building Multi-Animation Files

const lottie = require('lottie-js');

async function createBundle(animations) {
return new Promise((resolve, reject) => {
lottie.createDotLottie({
animations: animations.map(a => ({
id: a.id,
data: a.data,
loop: a.loop || false
})),
callback: resolve,
error: reject
});
});
}
import { DotLottie } from '@lottiefiles/dotlottie-js';

async function createBundle(animations) {
  const dotLottie = new DotLottie();

  for (const anim of animations) {
    await dotLottie.addAnimation({
      id: anim.id,
      data: anim.data,
      loop: anim.loop || false
    });
  }

  return await dotLottie.build();
}

Pattern 3: Reading and Modifying

const lottie = require('lottie-js');
const fs = require('fs');

function modifyDotLottie(inputPath, outputPath) {
const buffer = fs.readFileSync(inputPath);

lottie.loadFromBuffer({
buffer: buffer,
callback: (dotLottie) => {
// Modify manifest
const manifest = dotLottie.getManifest();
manifest.author = "Modified Author";

      // Save modified version
      const newBuffer = dotLottie.toBuffer();
      fs.writeFileSync(outputPath, newBuffer);
    },
    error: (err) => {
      console.error('Failed:', err);
    }

});
}
import { DotLottie } from '@lottiefiles/dotlottie-js';
import fs from 'fs/promises';

async function modifyDotLottie(inputPath, outputPath) {
  // Load existing file
  const buffer = await fs.readFile(inputPath);
  const dotLottie = new DotLottie();
  await dotLottie.fromArrayBuffer(buffer.buffer);

  // Modify manifest
  dotLottie.setAuthor("Modified Author");

  // Save modified version
  const newBuffer = await dotLottie.build();
  await fs.writeFile(outputPath, Buffer.from(newBuffer));
}

Step 6: Error Handling

Error handling is more straightforward with try/catch:

lottie.loadAnimation({
  path: 'animation.json',
  callback: (animation) => {
    // Handle success
    processAnimation(animation);
  },
  error: (err) => {
    // Handle different error types
    if (err.code === 'ENOENT') {
      console.error('File not found');
    } else if (err.code === 'INVALID_JSON') {
      console.error('Invalid animation data');
    } else {
      console.error('Unknown error:', err);
    }
  }
});
try {
  const dotLottie = new DotLottie();
  await dotLottie.fromURL("animation.json");

  // Handle success
  processAnimation(dotLottie);
} catch (err) {
  // Handle different error types
  if (err.message.includes("not found")) {
    console.error("File not found");
  } else if (err.message.includes("Invalid")) {
    console.error("Invalid animation data");
  } else {
    console.error("Unknown error:", err);
  }
}

Step 7: TypeScript Migration

If using TypeScript, you'll benefit from improved type definitions:

// lottie-js had limited types
import lottie from 'lottie-js';

interface AnimationConfig {
path: string;
callback?: (animation: any) => void;
error?: (err: any) => void;
}

const config: AnimationConfig = {
path: 'animation.json',
callback: (anim) => {
// 'anim' type is 'any'
console.log(anim);
}
};

lottie.loadAnimation(config);
// dotlottie-js has full TypeScript support
import { DotLottie, type Manifest } from '@lottiefiles/dotlottie-js';

async function loadAnimation(url: string): Promise<DotLottie> {
  const dotLottie = new DotLottie();
  await dotLottie.fromURL(url);
  return dotLottie;
}

// Full type inference
const dotLottie = await loadAnimation('animation.json');
const manifest: Manifest = dotLottie.manifest;

// TypeScript knows the structure
console.log(manifest.animations[0].id); // Type-safe

Troubleshooting

Issue: "Cannot find module 'lottie-js'"

Cause: Old imports still present in code.

Solution: Search your codebase for lottie-js references:

# Find all references
grep -r "lottie-js" src/

# Or using ripgrep
rg "lottie-js" src/

Replace all occurrences with @lottiefiles/dotlottie-js.

Issue: "callback is not a function"

Cause: Using old callback-based API.

Solution: Convert to async/await or Promises.

Issue: "Cannot use import statement outside a module"

Cause: Using ESM imports in a CommonJS project.

Solution: Either:

  • Use CommonJS: const { DotLottie } = require('@lottiefiles/dotlottie-js')

  • Enable ESM in package.json: "type": "module"

Issue: "Method not found" errors

Cause: Using old method names.

Solution: Check the Legacy API Reference for the new method names.

Issue: Different manifest structure

Cause: Manifest schema changes between versions.

Solution: Update code to use new manifest structure:

// Old
const animations = dotLottie.getAnimations();

// New
const animations = dotLottie.manifest.animations;

Testing Your Migration

After migrating, thoroughly test your application:

  1. Unit Tests: Update all tests that use lottie-js

  2. Integration Tests: Test end-to-end animation workflows

  3. Browser Testing: If using in browsers, test across target browsers

  4. Bundle Size: Verify the new library doesn't increase bundle size unexpectedly

  5. Performance: Check that animation loading performance is maintained or improved

Example Test Migration

describe('Animation Loading', () => {
  it('should load animation', (done) => {
    lottie.loadAnimation({
      path: 'test.json',
      callback: (anim) => {
        expect(anim).toBeDefined();
        done();
      },
      error: done
    });
  });
});
describe("Animation Loading", () => {
  it("should load animation", async () => {
    const dotLottie = new DotLottie();
    await dotLottie.fromURL("test.json");

    expect(dotLottie.manifest).toBeDefined();
    expect(dotLottie.manifest.animations.length).toBeGreaterThan(0);
  });
});

Performance Considerations

The new library offers several performance improvements:

  • Lazy Loading: Animations are not parsed until needed

  • Streaming Support: Better handling of large files

  • Memory Efficiency: Improved garbage collection

  • Smaller Bundle: Optimized build results in smaller bundles

Next Steps

Need Help?

If you're stuck or have questions:

Last updated: April 10, 2026 at 9:12 AMEdit this page