DevToolBoxGRATUIT
Blog

Guide Electron 2026 : Apps Desktop Cross-Platform avec Technologies Web

19 min de lecturepar DevToolBox Team

Electron is an open-source framework that lets you build cross-platform desktop applications using HTML, CSS, and JavaScript. Created by GitHub and now maintained by the OpenJS Foundation, Electron combines the Chromium rendering engine with the Node.js runtime to give web developers full access to native operating system APIs. Applications like Visual Studio Code, Slack, Discord, Figma, and Notion are all built with Electron, proving that web technologies can deliver production-quality desktop experiences on Windows, macOS, and Linux.

TL;DR

Electron enables building cross-platform desktop apps with web technologies (HTML, CSS, JS). It uses a multi-process architecture with a main process for native OS access and renderer processes for UI. Modern Electron enforces context isolation and preload scripts for security. Tools like electron-builder and electron-forge handle packaging and distribution. While Tauri offers smaller binaries, Electron provides mature ecosystem support, proven scalability (VS Code, Slack, Discord), and full Node.js access.

Key Takeaways
  • Electron combines Chromium and Node.js, allowing web developers to build native desktop apps for Windows, macOS, and Linux from a single codebase.
  • The multi-process architecture separates the main process (Node.js, native APIs) from renderer processes (web UI), improving security and stability.
  • Context isolation and preload scripts are mandatory security patterns that prevent renderer processes from directly accessing Node.js APIs.
  • IPC (Inter-Process Communication) via ipcMain and ipcRenderer is the safe way to communicate between main and renderer processes.
  • electron-builder and electron-forge handle code signing, auto-updates, and packaging for all platforms with a single configuration.
  • Electron apps can integrate React, Vue, or Svelte for the UI layer while having full access to native APIs like file system, notifications, tray, and menus.

What Is Electron and How Does It Work?

Electron is a framework for building desktop applications using web technologies. Under the hood, it bundles a Chromium browser to render your UI and a Node.js runtime to interact with the operating system. When a user launches your Electron app, it starts a main process that creates browser windows, each of which runs in its own renderer process. The main process has full access to Node.js APIs and native OS features, while renderer processes run your web-based UI in a sandboxed Chromium environment.

This architecture means you can use any web framework (React, Vue, Svelte, Angular) for your UI and any npm package for backend logic. Electron handles the plumbing between your web code and the operating system, providing APIs for file system access, system notifications, native menus, keyboard shortcuts, auto-updates, and more.

// main.js - Electron entry point
const { app, BrowserWindow } = require("electron");
const path = require("path");

function createWindow() {
  const win = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      sandbox: true,
    },
  });

  win.loadFile("index.html");
}

app.whenReady().then(createWindow);

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});

app.on("activate", () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

Electron Architecture: Main, Renderer, and Preload

Electron uses a multi-process architecture inspired by Chromium. Understanding the three types of processes is essential for building secure, performant Electron apps.

Main Process

The main process is the entry point of your application. It runs Node.js and has full access to the operating system. There is exactly one main process per application. It creates and manages BrowserWindow instances, handles native OS interactions (menus, dialogs, tray icons), and orchestrates the application lifecycle.

Renderer Process

Each BrowserWindow runs in its own renderer process. This is essentially a Chromium browser tab that loads your HTML, CSS, and JavaScript. Renderer processes are sandboxed by default and cannot directly access Node.js APIs or the file system. This isolation is a critical security feature.

Preload Scripts

Preload scripts bridge the gap between the main process and renderer process. They run in the renderer context but have access to a limited set of Node.js and Electron APIs. Using contextBridge, preload scripts selectively expose safe APIs to the renderer, creating a secure communication channel.

// preload.js - Bridge between main and renderer
const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  // Expose specific functions, not the entire ipcRenderer
  openFile: () => ipcRenderer.invoke("dialog:openFile"),
  saveFile: (content) => ipcRenderer.invoke("dialog:saveFile", content),
  onUpdateAvailable: (callback) => {
    ipcRenderer.on("update-available", (_event, info) => callback(info));
  },
  getAppVersion: () => ipcRenderer.invoke("app:getVersion"),
});

