News for hackers. Stuff that matters.
Re:Node.js 16 Available Now by jitl on Tuesday April 20, 2021 @05:52PM (#26882298)
Notion shares a large amount of code between the front-end and back-end. We have many algorithms, collections, helpers, etc that we share. Here's an example, we have a shared loadPageChunk function that takes a cursor and a loader implementation, then traverses our data graph to gather the data needed to render part of a page.

    // shared code - implement the algorithm
    export async function loadPageChunk(
     args: LoadPageChunkArgs,
     loadRecordValue: loadRecordValueFn
    ) {
      // ...
    }
    
    // client code - use the algorithm, provide client-specific IO
    // eg on Android we'd use Sqlite.
    const records = await loadPageChunk(cursor, SqliteService.loadRecordValue)
    
    // Server code - same, but use the server's data stores.
    // Behind the scenes, these loaders batch, etc
    const records = await loadPageChunk(cursor, useCache ? CacheService.loadRecordValue : PostgresService.loadRecordValue)
Even if we only shared types, there's a significant benefit. We try to push as much logic into the type system as we can; for example we use discriminating unions to define different groups of related types. Eg, we have a union type called ContentBlock that has all the specific block types that can have children, `Page | Text | Column | ...`, sharing this type and its helper functions like `isContentBlock(block: BlockValue): block is ContentBlock` means both our front-end and back-end code rely/expect/enforce the same invariants.

There are no comments on this comment yet.