Retour au blog

WebAssembly en 2025 : Comment Atteindre une Performance Native dans le Navigateur avec JavaScript

Salut HaWkers, WebAssembly (Wasm) a évolué de technologie expérimentale à standard de production en 2025. L'intégration seamless avec JavaScript permet aux applications web d'atteindre une performance proche des applications natives.

Mais quand avez-vous vraiment besoin de WebAssembly ? Et comment l'utiliser avec JavaScript ?

Qu'est-ce que WebAssembly

WebAssembly est un format binaire qui tourne dans le navigateur avec une performance proche du code natif :

// JavaScript - Interprété/JIT
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

fibonacci(40); // ~1000ms

// WebAssembly - Compilé, optimisé
// Même fonction en Wasm : ~50ms
// 20x plus rapide !

Pourquoi WebAssembly Est Si Rapide

const performanceComparison = {
  javascript: {
    parsing: 'Parse + compile pendant exécution',
    optimization: 'JIT tente d\'optimiser les hot paths',
    types: 'Dynamiquement typé (overhead)',
    memory: 'Garbage collection (pauses)',
    speed: 'Baseline'
  },
  webassembly: {
    parsing: 'Binaire pré-compilé',
    optimization: 'Déjà optimisé à la compilation',
    types: 'Statiquement typé (zéro overhead)',
    memory: 'Linear memory (sans GC)',
    speed: '10-20x plus rapide sur opérations lourdes'
  }
};

wasm performance

Utiliser WebAssembly avec JavaScript

Exemple 1 : Traitement d'Image

// imageProcessor.js
async function initWasm() {
  const response = await fetch('image-processor.wasm');
  const buffer = await response.arrayBuffer();
  const module = await WebAssembly.instantiate(buffer);

  return module.instance.exports;
}

class ImageProcessor {
  constructor() {
    this.wasm = null;
  }

  async init() {
    this.wasm = await initWasm();
  }

  // JavaScript pur - lent
  blurJS(imageData) {
    const start = performance.now();

    for (let y = 1; y < imageData.height - 1; y++) {
      for (let x = 1; x < imageData.width - 1; x++) {
        // Algorithme de blur (9 pixels autour)
        // ... code de blur
      }
    }

    console.log(`JS blur: ${performance.now() - start}ms`);
  }

  // WebAssembly - rapide
  blurWasm(imageData) {
    const start = performance.now();

    // Passer les données à Wasm
    const ptr = this.wasm.malloc(imageData.data.length);
    const wasmMem = new Uint8Array(
      this.wasm.memory.buffer,
      ptr,
      imageData.data.length
    );
    wasmMem.set(imageData.data);

    // Exécuter le blur en Wasm
    this.wasm.blur(ptr, imageData.width, imageData.height);

    // Récupérer le résultat
    imageData.data.set(wasmMem);
    this.wasm.free(ptr);

    console.log(`Wasm blur: ${performance.now() - start}ms`);
  }
}

// Usage
const processor = new ImageProcessor();
await processor.init();

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

processor.blurWasm(imageData); // 10x plus rapide !
ctx.putImageData(imageData, 0, 0);

Cas d'Usage Réels pour WebAssembly

1. Compression/Décompression

// wasm-compression.js
import init, { compress, decompress } from './pkg/compression_wasm.js';

await init();

// Compresser des données
const data = new Uint8Array(largeDataBuffer);
const compressed = compress(data);

console.log(`Original: ${data.length} bytes`);
console.log(`Compressé: ${compressed.length} bytes`);
console.log(`Ratio: ${((compressed.length / data.length) * 100).toFixed(1)}%`);

// Décompresser
const decompressed = decompress(compressed);

2. Cryptographie

// crypto-wasm.js
class WasmCrypto {
  async encrypt(data, key) {
    // Wasm exécute AES-256 beaucoup plus vite que JS
    const encrypted = this.wasm.aes_encrypt(data, key);
    return encrypted;
  }

  async decrypt(encrypted, key) {
    const decrypted = this.wasm.aes_decrypt(encrypted, key);
    return decrypted;
  }

  async hash(data) {
    // SHA-256 en Wasm
    return this.wasm.sha256(data);
  }
}

3. Jeux et Physique

// physics-engine.js
class PhysicsEngine {
  constructor() {
    this.bodies = [];
  }

  async init() {
    this.wasm = await initPhysicsWasm();
  }