// renderer.js - Uses the exposed API
// window.electronAPI.openFile();
// window.electronAPI.saveFile("Hello World");

Electron vs Tauri: Detailed Comparison

Tauri is the most common alternative to Electron. While both frameworks build cross-platform desktop apps with web UIs, they take fundamentally different approaches to the backend runtime and system integration.

FeatureElectronTauri
Backend RuntimeNode.js (full npm ecosystem)Rust (compiled binary)
Rendering EngineBundled ChromiumSystem WebView (WRY)
Binary Size~150-200 MB~3-10 MB
Memory Usage~100-300 MB baseline~30-80 MB baseline
Backend LanguageJavaScript / TypeScriptRust
EcosystemMature, huge npm library supportGrowing, Rust crate ecosystem
Security ModelProcess isolation + context isolationRust safety + allowlist permissions
Notable AppsVS Code, Slack, Discord, FigmaEmerging adoption

BrowserWindow API

The BrowserWindow class is the primary way to create application windows. Each window is a full Chromium browser instance with its own renderer process. You can configure window dimensions, frame style, security settings, and much more through the constructor options.

const { BrowserWindow, screen } = require("electron");

// Create a frameless, transparent window
const overlay = new BrowserWindow({
  width: 400,
  height: 300,
  frame: false,
  transparent: true,
  alwaysOnTop: true,
  webPreferences: {
    preload: path.join(__dirname, "preload.js"),
    contextIsolation: true,
    sandbox: true,
  },
});

// Create a window that remembers its position
const mainWin = new BrowserWindow({
  width: 1200,
  height: 800,
  minWidth: 800,
  minHeight: 600,
  show: false, // Prevent white flash
  backgroundColor: "#1e1e1e",
  titleBarStyle: "hiddenInset", // macOS traffic lights
  webPreferences: {
    preload: path.join(__dirname, "preload.js"),
    contextIsolation: true,
    sandbox: true,
  },
});

// Show window when ready to avoid white flash
mainWin.once("ready-to-show", () => {
  mainWin.show();
});

IPC Communication: ipcMain and ipcRenderer

Inter-Process Communication (IPC) is the mechanism for exchanging data between the main process and renderer processes. Since renderer processes are sandboxed, IPC is the only safe way to trigger native operations from your UI. Electron provides two primary IPC patterns.

One-Way Messages (Renderer to Main)

Use ipcRenderer.send() in the preload script and ipcMain.on() in the main process for fire-and-forget messages.

// preload.js - One-way message
const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  sendNotification: (title, body) => {
    ipcRenderer.send("show-notification", { title, body });
  },
});

// main.js - Handle one-way message
const { ipcMain, Notification } = require("electron");

ipcMain.on("show-notification", (_event, { title, body }) => {
  new Notification({ title, body }).show();
});

Two-Way Messages (Invoke/Handle)

Use ipcRenderer.invoke() and ipcMain.handle() for request-response patterns. This is the recommended approach for most IPC communication.

// preload.js - Two-way invoke/handle
contextBridge.exposeInMainWorld("electronAPI", {
  readFile: (filePath) => ipcRenderer.invoke("fs:readFile", filePath),
  writeFile: (filePath, data) => ipcRenderer.invoke("fs:writeFile", filePath, data),
  listDir: (dirPath) => ipcRenderer.invoke("fs:listDir", dirPath),
});

// main.js - Handle invoke requests
const fs = require("fs/promises");

ipcMain.handle("fs:readFile", async (_event, filePath) => {
  // Validate the path before reading
  if (!filePath.startsWith(app.getPath("userData"))) {
    throw new Error("Access denied: path outside user data");
  }
  return fs.readFile(filePath, "utf-8");
});

ipcMain.handle("fs:writeFile", async (_event, filePath, data) => {
  if (!filePath.startsWith(app.getPath("userData"))) {
    throw new Error("Access denied: path outside user data");
  }
  await fs.writeFile(filePath, data, "utf-8");
  return { success: true };
});

// renderer.js - Using the API
// const content = await window.electronAPI.readFile("/path/to/file");
// await window.electronAPI.writeFile("/path/to/file", "new content");

Preload Scripts and Context Isolation

