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-jsyarn remove lottie-jspnpm remove lottie-jsInstall New Package
Install the modern dotlottie-js package:
npm install @lottiefiles/dotlottie-jsyarn add @lottiefiles/dotlottie-jspnpm add @lottiefiles/dotlottie-jsStep 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 Method | New 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-safeTroubleshooting
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:
Unit Tests: Update all tests that use lottie-js
Integration Tests: Test end-to-end animation workflows
Browser Testing: If using in browsers, test across target browsers
Bundle Size: Verify the new library doesn't increase bundle size unexpectedly
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
Review the dotlottie-js documentation for advanced features
Explore advanced guides for themes and state machines
Check the API reference for complete method documentation
Need Help?
If you're stuck or have questions:
Check the Legacy API Reference
Join our Discord community
Open an issue on GitHub