Flux Blog

News, resources, and company updates

Flux + GPT-5 (Beta)

Open Flux now, switch Copilot to “Next-gen” and see how it handles your next design challenge. The sooner you try it, the more your feedback can shape the next leap in AI-powered hardware design.

|
August 11, 2025
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Explore the Advantages of Buck and Boost Converter in Modern Electronics

Explore the Advantages of Buck and Boost Converter in Modern Electronics

Buck and Boost converters are highlighted for their power efficiency and system reliability roles. The blog reveals their unique advantages, making them essential in diverse applications like renewable energy and portable electronics.

Buck Converter: The Inductor-Driven Step Down Marvel

A simplified circuit diagram of a buck converter or step-down converter
Buck Converter Topology

Principle of Operation

A Buck converter serves as a step-down DC-DC converter, adept at transforming a higher input voltage to a lower, regulated output voltage (Vout). The core components include an inductor, a diode, a switch (commonly a MOSFET), and a capacitor. By modulating the pulse-width modulation (PWM) duty cycle of the MOSFET, the Buck converter fine-tunes the Vout.

Advantages

  1. High Efficiency: Buck converters excel in recycling excess voltage through the inductor, achieving efficiencies often above 90%.
  2. Minimal Heat Dissipation: The high-efficiency operation of the Buck converter inherently curtails heat generation, mitigating the need for heat sinks or other cooling systems.
  3. Broad Input Voltage Spectrum: These converters can handle a wide array of input voltages, making them versatile in diverse applications like solar power systems and automotive electronics.
  4. Swift Transient Response: The Buck converter's rapid transient response to changes in load or input is a crucial asset in real-time applications.

Boost Converter: The Voltage-Elevating Specialist

A simplified circuit diagram of a boost converter or step-up converter
Boost Converter Topology

Principle of Operation

In contrast to the Buck converter, a Boost converter acts as a step-up DC-DC converter. It elevates a lower input voltage to a higher Vout. The essential components—inductor, diode, MOSFET, and capacitor—are arranged differently to achieve this function.

Advantages

  1. Voltage Amplification: Boost converters can significantly elevate the input voltage, making them invaluable in low-voltage applications like photovoltaic systems.
  2. Compact Footprint: The inductor-centric design of the Boost converter allows for a more compact form factor compared to transformer-based solutions.
  3. High Efficiency: Similar to Buck converters, Boost converters also maintain high efficiency, particularly when the voltage differential is minimal.
  4. Inrush Current Limitation: The inductor inherently restricts inrush current, adding an extra layer of system protection.

The Versatility of Buck-Boost and Sepic Converters

For systems that require both step-up and step-down voltage regulation, Buck-Boost and Sepic (Single-Ended Primary Inductor Converter) converters offer a flexible solution. They can function as either a Buck or a Boost converter, depending on the input voltage and system demands.

Special Mention: Flyback and Inverting Converters

Flyback converters are useful for applications requiring isolated outputs, while inverting converters can invert the polarity of the output voltage, expanding the range of potential applications.

The Significance of These Converters in Modern Electronics

  1. IoT Devices: The Internet of Things (IoT) is burgeoning, and with it comes the need for low-power, high-efficiency devices—perfect candidates for Buck and Boost converters.
  2. Electric Vehicles (EVs): EVs, with their varying voltage levels and subsystems, stand to gain significantly from these power converters.
  3. Renewable Energy Systems: In solar and wind energy setups, where voltage can fluctuate, these converters ensure a stable output for either storage or immediate use.
  4. Portable Electronics: Battery-operated devices like smartphones and laptops benefit from efficient power management, a role well-suited for these converters.

Conclusion

Buck and Boost converters, as specialized DC-DC converters, have become irreplaceable in the realm of modern electronics. Using simple components and concepts, like inductors, capacitors, MOSFETs, and PWM control, Buck and Boost converters work miracles for power circuits. Their unique advantages in terms of efficiency, versatility, and compactness make them indispensable in shaping the future of power management solutions.

|
September 16, 2023
Discovering PCB Manufacturing: Technologies That Shape the Industry