  update(deltaTime) {
    // Simulation physique en Wasm
    // 100x plus rapide que JS pour calculs complexes

    const ptr = this.wasm.malloc(this.bodies.length * 32); // 32 bytes par body

    // Copier l'état vers Wasm memory
    const view = new Float32Array(
      this.wasm.memory.buffer,
      ptr,
      this.bodies.length * 8
    );

    this.bodies.forEach((body, i) => {
      view[i * 8 + 0] = body.x;
      view[i * 8 + 1] = body.y;
      view[i * 8 + 2] = body.vx;
      view[i * 8 + 3] = body.vy;
      view[i * 8 + 4] = body.mass;
      // ...
    });

    // Exécuter la simulation
    this.wasm.simulate_physics(ptr, this.bodies.length, deltaTime);

    // Récupérer les résultats
    this.bodies.forEach((body, i) => {
      body.x = view[i * 8 + 0];
      body.y = view[i * 8 + 1];
      body.vx = view[i * 8 + 2];
      body.vy = view[i * 8 + 3];
    });

    this.wasm.free(ptr);
  }
}

Outils et Langages pour Wasm

Rust pour WebAssembly

// lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2)
    }
}

#[wasm_bindgen]
pub fn process_array(numbers: &[f64]) -> Vec<f64> {
    numbers.iter()
        .map(|&x| x * 2.0)
        .filter(|&x| x > 10.0)
        .collect()
}
// Utiliser en JavaScript
import init, { fibonacci, process_array } from './pkg/my_wasm.js';

await init();

console.log(fibonacci(40)); // Super rapide !

const numbers = [1, 5, 10, 15, 20];
const result = process_array(new Float64Array(numbers));
console.log(result); // [20, 30, 40]

AssemblyScript (TypeScript → Wasm)

// assembly/index.ts
export function add(a: i32, b: i32): i32 {
  return a + b;
}

export function processData(data: Float64Array): Float64Array {
  const result = new Float64Array(data.length);

  for (let i = 0; i < data.length; i++) {
    result[i] = Math.sqrt(data[i]) * 2.0;
  }

  return result;
}

Quand Utiliser WebAssembly

Utilisez Wasm quand :

  • Traitement lourd (image, vidéo, audio)
  • Calculs mathématiques complexes
  • Jeux et physique
  • Cryptographie
  • Compression/décompression
  • Parsing de formats binaires

N'utilisez pas Wasm pour :

  • Manipulation du DOM (JavaScript est meilleur)
  • I/O et network requests
  • Code simple sans calculs lourds
  • Quand la taille du bundle compte beaucoup

Performance Réelle : Benchmarks

// benchmark.js
async function runBenchmarks() {
  const iterations = 1000000;

  // JavaScript
  console.time('JS Sum');
  let sum = 0;
  for (let i = 0; i < iterations; i++) {
    sum += i * 2;
  }
  console.timeEnd('JS Sum'); // ~10ms

  // WebAssembly
  console.time('Wasm Sum');
  const wasmSum = wasm.calculate_sum(iterations);
  console.timeEnd('Wasm Sum'); // ~0.5ms

  console.log(`Gain de performance: ${10 / 0.5}x plus rapide`);
}

// Résultats typiques :
const benchmarkResults = {
  fibonacci: { js: '1000ms', wasm: '50ms', speedup: '20x' },
  imageBlur: { js: '350ms', wasm: '25ms', speedup: '14x' },
  matrixMultiply: { js: '450ms', wasm: '20ms', speedup: '22x' },
  compression: { js: '800ms', wasm: '60ms', speedup: '13x' }
};

Limitations et Considérations

  1. Taille du Bundle : Wasm ajoute des bytes au bundle
  2. Temps de Démarrage : La compilation initiale a un overhead
  3. Debugging : Plus difficile que JavaScript
  4. Communication JS↔Wasm : Transférer des données a un coût
  5. Pas tout n'est plus rapide : L'overhead de communication peut annuler les gains

Si vous voulez en savoir plus sur quand optimiser le code, lisez Optimisation Prématurée vs Optimisation Nécessaire où vous apprendrez à identifier les vrais goulots d'étranglement.

C'est parti !

🚀 Maîtrisez JavaScript Avant Wasm

WebAssembly complète JavaScript, il ne le remplace pas. Une base solide en JavaScript est essentielle.

Commencez maintenant :

  • 9,90€ (paiement unique)

🚀 Accéder au Guide Complet

Commentaires (0)

Cet article n'a pas encore de commentaires. Soyez le premier!

Ajouter des commentaires