Context isolation is a security feature enabled by default since Electron 12. It ensures that preload scripts and the Electron internal logic run in a separate JavaScript context from the renderer page. This prevents the web page from accessing Electron internals or Node.js APIs directly.

The contextBridge module provides a safe way to expose specific APIs from the preload script to the renderer. Only the functions you explicitly expose through contextBridge.exposeInMainWorld() are available to the renderer page.

// preload.js - Secure API exposure with contextBridge
const { contextBridge, ipcRenderer } = require("electron");

// GOOD: Expose specific functions with validation
contextBridge.exposeInMainWorld("api", {
  getSettings: () => ipcRenderer.invoke("get-settings"),
  saveSettings: (settings) => {
    // Validate data before sending to main process
    if (typeof settings !== "object") throw new Error("Invalid settings");
    return ipcRenderer.invoke("save-settings", settings);
  },
  onThemeChange: (callback) => {
    const handler = (_event, theme) => callback(theme);
    ipcRenderer.on("theme-changed", handler);
    // Return cleanup function
    return () => ipcRenderer.removeListener("theme-changed", handler);
  },
});

// BAD: Never expose the entire ipcRenderer
// contextBridge.exposeInMainWorld("ipc", ipcRenderer); // DANGEROUS!

Auto-Updater

Electron provides built-in auto-update functionality through the autoUpdater module and the popular electron-updater package. Auto-updates allow you to push new versions to users without requiring them to manually download and install updates.

// main.js - Auto-update with electron-updater
const { autoUpdater } = require("electron-updater");

autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true;

app.whenReady().then(() => {
  autoUpdater.checkForUpdates();
});

autoUpdater.on("update-available", (info) => {
  // Notify renderer about the update
  mainWindow.webContents.send("update-available", info.version);
});

autoUpdater.on("download-progress", (progress) => {
  mainWindow.webContents.send("download-progress", progress.percent);
});

autoUpdater.on("update-downloaded", () => {
  mainWindow.webContents.send("update-ready");
});

// IPC handler to trigger download and install
ipcMain.handle("download-update", () => autoUpdater.downloadUpdate());
ipcMain.handle("install-update", () => autoUpdater.quitAndInstall());

Packaging and Distribution

Packaging an Electron app involves bundling your application code with the Electron runtime into platform-specific installers. The two main tools for this are electron-builder and electron-forge.

electron-builder

electron-builder is the most popular packaging tool. It supports creating installers for Windows (NSIS, MSI), macOS (DMG, PKG), and Linux (AppImage, DEB, RPM). It also handles code signing and notarization.

// package.json - electron-builder configuration
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "main": "dist/main.js",
  "build": {
    "appId": "com.example.myapp",
    "productName": "My App",
    "directories": { "output": "release" },
    "mac": {
      "category": "public.app-category.developer-tools",
      "target": ["dmg", "zip"],
      "hardenedRuntime": true,
      "notarize": true
    },
    "win": {
      "target": ["nsis"],
      "signingHashAlgorithms": ["sha256"]
    },
    "linux": {
      "target": ["AppImage", "deb"],
      "category": "Development"
    },
    "publish": {
      "provider": "github",
      "owner": "your-username",
      "repo": "your-repo"
    }
  },
  "scripts": {
    "build": "tsc && electron-builder",
    "build:mac": "tsc && electron-builder --mac",
    "build:win": "tsc && electron-builder --win",
    "build:linux": "tsc && electron-builder --linux"
  }
}

electron-forge

electron-forge is the official Electron packaging tool maintained by the Electron team. It provides a more opinionated workflow with built-in support for webpack, Vite, and TypeScript scaffolding.

# Create a new Electron Forge project
npm init electron-app@latest my-app -- --template=vite-typescript

# Build and package
npm run make

# Publish to GitHub Releases
npm run publish

Native APIs: Dialog, Menu, Tray, and Notifications

Electron provides access to native operating system features that are unavailable in a regular browser. These APIs let your application feel like a first-class citizen on each platform.

Dialog (File Picker)

The dialog module provides methods for showing native system dialogs including file open, file save, message boxes, and error dialogs.

// main.js - File dialog examples
const { dialog } = require("electron");