Discovering PCB Manufacturing: Technologies That Shape the Industry

In this blog, you'll get an insider's look at PCB manufacturing, learn how PCB boards have evolved, and why they're vital in almost every piece of tech you use. We cover all the bases from circuit board printing for basic gadgets to the advanced techniques used by top PCB manufacturers for multilayer boards. The blog also sheds light on upcoming tech that could redefine the industry. It's essential reading for anyone interested in electronics or PCBs.

Evolutionary Milestones in PCB Manufacturing

The industry of PCB manufacturing has undergone significant transformations since its early days in the 20th century. Initially confined to single-sided circuit boards, technological advancements have enabled the development of more intricate double-sided and multilayer PCBs.

The Indispensable Role of PCBs in Modern Technology

In today's technology-driven world, the importance of PCB manufacturing is monumental. These boards are essential for the functionality and reliability of a wide array of electronic systems, making their fabrication a cornerstone of industrial processes.

Categories of PCB Manufacturing

Single-Sided PCB

Understanding and Applications of Single-Sided PCBs

Single-sided PCBs feature only one layer of conductive material, typically copper, and are ideal for low-density designs. These types of circuit boards are prevalent in simple electronic devices like radios and sensors.

Fabrication Process for Single-Sided PCBs

The fabrication involves applying a copper layer on one side of an insulating substrate. The unwanted copper is then etched away, leaving the desired circuit pattern. Soldering components onto the board follows this.

Double-Sided PCB

What Are Double-Sided PCBs and Where Are They Used?

Double-sided PCBs have copper layers on both sides of the substrate, allowing for more complex circuits. These are commonly found in sophisticated devices like smartphones and automotive control systems.

Manufacturing Workflow for Double-Sided PCBs

The process includes applying copper layers on both sides of the substrate and connecting the layers using vias. Soldermask is then applied, followed by the HASL (Hot Air Solder Leveling) or ENIG (Electroless Nickel Immersion Gold) finishing process.

Multilayer PCB

Defining Multilayer PCBs and Their Use Cases

Multilayer PCBs consist of multiple conductive layers, separated by insulating material, and are used in highly complex systems like medical equipment and data servers.

Multilayer PCB Fabrication

The fabrication, or stackup, involves layering multiple sheets of copper and insulating material, which are then pressed together under heat and pressure. Circuit patterns are etched onto each layer, and vias are used to connect them.

Key Stages in PCB Manufacturing

Design and DFM (Design for Manufacturability)

The initial stage involves creating a detailed design of the circuit using CAD software, often incorporating DFM principles to ensure efficient manufacturing.

Substrate Creation and Stackup

The substrate, usually made from materials like FR4 or Polyimide, is fabricated to provide mechanical support to the circuit board. This is followed by the stackup process, where multiple layers are combined.

Copper Layering, Etching, and Finishing

Copper layers are applied to the substrate, and the circuit pattern is etched using chemical processes. The board then undergoes various finishing processes like applying soldermask and silkscreen, followed by HASL or ENIG surface finishing.

The Future Landscape of PCB Manufacturing

Technological Innovations on the Horizon

Emerging technologies like 3D printing and AI-driven optimization are set to redefine the PCB manufacturing sector.

Sustainability and Eco-Friendly Manufacturing

The industry is increasingly focusing on sustainable materials and eco-friendly fabrication processes to mitigate environmental impact.

Challenges and Opportunities

The demand for smaller, more efficient PCB boards presents both challenges, such as material limitations, and opportunities for innovation and technological breakthroughs.

Conclusion

Understanding the intricacies of PCB manufacturing, from the types of PCBs to the key stages in their fabrication, is crucial for anyone involved in the electronics or electrical engineering sectors. As technology continues to evolve, the PCB manufacturing industry is set for transformative developments that will significantly influence the future of electronics.

|
September 1, 2023
The Ultimate Guide to Electrical Connectors and Wiring Connection

The Ultimate Guide to Electrical Connectors and Wiring Connection

This comprehensive guide explores the roles and types of electrical connectors in any wiring project. From crimping tools to wire strippers, it outlines the tools and techniques needed for efficient electrical wiring. The post also provides safety tips and insights into specialized connectors.

