Never Sleep Again: How I Built AwakeLock, a Robust, Multi-Layered Solution for Web Wake Locks



This content originally appeared on DEV Community and was authored by Emmanuel

Have you ever been frustrated by your screen dimming or your device falling asleep in the middle of a critical presentation, a long-running data process, or while you’re simply trying to follow a recipe online? It’s a common nuisance that can disrupt workflows and user experience. As a developer, I decided to tackle this head-on, building AwakeLock – a sophisticated, multi-layered JavaScript library designed to prevent device sleep with intelligent fallbacks, performance monitoring, and seamless framework integrations.

This article will dive into how AwakeLock solves this pervasive problem, its core architecture, the clever strategies it employs, and why it’s a project that showcases robust engineering for any developer or recruiter looking for a deep technical understanding.

The Problem: When Your Device Just Won’t Stay Awake

Modern web applications increasingly need to keep a device active. Think about:

  • Dashboards: Monitoring real-time data or analytics.

  • Presentations: Displaying slides without interruption.

  • Long Forms/Workflows: Preventing session timeouts or lost progress.

  • Media Playback: Ensuring audio or video continues uninterrupted.

  • Kiosks or Information Displays: Keeping the screen on indefinitely.

Relying solely on native browser APIs can be unreliable due to varying support and strict permission models. That’s where AwakeLock steps in to provide a bulletproof solution.

My Solution: AwakeLock’s Intelligent Wake Lock System

AwakeLock is more than just a wrapper around navigator.wakeLock.request(). It’s a comprehensive library that ensures your device stays awake through a hierarchical system of strategies, intelligent fallbacks, and proactive performance management. Its main purpose is to provide a reliable, cross-browser, and easy-to-use API for maintaining a wake lock.

Diving Deep: AwakeLock’s Architecture and Technical Prowess

Building a truly robust wake lock solution required careful architectural design and a deep understanding of browser quirks. Here’s how AwakeLock is structured:

Project Structure at a Glance

The project is meticulously organized for clarity and maintainability. Key directories include src/ for all source code, src/strategies/ for different wake lock implementations, src/frameworks/ for framework-specific integrations, and tests/ for comprehensive testing.

awake-lock/
├── src/ # Source code
│ ├── strategies/ # Wake lock strategy implementations
│ ├── frameworks/ # Framework-specific integrations
│ ├── utils/ # Utility modules
│ ├── WakeLock.ts # Main WakeLock class
│ ├── PerformanceMonitor.ts # Performance tracking
│ ├── PermissionManager.ts # Permission handling
├── tests/ # Test suite
├── examples/ # Usage examples
├── dist/ # Build outputs (ESM, CJS, UMD)
└── docs/ # Documentation




The Central Brain: WakeLock Class

The src/WakeLock.ts file houses the WakeLock class, which acts as the central orchestrator. It coordinates all subsystems: managing strategies and fallbacks, emitting events, integrating with performance monitoring, and handling permissions and battery optimizations.

TypeScript

export class WakeLock extends EventEmitter<WakeLockEvents> {
private readonly options: Required<WakeLockOptions>;
private readonly permissionManager: PermissionManager;
private readonly performanceMonitor: PerformanceMonitor;
private readonly strategies: FallbackStrategy[];

private activeSentinel: InternalWakeLockSentinel | null = null;
private currentStrategy: FallbackStrategy | null = null;
}




The Strategy Pattern: A Multi-Layered Approach

This is where AwakeLock truly shines. It employs the Strategy Pattern with a hierarchical fallback system to ensure maximum compatibility and reliability. If one method fails, it seamlessly tries the next.

  1. ScreenWakeLockStrategy (Priority 1): Utilizes the native Screen Wake Lock API (navigator.wakeLock.request('screen')). This is the most efficient and preferred method, supported in modern Chrome, Edge, and Safari versions.

  2. VideoElementStrategy (Priority 2): Creates a tiny, hidden video element with silent playback. Surprisingly effective, especially for mobile Safari where native API support might be limited.

  3. AudioContextStrategy (Priority 3): Generates a silent audio context oscillator, leveraging the Web Audio API to keep the device awake.

  4. TimerStrategy (Priority 4): As a universal last resort, this strategy uses periodic no-op setInterval operations combined with touch events and CPU activity to signal activity.

This robust fallback mechanism is crucial for ensuring a consistent experience across the fragmented browser landscape.

Strategy Selection Flow

Code snippet

flowchart TD
A[Request Wake Lock] --> B{Screen Wake Lock API Available?}
B -->|Yes| C[Use ScreenWakeLockStrategy]
B -->|No| D{Video Element Supported?}
D -->|Yes| E[Use VideoElementStrategy]
D -->|No| F{Audio Context Available?}
F -->|Yes| G[Use AudioContextStrategy]
F -->|No| H[Use TimerStrategy]
C --&gt; I{Success?}
E --&gt; I
G --&gt; I
H --&gt; I