ipcMain.handle("dialog:openFile", async () => {
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ["openFile", "multiSelections"],
    filters: [
      { name: "Documents", extensions: ["txt", "md", "json"] },
      { name: "Images", extensions: ["png", "jpg", "gif"] },
      { name: "All Files", extensions: ["*"] },
    ],
  });
  return result.canceled ? null : result.filePaths;
});

ipcMain.handle("dialog:saveFile", async (_event, content) => {
  const result = await dialog.showSaveDialog(mainWindow, {
    defaultPath: "untitled.txt",
    filters: [{ name: "Text", extensions: ["txt"] }],
  });
  if (!result.canceled) {
    await fs.writeFile(result.filePath, content);
    return result.filePath;
  }
  return null;
});

Application Menu and Context Menu

Electron supports both application menus (the menu bar at the top of the window or screen) and context menus (right-click menus). Menus are built from a template of MenuItems with roles, labels, accelerators, and click handlers.

const { Menu, MenuItem } = require("electron");

const template = [
  {
    label: "File",
    submenu: [
      { label: "New File", accelerator: "CmdOrCtrl+N", click: () => createNewFile() },
      { label: "Open...", accelerator: "CmdOrCtrl+O", click: () => openFile() },
      { label: "Save", accelerator: "CmdOrCtrl+S", click: () => saveFile() },
      { type: "separator" },
      { role: "quit" },
    ],
  },
  {
    label: "Edit",
    submenu: [
      { role: "undo" },
      { role: "redo" },
      { type: "separator" },
      { role: "cut" },
      { role: "copy" },
      { role: "paste" },
      { role: "selectAll" },
    ],
  },
];

const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);

System Tray

The Tray module lets you create an icon in the system tray (or menu bar on macOS) with a context menu. This is commonly used for background applications that run without a visible window.

const { Tray, Menu, nativeImage } = require("electron");

let tray = null;

app.whenReady().then(() => {
  const icon = nativeImage.createFromPath("assets/tray-icon.png");
  tray = new Tray(icon.resize({ width: 16, height: 16 }));

  const contextMenu = Menu.buildFromTemplate([
    { label: "Show App", click: () => mainWindow.show() },
    { label: "Status: Running", enabled: false },
    { type: "separator" },
    { label: "Quit", click: () => app.quit() },
  ]);

  tray.setToolTip("My Electron App");
  tray.setContextMenu(contextMenu);
  tray.on("click", () => mainWindow.show());
});

Notifications

Electron supports native OS notifications through the Notification class. Notifications can include a title, body, icon, and action buttons.

const { Notification } = require("electron");

function showNotification(title, body) {
  const notification = new Notification({
    title: title,
    body: body,
    icon: "assets/icon.png",
    silent: false,
  });

  notification.on("click", () => {
    mainWindow.show();
    mainWindow.focus();
  });

  notification.show();
}

Security Best Practices

Security is critical in Electron because your app has access to both the web and the operating system. Following these best practices protects your users from common attack vectors.

  • Always enable context isolation (contextIsolation: true) and sandbox mode (sandbox: true) for all BrowserWindows.
  • Never disable webSecurity. Keeping it enabled prevents cross-origin attacks and ensures CSP headers are respected.
  • Use contextBridge.exposeInMainWorld() to expose only specific, validated functions to the renderer.
  • Validate all IPC message arguments in the main process. Never trust data from the renderer.
  • Disable nodeIntegration in all renderer processes. Use preload scripts instead.
  • Set a strict Content Security Policy (CSP) that restricts script sources and prevents inline scripts.
  • Never load remote content in a BrowserWindow with node integration or without proper CSP.
  • Use session.defaultSession.webRequest to filter and block suspicious network requests.
// Secure BrowserWindow configuration
const win = new BrowserWindow({
  webPreferences: {
    contextIsolation: true,    // Required: isolate preload from page
    sandbox: true,             // Required: sandbox renderer process
    nodeIntegration: false,    // Required: no Node in renderer
    webSecurity: true,         // Required: enforce same-origin
    allowRunningInsecureContent: false,
    preload: path.join(__dirname, "preload.js"),
  },
});