Types of Connectors

Wire Connector

Wire connectors come in various types, such as wire nuts, Wago connectors, and crimp connectors. Wire nuts are simple but effective, sometimes used to splice together small AWG (American Wire Gauge) wires. The twist and insulating properties of wire nuts make them popular in residential wiring projects.

Crimp Connectors

Crimping involves placing a metal conductor inside a crimp and using a crimping tool to deform the crimp, enclosing and pressing together the conductor securely. Crimped connections are durable and reliable when done correctly. Crimping is often used for electrical wire splicing and terminal applications.

Solder Connectors

In solder connectors, the conductor is soldered to ensure a robust electrical connection. While soldering requires a soldering iron and solder, the resulting connection is extremely stable and strong. These are common in PCB (Printed Circuit Board) and other high-stake electrical wiring.

Other Types

Wago connectors provide a lever-action to clamp down on the wire. They are often used for stranded wire and offer a reusable solution. DC connectors are used in low-voltage applications and are color-coded for positive (RED) terminal and negative (BLACK) terminal to prevent mistakes.

Key Considerations

Insulation

Insulation is another crucial factor. The insulation around the wire should be stripped using a wire stripper to expose the conductor before using any connector. Insulated connectors provide an extra layer of safety.

Wire Gauge

The gauge wire chosen should match the requirements of the circuit and the connector. Using a wire gauge that's inappropriate can lead to overheating or inefficiency. Can sometimes lead to intermittent connection.

The American Wire Gauge (AWG) is a standard system used primarily in the United States to denote the diameter of electrically conducting wire. The current capacity of a wire varies depending on several factors, such as the insulation type, ambient temperature, and whether the wire is in free air or bundled with other wires.

This table provides a rough estimate of the current-carrying capacity of copper wires with different AWG sizes, typically used for chassis wiring.

| AWG Size | Diameter (mm) | Current (Amps) for Chassis Wiring | | :=== | :=== | :=== | | 0000 | 11.684 | 302 | | 000 | 10.405 | 239 | | 00 | 9.266 | 190 | | 0 | 8.252 | 150 | | 1 | 7.348 | 119 | | 2 | 6.544 | 94 | | 3 | 5.827 | 75 | | 4 | 5.189 | 60 | | 5 | 4.621 | 47 | | 6 | 4.115 | 37 | | 7 | 3.665 | 30 | | 8 | 3.264 | 24 | | 9 | 2.906 | 19 | | 10 | 2.588 | 15 | | 11 | 2.304 | 12 | | 12 | 2.053 | 9.3 | | 13 | 1.828 | 7.4 | | 14 | 1.628 | 5.9 | | 15 | 1.450 | 4.7 | | 16 | 1.291 | 3.7 | | 17 | 1.150 | 2.9 | | 18 | 1.024 | 2.3 |

Conductor Material

Copper is the most common conductor material. The quality of the conductor affects the reliability of the electrical connector.

Voltage Rating and Circuit Breaker

Always consider the voltage and the circuit breaker involved. Incorrectly matched connectors and circuit breakers can result in electrical fires or other hazardous conditions.

How to Use Connectors

  1. Wire Preparation: Use a wire stripper to strip the insulation off the wire ends.
  2. Select Connector: Choose the right electrical connector based on your wiring needs.
  3. Connect Wire: Insert the stripped conductor into the connector.
  4. Secure Connection: Use a crimping tool for crimp connectors, twist the wire nut, or solder for solder connectors.
  5. Test: Always test the electrical connection before incorporating it into your circuit.
  6. Insulate: Finally, use electrical tape or other insulating material to insulate any exposed wiring.

Safety Tips

  1. Always turn off the circuit breaker before working on any electrical wiring.
  2. Only a qualified electrician should handle complex tasks.
  3. Check for wire connection compatibility and color-coded indications to avoid mismatches.
  4. If you're unsure, consult an electrician.

Specialized Connectors

For data transmission, ethernet connectors are usually used. Junction boxes serve as receptacles for multiple wire connections. For automotive applications, DTL (Deutsch Terminal Lugs) connectors offer robustness against harsh conditions.