I --&gt;|Yes| J[Wake Lock Active]
I --&gt;|No| K[Try Next Strategy]
K --&gt; D




Permission and Performance Management

AwakeLock includes dedicated modules for PermissionManager to handle browser permission states and user interaction requirements, and PerformanceMonitor to track metrics like CPU usage, memory consumption, and battery levels. This allows for intelligent decisions, such as automatically releasing the wake lock on low battery (below 15% threshold) to preserve device life.

Framework Integrations

To make AwakeLock effortless to use in popular frontend frameworks, I built specific integrations:

  • ✅ React

    TypeScript

    const { request, release } = useWakeLock();
    
  • ✅ Vue

    TypeScript

    const { request } = useWakeLock(); // composition API
    
  • ✅ Angular

    TypeScript

    this.wakeLockService.request().subscribe();
    

These integrations significantly enhance developer experience and adoption.

Key Design Patterns Utilized

The architecture consciously employs several classic design patterns:

  • Strategy Pattern: For interchangeable wake lock implementations.

  • Observer Pattern: For a decoupled event notification system.

  • Facade Pattern: To provide a simple API that hides underlying complexity.

  • Template Method Pattern: For a consistent request/release lifecycle across strategies.

  • Singleton Pattern: For framework services maintaining a single instance.

This structured approach ensures the library is robust, extensible, and maintainable.

Challenges Faced & How I Overcame Them

Building a cross-browser, reliable wake lock solution came with its share of hurdles:

  • Browser Inconsistencies: The biggest challenge was the fragmented support for native Wake Lock APIs and the varying behaviors of background processes across browsers. My solution was the multi-layered strategy pattern, ensuring that if one method fails or isn’t supported, AwakeLock intelligently falls back to the next reliable option.

  • Resource Management: Preventing memory leaks and optimizing for battery life were crucial. I overcame this by implementing modern cleanup mechanisms using pagehide and visibilitychange events, ensuring resources are released efficiently when no longer needed.

  • Permission Handling: Browsers often require explicit user interaction for sensitive APIs. The PermissionManager was built to gracefully handle these scenarios, guiding users through necessary prompts and ensuring a smooth experience.

Why AwakeLock Stands Out: A Brief Comparison with NoSleep.js

While projects like NoSleep.js have been valuable, AwakeLock offers a more comprehensive and robust solution:

  • Multi-Strategy Reliability: Unlike simpler solutions that often rely on a single method (e.g., a hidden video), AwakeLock employs a prioritized, multi-layered strategy system for superior compatibility and resilience across browsers.

  • Intelligent Resource Management: AwakeLock actively monitors performance and optimizes battery usage, automatically releasing the wake lock on low battery, a feature typically absent in basic implementations.

  • Seamless Framework Integration: It provides first-class, idiomatic integrations for React, Vue, and Angular, simplifying usage and ensuring proper lifecycle management within modern web applications.

  • Optimized & Modern: Built with a focus on a tiny bundle size (7KB gzipped) and modern tooling, AwakeLock is highly performant and maintains clean, up-to-date practices.

Innovation & Impact: Why AwakeLock Matters

What makes AwakeLock truly unique and a project I’m particularly proud of:

  • Robust Fallback System: The intelligent priority-based strategy selection ensures maximum compatibility across over 95% of browsers.

  • Comprehensive Monitoring: Integrating performance and battery monitoring sets it apart, allowing for responsible resource usage.

  • Framework Agnostic & Specific: While core functionality is framework-agnostic, providing first-class integrations for React, Vue, and Angular makes it incredibly accessible to a broad developer audience.

  • Significant Performance Optimizations: Through meticulous build optimizations, I achieved a remarkable 59% bundle size reduction, resulting in a tiny 7KB gzipped UMD build. This minimal footprint ensures it’s lightweight and performant.

  • Developer Experience Focus: From zero build warnings to comprehensive testing and clear documentation, the project prioritizes a smooth developer experience.

AwakeLock demonstrates a deep understanding of browser APIs, robust architectural design, and a commitment to performance and developer-friendliness.

Explore AwakeLock: See the Code in Action

AwakeLock is production-ready, thoroughly tested, and actively maintained.

  • Project Demo: See AwakeLock in action with React on StackBlitz: Live Demo and on Netlify

  • GitHub Repository: Want to dive into the code, contribute, or fork the project? Check out the full source code on GitHub: Source Code

I invite you to explore the repository, run the examples, and even contribute if you find an opportunity for improvement. Your feedback is highly welcome!

Conclusion: A Reliable Solution for a Common Web Challenge

Building AwakeLock has been an incredible journey, solidifying my skills in robust library design, cross-browser compatibility, performance optimization, and developer tooling. It represents a practical solution to a common web development challenge, delivered with a focus on reliability, extensibility, and user experience.

I hope this deep dive into AwakeLock’s architecture provides valuable insights into how complex browser behaviors can be tamed with thoughtful engineering and a multi-layered approach. Feel free to reach out with any questions or thoughts!


This content originally appeared on DEV Community and was authored by Emmanuel