// Set Content Security Policy
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
  callback({
    responseHeaders: {
      ...details.responseHeaders,
      "Content-Security-Policy": [
        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
      ],
    },
  });
});

Performance Optimization

Electron apps can consume significant memory and CPU. These techniques help reduce resource usage and improve startup time.

  • Lazy-load heavy modules and defer non-critical initialization to after the window is visible.
  • Use BrowserWindow show: false and show the window only after the ready-to-show event to avoid white flash.
  • Minimize the number of BrowserWindow instances. Each window creates a new Chromium renderer process.
  • Use V8 snapshots (via electron-link or custom snapshots) to reduce startup time by pre-compiling JavaScript.
  • Offload CPU-intensive work to worker threads (worker_threads) or child processes to keep the main process responsive.
  • Profile memory usage with Chrome DevTools and fix memory leaks from detached DOM nodes and uncleaned event listeners.
  • Bundle your renderer code with Vite or webpack and enable tree-shaking to reduce bundle size.
// Performance: Lazy-load heavy modules
app.whenReady().then(async () => {
  // Show window immediately with skeleton UI
  const win = new BrowserWindow({ show: false, /* ... */ });
  win.loadFile("index.html");
  win.once("ready-to-show", () => win.show());

  // Defer heavy initialization
  setTimeout(async () => {
    const db = await import("./database.js");
    await db.initialize();
    const analytics = await import("./analytics.js");
    analytics.track("app-launched");
  }, 1000);
});

// Offload CPU-intensive work to a worker thread
const { Worker } = require("worker_threads");

function processLargeFile(filePath) {
  return new Promise((resolve, reject) => {
    const worker = new Worker("./file-processor.js", {
      workerData: { filePath },
    });
    worker.on("message", resolve);
    worker.on("error", reject);
  });
}

Integrating React, Vue, and Svelte

Electron is framework-agnostic for the renderer process. You can use any web framework for your UI. The most popular choices are React, Vue, and Svelte, each with dedicated Electron scaffolding tools.

React with Electron

Use electron-vite or create-electron-app with the Vite template to scaffold a React-based Electron application. Vite provides fast HMR during development.

# Scaffold React + Electron with electron-vite
npm create electron-vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev

# Project structure:
# src/
#   main/       - Electron main process
#   preload/    - Preload scripts
#   renderer/   - React app (Vite-powered)
#     App.tsx
#     main.tsx

Vue with Electron

electron-vite also supports Vue out of the box. Alternatively, use Vue CLI with the electron-builder plugin for a more traditional setup.

# Scaffold Vue + Electron with electron-vite
npm create electron-vite@latest my-vue-app -- --template vue-ts

# Or using Vue CLI plugin
vue create my-vue-app
cd my-vue-app
vue add electron-builder

Svelte with Electron

Svelte pairs well with Electron because of its compiled output and small bundle size. Use electron-vite with the Svelte template for the fastest setup.

# Scaffold Svelte + Electron with electron-vite
npm create electron-vite@latest my-svelte-app -- --template svelte-ts
cd my-svelte-app
npm install
npm run dev

Testing Electron Applications

Testing Electron apps requires different strategies for unit tests, integration tests, and end-to-end tests. The most common tools are Playwright (with Electron support), Spectron (legacy), and standard test runners like Vitest for unit testing.

// e2e test with Playwright for Electron
const { _electron: electron } = require("@playwright/test");
const { test, expect } = require("@playwright/test");

test("app launches and shows title", async () => {
  const app = await electron.launch({ args: ["."] });
  const window = await app.firstWindow();

  // Wait for the page to load
  await window.waitForLoadState("domcontentloaded");

  // Check the window title
  const title = await window.title();
  expect(title).toBe("My Electron App");

  // Interact with the UI
  await window.click("button#open-file");
  await expect(window.locator("#file-content")).toBeVisible();

  // Check main process evaluations
  const appPath = await app.evaluate(async ({ app }) => {
    return app.getAppPath();
  });
  expect(appPath).toBeTruthy();

  await app.close();
});

Real-World Applications Built with Electron