Wrapping up

Electrical connectors serve as the backbone for any electrical wiring project. Whether you are splicing, crimping, or soldering, understanding the roles of each connector can make your project efficient and safe. From the humble wire nut to the complex ethernet connector, your choice of connector makes all the difference in ensuring a smooth flow of electricity through your circuit.

So, the next time you take on an electrical project, keep this guide handy to navigate through the complex yet fascinating world of electrical connectors.

Happy Wiring!

|
August 25, 2023
What Makes Good Circuit Simulation Software: Factors to Consider in 2023

What Makes Good Circuit Simulation Software: Factors to Consider in 2023

Circuit simulation is a crucial tool in electronic design. It uses software to predict how circuits will perform, saving time and money. Popular options like Flux, LTSpice, and CircuitMaker offer powerful features.

The importance of circuit simulation cannot be overstated. It assists in the detection of potential design flaws, reduces the need for physical prototyping, and accelerates the development cycle. In 2023, current trends in circuit simulation include the integration of machine learning for predictive modeling, the move toward online simulators, and the adoption of more accurate modeling techniques.

Types of Circuit Simulators

Circuit simulators are typically categorized into analog and digital types. Analog simulators, like SPICE (Simulation Program with Integrated Circuit Emphasis), model continuous signals, while digital simulators model circuits that have a number of discrete states. Some circuit simulators, like Flux's circuit simulator, operate directly in your EDA's schematic diagram. With an understanding of your netlist and schematic diagram, these simulators help verify the functionality of your system.

Options for Circuit Simulation

Circuit simulation can either be performed offline with software installed on a local machine, or online via web-based tools. Online simulators offer several benefits, including accessibility from any device, collaborative features, and easy updates. However, they might be limited in computational power compared to offline options and can be affected by network issues.

Examples of Popular Circuit Simulators

Numerous circuit simulators have gained popularity due to their robust features and user-friendly interfaces. Some of these include:

  • LTSpice: An offline SPICE simulator with powerful simulation and schematic capture features. LTSpice is popular because it's free and available to all.
  • MultiSim Live: An online platform offering SPICE simulation and collaborative features.
  • CircuitMaker: A comprehensive platform for electronic design automation, including simulation and PCB design.
  • EasyEDA: A cloud-based tool for circuit design, simulation, and PCB prototyping.
  • Circuit Lab: An online simulator and schematic editor with a simple, intuitive interface.

Features of Circuit Simulators

The feature set of circuit simulation software can be broad, catering to a wide range of needs:

  • Circuit diagram design: Allows users to create and modify electrical circuit diagrams.
  • SPICE simulation: Simulates the performance of circuits based on SPICE models.
  • PCB design and prototyping: Enables the design of printed circuit boards and the generation of manufacturing files.
  • Electrical circuit design: Assists in designing and simulating electrical circuits and systems.
  • Online simulations and games: Provides interactive learning tools, like PhET Colorado and Every Circuit, to understand electronic concepts.

Benefits of Using Circuit Simulation

Circuit simulation has many advantages. It offers cost-effective circuit design by reducing the need for expensive prototypes. It increases efficiency by streamlining the design process. It improves design accuracy by allowing for extensive testing and validation. It also simplifies troubleshooting by highlighting problem areas in the circuit.

Drawbacks of Using Circuit Simulation

Despite its advantages, overreliance on circuit simulation can have some drawbacks. It can lead to a lack of hands-on experience and a limited understanding of physical circuit components, both crucial for practical applications. It can be difficult to properly simulate the behavior of complex PCBS with dynamic parts like integrated circuit

Conclusion

Being able to simulate a circuit is a critical aspect of modern electronic design. The variety of available simulators cater to diverse needs, offering features ranging from circuit design to PCB prototyping. While the benefits of using circuit simulation are substantial, it's essential to balance its use with practical, hands-on experience. As we look toward the future, we can expect even more advanced and intuitive circuit simulation technologies, further revolutionizing the electronics design landscape.

|
July 24, 2023
Convert your Typescript codebase to No Unchecked Indexed Access

Convert your Typescript codebase to No Unchecked Indexed Access

Describes Flux.ai's process of enabling 'noUncheckedIndexedAccess' in their TypeScript codebase. This setting enhances type safety by enforcing checks for possible 'undefined' values but introduces numerous type errors in a large codebase. To manage this, Flux.ai used heuristics and automation to suppress new errors with '!' and automate fixes using a provided script.

Introduction

Flux.ai was started around 3 years ago in TypeScript with the default compiler settings. If we could go back in time, there is one setting we would surely change: noUncheckedIndexedAccess. By default, this setting is false. Many people believe it should be true.

The flag

What does noUncheckedIndexedAccess do? By default, TypeScript assumes any array element or object property you access dynamically actually exists:

function uppercaseFirst(str: string) {
  return str[0].toUpperCase() + str.slice(1);
}

uppercaseFirst('') // runtime error BAD!!!

In the example above, the function will throw an error if the string is empty, because str[0] returns undefined and doesn't have a toUpperCase function. TypeScript doesn't warn you about that, regardless of whether strict mode is enabled or not. This is a huge hole in type safety.

The flag noUncheckedIndexedAccess will plug that hole and force you to deal with the possible undefined:

function uppercaseFirst(str: string) {
  return str[0]?.toUpperCase() + str.slice(1); // note: ? nullish operator
}

uppercaseFirst('') // returns ''

So, why can't we just turn on noUncheckedIndexedAccess? You can, but in a large codebase like that of Flux.ai, you are likely to get thousands of type errors. We had 2761 errors across 373 files! For one speedy engineer converting one file every minute, it would have taken 6+ hours of mind-numbing work to convert all 373 files.

The solution we describe here is how to smoothly convert your codebase with some simple heuristics and automation.

Heuristics

According to Wikipedia, a heuristic technique

is any approach to problem solving or self-discovery that employs a practical method that is not guaranteed to be optimal, perfect, or rational, but is nevertheless sufficient for reaching an immediate, short-term goal or approximation.

That is definitely true here.

The goal was to get the codebase compiling with the new flag, not to fix any bugs. The fixing can come later.

To that end, we intentionally added type assertions ! to suppress all new type errors from undefined types without changing the runtime behavior of the code.

const firstLetter = str[0] // needs too be str[0]!
const rest = str.slice(1)
const upperFirst = firstLetter.toUpperCase()

Expanding the scope of replacements to preceding lines allowed us then to automate more fixes with few false positives.

Automation

The full script we ran on our codebase is below. Note: it did not fix all the errors. It fixed around 2400 out of 2761 errors, leaving around 100 files for us to fix by hand.

Pro-tip: when experimenting with the replacers and precede, you can simply reset your changes with git reset --hard HEAD (assuming you are working in a git repo).

#!/usr/bin/env ts-node

// To generate noUncheckedIndexedAccess.txt, run
// $ npx tsc | grep 'error T' > noUncheckedIndexedAccess.txt

import {readFileSync, writeFileSync} from "fs";

type ErrorLines = {path: string; lineNum: number; message: string}[];

// NOTE: these should be idempotent for safety!
const replacers: [RegExp, string][] = [
    [/(\w+\.\w+\.\w+)\.(\w+)/g, "$1!.$2"], // a.b.c.d to a.b.c!.d
    [/(\w+\[(\w|\.)+\])!*/g, "$1!"], // add ! after []
    [/(\w+\])(\[\w+\])/g, "$1!$2"], // add ! between [][]
    [/(\[\w+\])(\.\w+)/g, "$1!$2"], // add ! between [] and .
    [/(\[\d\]?)!*/g, "$1!"], // add ! after [0]
    // START CORRECTIONS
    [/\]!\) =>/g, "]) =>"], // correcting add ! above
    [/\]! =/g, "] ="], // correcting add ! above
];

const precede = 2;