Electron powers some of the most widely-used desktop applications in the world. These examples demonstrate that Electron can scale to handle complex, performance-sensitive use cases.

  • VS Code - The most popular code editor, used by millions of developers. Demonstrates that Electron can deliver high-performance text editing, extension systems, and integrated terminal functionality.
  • Slack - Enterprise messaging platform used by millions of teams. Handles real-time messaging, file sharing, and video calls across Windows, macOS, and Linux.
  • Discord - Gaming and community chat platform serving hundreds of millions of users. Features voice chat, video streaming, and rich media embedding.
  • Figma Desktop - Professional design tool that uses Electron for its desktop wrapper while running the core rendering engine in WebAssembly for near-native performance.
  • Notion - All-in-one workspace for notes, databases, and project management. Demonstrates complex rich-text editing and real-time collaboration in Electron.
  • GitHub Desktop - Git client that simplifies version control workflows. A showcase for clean Electron architecture with React.

Frequently Asked Questions

What is Electron used for?

Electron is used for building cross-platform desktop applications with web technologies (HTML, CSS, JavaScript). It is ideal for teams that want to reuse web development skills for desktop apps. Common use cases include code editors (VS Code), messaging apps (Slack, Discord), productivity tools (Notion), and developer utilities.

Is Electron still a good choice in 2026?

Yes. Despite competition from Tauri, Electron remains the most mature and widely-used framework for cross-platform desktop apps. It has the largest ecosystem, extensive documentation, and proven production track record with apps serving hundreds of millions of users. Electron continues to receive active updates improving security, performance, and Chromium compatibility.

Why are Electron apps so large?

Electron apps bundle a full Chromium browser and Node.js runtime, which adds approximately 150-200 MB to the application size. This ensures consistent rendering across platforms but results in larger downloads compared to native apps. Techniques like ASAR archiving, code splitting, and compression can help reduce the total size.

How do I reduce Electron app memory usage?

Minimize the number of BrowserWindow instances, lazy-load modules, use web workers for heavy computation, profile with Chrome DevTools to find memory leaks, and consider using the session partition feature to share resources between windows. Upgrading to the latest Electron version also brings Chromium memory optimizations.

Is Electron secure?

Electron can be very secure when best practices are followed. Enable context isolation and sandbox mode, use preload scripts with contextBridge instead of nodeIntegration, validate all IPC messages, set strict Content Security Policies, and keep Electron updated to get the latest Chromium security patches.

Can I use TypeScript with Electron?

Yes. Electron has excellent TypeScript support. Tools like electron-vite and electron-forge include TypeScript templates. Electron ships its own type definitions, and ipcMain/ipcRenderer can be fully typed for end-to-end type safety in your IPC communication.

How does Electron auto-update work?

Electron auto-update uses the autoUpdater module or the electron-updater package. The app checks a remote server for new versions, downloads the update in the background, and prompts the user to restart. On macOS, updates use Squirrel. On Windows, NSIS or Squirrel handles the update process. You can host updates on GitHub Releases, S3, or a custom server.

Should I choose Electron or Tauri?

Choose Electron if you need full Node.js and npm ecosystem access, have an existing web app to wrap, or need proven stability at scale. Choose Tauri if binary size and memory usage are critical, your team knows Rust, or you are building a lightweight utility. Electron has a larger ecosystem and more production deployments, while Tauri offers smaller binaries and lower resource consumption.

𝕏 Twitterin LinkedIn
Cet article vous a-t-il aidé ?

Restez informé

Recevez des astuces dev et les nouveaux outils chaque semaine.

Pas de spam. Désabonnez-vous à tout moment.

Essayez ces outils associés

{ }JSON FormatterJSJavaScript MinifierTSJSON to TypeScript

Articles connexes

Guide Tauri 2026 : Apps Desktop Légères et Cross-Platform avec Rust

Guide complet Tauri : backend Rust, frontend web, Tauri 2.0, commandes, événements, plugins, sécurité, auto-updater et support mobile.

Guide Patterns React: Compound Components, Custom Hooks, HOC, Render Props & State Machines

Guide complet patterns React: compound components, custom hooks, HOC, render props, provider pattern, state machines et error boundaries.

Guide Complet Playwright E2E Testing

Apprenez Playwright pour les tests E2E.