function main() {
    const txt = readFileSync("./noUncheckedIndexedAccess.txt", "utf-8");
    const errorLines = parseErrorLines(txt);
    errorLines.forEach((errorLine) => {
        let lineText = readLine("../" + errorLine.path, errorLine.lineNum, precede) as string;
        replacers.forEach(([match, replacement]) => {
            const newLineText = getNewLineText(lineText, match, replacement);
            if (newLineText) lineText = newLineText;
        });
        console.log("\n---");
        console.log(errorLine.path, errorLine.lineNum, "\n", lineText);
        console.log("---\n");
        writeLine("../" + errorLine.path, errorLine.lineNum, lineText, precede);
    });
}

function getNewLineText(lineText: string, match: RegExp, replacement: string) {
    return (
        lineText
            .split("\n")
            // @ts-ignore: ignore missing string method
            .map((line) => line.replaceAll(match, replacement))
            .join("\n")
    );
}

function parseErrorLines(txt: string): ErrorLines {
    return txt
        .split("\n")
        .filter(Boolean)
        .map((line) => {
            const [pathPlus, message] = line.split(": error ");
            const pieces = pathPlus?.split("(");
            if (!pieces || !pieces[0] || !pieces[1] || !message) {
                throw new Error(`Missing bits in line: ${line}`);
            }
            const numberPieces = pieces[1].split(",", 1);
            if (!numberPieces || !numberPieces[0]) {
                throw new Error(`Missing numbers in pieces: ${pieces}`);
            }
            const lineNum = parseInt(numberPieces[0], 10);
            if (!(lineNum > 0 && lineNum < 1000000)) {
                throw new Error(`Bad line number: ${lineNum}`);
            }
            return {
                path: pieces[0],
                lineNum,
                message,
            };
        });
}

function readLine(filename: string, lineNum: number, precede: number) {
    const lines = readFileSync(filename, "utf8").split("\n");
    return lines.slice(lineNum - 1 - precede, lineNum).join("\n");
}

function writeLine(filename: string, lineNum: number, lineText: string, precede: number) {
    const lines = readFileSync(filename, "utf8").split("\n");
    lines.splice(lineNum - 1 - precede, precede + 1, ...lineText.split("\n"));
    writeFileSync(filename, lines.join("\n"));
}

main();
|
May 19, 2023
How to replicate data from the main thread to a web worker using ImmerJS

How to replicate data from the main thread to a web worker using ImmerJS

In this blog post, we explore how Flux.ai effectively uses Web Workers and ImmerJS to enhance data replication in our web-based EDA tool. We discuss our challenges with data transfer, our exploration of SharedArrayBuffer, and our ultimate solution using ImmerJS patches.

Introduction

Web Workers are an established browser technology for running Javascript tasks in a background thread. They're the gold standard for executing long-running, CPU-intensive tasks in the browser. At Flux.ai, we successfully harnessed Web Workers, paired with ImmerJS patches, to minimize data transfer and deliver an ultra-fast user experience. This post will take you through our journey of using Web Workers and ImmerJS for data replication in our web-based EDA tool.

The Problem

Flux.ai, an innovative web-based EDA tool, needs to compute the layout of thousands of electronic components simultaneously for its unique PCB layouting system. This process must adhere to user-defined rules. Our initial prototype revealed that layouting could take several seconds, leading us to explore the capabilities of Web Workers to parallelize this process and unblock the UI.

At bottom, the web worker API is extremely simple. A single method, postMessage, sends data to a web woker, and the same postMessage method is used to send data back to the main thread. We use a popular abstraction layer on top of postMessage, Comlink, developed several years ago by Google, that makes it possible to call one of your functions in a web worker as if it existed in the main thread. Newer, better or similar abstractions may exist. We did learn in using Comlink that it can easily blow up your JavaScript bundle size.

The trouble with using a web worker in a pure RPC style is that you most likely have a lot of data to pass through postMessage which is as slow as JSON.stringify, as a rule of thumb. This was definitely true in our case. We calculated that it would take 100ms at our desired level of scale just to transfer the layouting data each way, eating into the benefit of a parallel web worker.

Exploring SharedArrayBuffer for Data Transfer

A potential solution to the data transfer problem could be using SharedArrayBuffer, recommended for use with web workers. However, SharedArrayBuffer "represents a generic raw binary data buffer" meaning that a) it is of fixed size and b) it does not accept JS objects, strings, or other typical application data. Our investigations led us to conclude that the performance benefits were offset by the encoding and decoding costs in SharedArrayBuffer. One hope for the future is a Stage 3 ECMAScript proposal for growable ArrayBuffers.

The Solution

We decided instead to populate our web worker with all the data on initial load of a Flux document (while the user is already waiting) and update it with changes as they happened. An added benefit of this approach is that the functions designed to run inside the web worker can also be run in the main thread with the flip of a global variable. You might want to do this for Jest tests, for example, which do not support web workers by default.

We got our changes in document data from ImmerJS, something we were already using as part of Redux Toolkit. Immer is an extremely popular library that enables copy-on-write for built-in data types via a Proxy. A lesser-known feature of Immer is Patches. The function produceWithPatches will return a sequence of patches that represent the changes to the original input.

We made a function that wraps produceWithPatches and assigns the patches back into the document for use downstream.

//
// in helpers.ts
//
export function withPatches(
  document: IDocumentState,
  mutationFn: Parameters[1]
): IDocumentState {
  const [newDocument, forward] = produceWithPatches(document, mutationFn);
  if (forward.length === 0) {
    return newDocument;
  } else {
    return produce(newDocument, (draftDoc) => {
      draftDoc.latestPatchSeq = forward;
    });
  }
}

//
// in reducers.ts
//
const documentReducer = (
    state: IDocumentState | null = documentInitialState,
    action: IDocumentReduxAction,
): IDocumentState | null => {
    if (!state) {
        // note, we don't create patches on the first load of the document
        if (action.type === Actions.loadDocumentActions.successType) {
            return action.response
        }
        return state;
    } else {
        return withPatches(
            state,
            (draftState) => {
                if (isAnyOf(Actions.setSubjectProperties)(action)) {
                // ... do mutations
            }
        )
    }
}

With the patches in hand, we could then complete our data flow from main thread to web worker and back again. The main thread calls the worker functions from middleware after every global state change. In Flux, we use redux-observable middleware.

More Code Samples

In the code, the relevant functions look like this, assuming you are using Comlink.

//
// in LayoutEngineInMain.ts
//
import Comlink from "comlink-loader!./LayoutEngineInWorker";
import { Patch } from "immer";

const comlink = new Comlink();

export async function setInitialDocumentState(
  documentState: DocumentState
): void {
  comlink.setInitialDocumentState(documentState);
}

export function applyDocumentPatches(patches: Patch[]): Patch[] {
  const layoutPatches = comlink.applyDocumentPatches(patches);
  // apply these patches to the global state in middleware
  return layoutPatches;
}

//
// in LayoutEngineInWorker.ts
//
import { Patch, applyPatches } from "immer";
import { LayoutEngine, DocumentState } from "./LayoutEngine";

let documentState: DocumentState | undefined;

export function setInitialDocumentState(state: DocumentState): void {
  documentState = state;
}

export function applyDocumentPatches(patches: Patch[]): Patch[] {
  if (documentState === undefined) {
    throw new Error("First call setInitialDocumentState");
  }
  documentState = applyPatches(documentState, patches);
  return new LayoutEngine(documentState).recomputeLayout();
}

Results: Speedy Data Replication with Web Workers and ImmerJS

The result of our use of Web Workers and ImmerJS patches was a significant reduction in workload on every document change and the ability for users to continue interacting with the application during a large re-layout - a priceless benefit in our web-based EDA tool.

Extra Credit: Boosting Speed with ImmerJS

For extra speed in our web worker, we forked the Immer applyPatches function. The original version was too slow for our needs. So, we adapted applyPatches to skip the draft step and mutate the target object in-place, resulting in a 10X speedup.

In conclusion, Web Workers and ImmerJS have proven to be powerful tools for efficient data replication in Javascript, particularly in the context of our web-based EDA tool, Flux.ai. They offer a potent combination for handling complex, CPU-intensive tasks, and improving user experience through faster data transfer and processing.

|
May 18, 2023