Back to "Låt oss prata om det."

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

.NET C# gRPC Interop JavaScript Node.js Packing SQLite

Låt oss prata om det.

Friday, 13 November 2026

Noder kan ladda en .NET assemblage och ropa på dess C-metoder utan att starta något annat process.

Båda runtimen körs i samma process.

Vi kommer att bygga båda riktningarna runt ett praktiskt exempel. :, med hjälp av vår De mest tydliga.Packning bibliotek. Noder ropar på C# för att hitta och reservera möten ; en M SK3 NET-applikation ropar sedan på den delade JavaScript formatteren genom ett inbyggdt nodMSC4 Vi mäter också latensiteten och minnesövertagningen mot en gRPC-bistol

Den sällskapliga prover inkluderar kompletta projekt och benchmark harness

Varför använda C# inuti en existerande nod-applikation

Vi har redan skrivit resourcen, -, packningsregler i ., NET och :, vilka anställda är kvalificerade för en tjänst. ,, när utrustningen behövs.,, och hur man sparar allt tillsammans. ., genom att ringa in den där biblioteket från Node-appn kan vi behålla reglerna på samma plats.

Vi kan ladda biblioteket till Node eller lägga det bakom en tjänst:

Design Vad noderanwendungen gör ♫ ♫ Vad vi är ansvariga för ♫
Iprocessmodulen node-api-dotnet Loading . Net och inhemska beroenden inuti noderprocessen
gRPC sidecar skickar ett begäran till en separat . NET-tjänster Hosting МSK4 övervakning och kommunikation med en annan process

Att lagra biblioteket i Node för att undvika HTTP: s ringfärder/2 . En motordrivare kör motorn i en separat process, så den kan falla eller återstarta oberoende av webappletM SK3 Appen väntar på sin respons asynkronisktMSC4 och flera applikationsprocesser kan använda samma tjänstMST5

Vi ska mäta båda arrangemangen med samma C-implementation. Det låter oss jämföra angreppsöverskott och minnesförbrukning utan att ändra schemaalgoritmen.

Funktionen : antyder, previewM SK2 reserv

Alice vill ha geler, . Beth vill ha pedicure,. De vill börja tillsammans,. Varje möte behöver en kvalificerad tekniker och den lämpliga stationen.

Frågan går genom det existerande bakprogramet:

sequenceDiagram
    participant Browser as Existing calendar UI
    participant Node as Existing Node backend
    participant Engine as C# packing engine
    Browser->>Node: Find appointments within this window
    Node->>Engine: FindTogether(window, services)
    Engine-->>Node: Candidate, assignments and revision
    Node-->>Browser: Suggested calendar events
    Browser->>Node: Accept this candidate
    Node->>Engine: TryHold(candidate, command ID)
    Engine-->>Node: Hold accepted or rejected
    Node-->>Browser: Show held appointments or refresh suggestions

Ett förslag är förenklat.. Någon kan ta plats medan användaren tittar på kalendern.

“AutoM SK1planering” betyder att hitta en genomförbar gemensam tjänstgörelse under deklarerade begränsningar . Det här exemplet ordnar inte upp hela dagen eller ger ett globalt optimalt plan

kör arbetsexemplet

Använd .NET | 10 | och nod |22. | Håll mostlylucid.packing och mostlylucidweb som syskonkontroller, och sedan springa från mostlylucidweb/samples/NodePacking:

npm ci
npm run build
npm run booking

Ni borde se:

alice: gels with sarah
beth: pedicure with anna
Both appointments confirmed.

Den exempel README har klona kommandor och instruktioner för att använda en annan checkout-position. Sampleset bygger packningsversionen från källan

Sampleset använder 3 juni 2030, en fixerad klocka och en in-memory-databank, så att varje lopp börjar med samma tillgänglighet.

1. Beskriv de resurser som programmeraren måste respektera

Ett tomt kalenderslot säger inte till oss om en kvalificerad tekniker och rätt utrustning är tillgänglig.

Alices appointment med gelbeläggning tar upp dessa resurser

Avset från början Etappe Bevarade resurser
0–15 minuter förbereda Sarah och manicure stationen МSK4
15–35 minuter torr Manikürstation och lampe МSK4
35–45 minuter avsluta Sarah och manicure stationen M
45–55 minuter Reset Manikurstationen M

Till exempel , i det här stadiet säger att lampan behövs från minuten 15 till minuten

new ServiceStage(
    "dry",
    TimeSpan.FromMinutes(15),
    TimeSpan.FromMinutes(20),
    ["station", "lamp"])

station och lamp är rollnamen . Servicedefinitionen säger vilka förmågor som kvalificerar en resurs för varje roll. Motorn tillhandahåller resurser till dessa roller

Sarah är inte upptagna under torrningen. Hon behövs igen för att färdigställa. Stationen är fortfarande upptagen efter Alice ' kunderna M SK3 mötesbesöket slutar eftersom det behöver ställas om . En sökning nära slutet av tiden måste passa in i den ställningen också MSC5

Den kompletta salondefinition deklarerar Sarah, AnnaM SK1 två stationen , en lampe , tjänster och ett femminuterstimmarsnät M SK5 Du kan byta dessa deklarationer för att pröva olika personal- eller utrustningsbegränsningar MSC6

2. Fråga motorn CM SK1 om ett gemensamt möte

I C#, kombinerar ett kalender med en definition och en reservationsbutik

var definition = SalonDefinition.Create();
using var store = new SqliteCalendarStore(":memory:", definition);
var calendar = Pack.Calendar(definition, store);

Sampeln's exporterade klass tillhandahåller också den fixera klocken . För att hitta en starttid för båda kunderna

var result = calendar.FindTogether(
    from, to,
    [new BookingRequirements("gels", "alice"),
     new BookingRequirements("pedicure", "beth")],
    limit: 1);

Här from och to är DateTimeOffset värden. Resultatet består av en kandidat vars nominationer delar starttid , med resursfördelar för varje tjänst M SK2 sökfenon gränsar hela resursavtrycket , inklusive återställingsstader MSC4

limit: 1 begär en återvänd match. Prüfa CandidatesComplete innan man tolkar ett tomt resultat Version identifierar reservationsvalet som används för sökningen.

bryggan håller CalendarMatch i C#. JavaScript får dess ID och de nominationsfällor som behövs för att kunna se fram. När användaren accepterar,, ser bryggan upp den som matchar och sparar dess resurser. Browsern skickar inte fram resourcesbehovet

3. Exposera den operationen till noden

Vi använder Microsoft.JavaScript.NodeApi och dess generator, ,, kopplad till 0.9.36. tillämpar [JSExport] till vår Salon klass gör sina offentliga metoder tillgängliga som nodermodul. skapad moduls arbetsflöde.

Lade upp den genererade modulen från dess montageväg:

import { fileURLToPath } from 'node:url';
import dotnet from 'node-api-dotnet/net10.0';

const assembly = fileURLToPath(new URL(
    './PackingBridge/bin/Release/net10.0/PackingBridge.dll', import.meta.url
));
const { Salon } = dotnet.require(assembly);

PackingBridge.dll är en skött .NET assemblage. Paketet hostar .NET inuti Noden och laddar dess exporterade metoderM SK3 Uppmanade gränser mellan JavaScript och | . | NET i den processen

Använda dotnet.require() för det exporterade modulet. Det separata dotnet.load() API är till för att ladda godtyckliga assembler och få tillgång till deras offentliga typer genom .NET Namespacer Referens för JavaScript beskriver båda.

För den prövade npm-versionen, är importen node-api-dotnet/net10.0. Ett äldre dokumentationsexempla innefattar .js, som misslyckas med detta paket

Släng inskrivna objekt genom gränsen

BuchungsAPIn återvänder C# objekt direkt

public SearchOffer FindTogether(SearchWindow window)

begäran är en liten struktur med namn på fält:

public struct SearchWindow
{
    public string Start { get; set; }
    public string End { get; set; }
}

På nodersidan, accepterar exporterad metod ett objekt:

const session = new Salon(':memory:');
const offer = session.findTogether({
    start: '2030-06-03T10:00:00Z',
    end: '2030-06-03T12:00:00Z'
});
console.log(offer.appointments[0].technician);

Generatoren producerar deklarationer för SearchWindow, SearchOffer, AppointmentView och ReservationResult. Deras metoddeklaration är nu

findTogether(window: SearchWindow): SearchOffer;

Det finns ingen serialiserad JSON-sträng mellan denna sändning och metoden C# outcome, candidatesComplete, candidateId och appointments. Håller och bekräftar också återskapar inskrivna resultat kontraktsfilar definierar exporterade fält. Datums fält förblir ISO-strängar så att kalendern kan konsumera dem direkt

De TypeScript-deklarationerna beskriver API: t i kompileringsögonblicket.

Kurser och strukturer har olika kostnader

Noder API för .NET kopierar strukturer efter värde. Att läsa ut de resulterande JS-eigenheterna låter inte ' kalla en | . | NET-behållare ♫ . ♫ Vi använder strukturer för begäran och små Buchungssvarningar ♫

Det nesterade sökresultatet använder exporterade kategorier. En klass exponeras genom en wrapper runt det skötta objektet, så att läsa en egenskap korsar sig till .NETM SK3 Att ta bort JSON inte removerar de där samtalenMSC5 radens omvandling eller fördelningar att samla ihop dokumentation förklarar livstid och omvandlingsregler.

Jag försökte göra inspelat sökresultatet till en struktur också, men 0.9.36 generatorn lyckades inte bygga upp dess ställelse- skiffer omvandling. Klassenresultatet som visas här bygger och passerar testerna . Detta är en begränsning av den testade föreställningen och kontraktformaden M SK3 inte ett påstående att strukturresultat i allmänhet inte stödjers

Lees resultatet en gång för webapplikationen

Den JavaScript-wrapper bevarar de bekväma två argument API: n som användes under ett ögonblicksbild av de återfällda egenskaperna in i vanliga JS-data . Det läser varje fält en gång, inklusive varje nominationsfält, utan JSON.stringify eller JSON.parse.

Snapshotet undviker upprepade managed getter sändningar eftersom applikationen bygger kalendrar händelser. Det ger HTTP-skivan uppंकbara datafält för att serialisera ; Att skicka en managed wrapper direkt kan utelämna egenskaper som exponeras genom prototypen. Vi testar att snapshotet överlever en vanlig HTTPM SK3style JSON rund resaMSC4 JSON vid webbläsarens gräns är separerad från JSON mellan noder och Mska5NETMske6

Declarationerna i wrappern' förbehåller genererade C # kontraktstyper npm run typecheck för att kontrollera en TypeScript-konsument, inklusive förväntade fel på ett felaktigt parametrtyp och en okänd resultat- egenskap ValueType bas för strukturer, så den här checken använder skipLibCheck för beroende deklarationer. konsumentfältet och argumenten är fortfarande kontrollerade ; det är inte en ren kontroll på generatorn

4. Hitta en förslag från Nodes baksida

Med lådan laddad, ser applikationskod ut som den här

const salon = createSalon(':memory:');
const offer = salon.findTogether(
    '2030-06-03T10:00:00Z',
    '2030-06-03T12:00:00Z'
);

if (!offer.candidateId) {
    throw new Error(`No joint appointment: ${offer.outcome}`);
}

Den [from, to] värden kommer från användaren' det ausgewählta vensteret i den existerande appen . konstruktionen har Alice' och BethM SK3 servicebehovet byggt in i bron ; applikationsAPI skulle acceptera validerad service

Angebotet består av två affischer för att visas: Alice ' geler med Sarah M SK2 och Beth ' pedicure med Anna MSC4 båda från 10:00 UTC MST6 Det bär också kandidaten ID MSV7 revisions- och komplettitetsflaggen M SV8 När man får reda på att programmet inte har ändrat kapaciteten

Datum överskrider gränsen som ISO-timmar med avvikelser. Håll det budskapet oföränderligt genom baksidan , och låter kalendern i konfigurerad tidszon handlera displayen

5. Dodaj föreslagna händelser till den existerande kalendern

Vår Kalenderadapter kartlägger valprojektionerna till händelseobjekt

export function toCalendarEvents(offer) {
    return (offer.appointments ?? []).map(appointment => ({
        id: `${offer.candidateId}/${appointment.clientId}`,
        title: `${appointment.clientId}: ${appointment.serviceId} (${appointment.technician})`,
        start: appointment.start,
        end: appointment.end,
        editable: false,
        extendedProps: { candidateId: offer.candidateId, state: 'suggested' }
    }));
}

Ge tillbaka de händelserna tillsammans med programmet från din nuvarande arrangemangs slutpunkt. För en FullCalendar

const preview = calendar.addEventSource(suggestion.events);

Det här är full kalender, ' och dokumenterad händelsefällor, lisädes genom event- källa API. Sampleset testar händelsernas kartläggning . Du' kommer att behöva koppla din avvägningspunkt till den existerande kalenderns gränssnitt

De föreslagna händelserna är inte redigerbara eftersom att dra en självständigt skulle kunna bryta den gemensama Buchungen. preview.remove() och fråga om ett nytt Angebot.

Den markerade möten slutar när kundens service slutar' . Motoren sparar också städtid, så nästa Buchung måste komma från en ny tillgänglighetskontroll även om skärmen verkar ha ett hål

Konnekt till autentiska Buchungsdata

Sampeln äger sin SQLite-reserveringssituation. För att integrera den med en existerande app , karta över appn, ' personalen, M SK3 tjänster, , tillgänglighet och aktiva engagemang i maskinen M SK5 bara kalendereventen vann ' inte tillgångskvalifikationer,, utrustningskapacitet eller återställningsbehov,.

Sök- och bokande måste använda samma källa till beställningsdata. Om du skriver till den gamla Buchungsdatabasen och en separat paketdatabas oberoende av dig , ett misslyckat skrivande kan låta dem inte hålla med om det . Välj vilken komponent som äger beräkningar och hur den andra läser eller uppdaterar dem innan man lägger in schemat i appn M SK3

6. Håll kandidaten, ,, och bekräfta den

När användaren accepterar föreställningen

const commandId = randomUUID();
const hold = salon.tryHold(offer.candidateId, commandId);
if (!hold.success) throw new Error(hold.reason);

const confirmation = salon.confirm(hold.reservationId, randomUUID());
if (!confirmation.success) throw new Error(confirmation.reason);

randomUUID kommer från node:crypto. En kommando ID identifierar en operation , så att en repetition av samma operation måste återanvända dess ID

Bridgen som utgör C: n är #.

calendar.TryHold(commandId, "alice", match, TimeSpan.FromMinutes(5));

match är den förvarade maskinens resultat. SQLite-butiken förvärvar de länkade kraven i en affär

Vårt korta exempel bekräftar det omedelbart. En applikation skulle istället kunna behålla hållet medan användaren completerar en överprüfung eller betalande steg , och sedan bekräfta eller avbryta den enligt den strömmen

I längre demo, två anslutningar söker samma affär innan de båda sparar något . utgången visar vad som händer när båda försöker använda resultatet

First hold: true
Same command returns same reservation: true
Competing stale offer accepted: false
Sarah free during drying: true
Sarah free during finishing: false
Confirmed: true

Detta kontrollerar ett föråldrade förslag med hjälp av en upprepad sekvens av samtalen. Samma processer skulle behöva en separat stresstest

Bestämningen antar att Alice kan boka för Beth Salon instance: omfattningen av den instancen till ett Buchungsverk

Gör det att JSONs radning gör samtalet snabbare?

Det tar bort serialiseringen , men ersättningen kostar också. För att mäta dem Benchmark harness nu jämför tre vägar:

  • Tiktade objekt i processen, inklusive att läsa varje återvända fält i JS-snapshot.
  • JSON i processen - , inklusive serialisering och JavaScript parsing
  • Ett gRPC-bilar, som bär den JSON-responsen i ett protobuf- meddelande.

Alla tre ropar på samma C# sök och bygger samma resultatmodell FindTogetherJson metod är kvar endast för jämförelsen och bilaradaptern. ApplikationenM SK1 använder FindTogether och tryckta resultat.

Benchmarken läser hela resultatet på varje väg. Timing bara skapandet av en skött objektompackare skulle lämna ut arbetet som kalenderappn måste göra senare. Knyckseln kontrollerar den återvända kandidaten och uppgifterna över alla tre vägar , och varje mätt sök utför noggrannhetenskontroller

Latens och sequentiell genomspetsning

mätt på en Apple M5, macOS ARM64, 32 GiB RAMM SK3 Nod v22.15.0 och .NET SDK 10.0.201. Avgasbilen använder Grpc.AspNetCore 2.85.0; som Nodeclienten använder @grpc/grpc-js 1.14.7. Båda | . | NET-händer använder arbetsstation GC

Var och en av tre nya processtestar värmer upp varje aktivitet med 200 sändningar | , | och mäter sedan ♫ 1,500 sändningarna vid samtida sändning | 1 |. | De tre moderna roterar genom loppet | МSK5 | Varje tabelinskrywing är den medianen i den statistiken över testerna | p50 är ett mellantal av ringer latens p95 är den tid i vilken 95% av en testinspelning 's samtalen avslutades

jobb per sändning väg p50 p\95 Sekundära sändningar
Echo a 1 KiB-fält 2 Typobjekt 3 Snapshot av JS 4 5 μs 6 7 mm 8 9 10
Echo a 1 KiB-fält ♫ ♫ ♫ JSON interop ♫
Echo a 1 KiB-fält ♫ ♫ ♫ gRPC ♫
Hitta den gemensama inställningen Typerade objekt МSK2 JS-snapshot
Hitta den gemensama anställningen JSON interop ♫ ♫ ♫
Hitta den gemensama anställningen gRPC ♫ ♫ + ♫ JSON-respons ♫

Det skrivna söket var långsammare vid p50 i den här konstruktionen Det tog ungefär 621 μsM SK1 jämfört med 575μs genom JSON och 718 μ s genom gRPC. I parade testerMSC5 när man läste utskrivet resultat, så kom det ungefär ♫ 33–87 μS till över JSON-versionenMska7 Det utskrivna pMske8 var lägre i den sammanlagda tabelnMsko9 så mätningarna inte stödjer ett överlagde påstående att antingen i -, eller så vinner processen vid varje procentil

Klassbeslagare och den explicita JS-snapshot förklarar varför serialiseringen behöver undvikas' inte är en acceleration. Vi läser fält genom interop-layern och skapar JS objekt för applikationen . För denna lilla uppdragningM SK3 concurrar JSON-encodern / paret som analyserar bra med det arbetetMska5 En annan uppdragingMske6 en annan DTO-form eller förbättrad värdeM Ska7 typmarshalling skulle kunna ändra resultatet Mska8 dessa behöver sina egna mätningar M Ska9

Echokontrollen passerar ett 1 KiB textfält genom varje väg . dess inskrivna version använder en värdestruktur, sen läser den återvända fältetM SK3 Dess JSON-version passerar och tolkar en JSON stringMska4 Även härM Ska5 direkt marshalling har jobb att göraM ska6 den läser och kopierar objektfälten Mska7 Att ta bort JSON ensamma gör det inte M Ska8 gör gränsen fria M ska9

Timmaarens respons är 495 byter när representerad som JSON.

Vad är gRPC överhuvudtaget?

gRPC-tjänsterna ropar FindTogetherJson över en återanvändad enkeltext HTTP/2 koppling på loopback TCP. Clienten följer kanal-användbar vägledning, så att kopplingen bildas innan mätda samtalen sker. Det finns ingen TLSM SK2 proxy eller fjärran nätverk i detta test

I parade tester, var dess sökpM SK1 ungefär 119–282 μs högre än JSON interop och 32–221 μ s högre än den skrivna vägenMSC4 Det innefattar protobufbehandlingarMska5 HTTPMske6 trådens scheduling och JavaScripts återkopplingM Ska7 Föregång handlingar Mska8 Ett fullt skrivt Protobuf försvar skulle ha olika serialiseringskostnaderMskan9 Dessa siffror beskriver adapteret som byggdes härMskar10 snarare än ett fixet överskott för gRPCMsker11

Skillnaderna är små för en enda kalender.-knappklicken.

Det här var en utveckling- maskin som kördes med naturliga skräphantering och annan systemactivitet . samtalen/ kolumnen rapporterar sequentiell strömförbrukning vid samspelning ett . Serverskapacitet under samma belastning M SK4 reservskriver och skriver emotstånd behöver separata tester MSC5

minne: räkna hela arrangemanget

RSS är den inhemska minnen som rapporteras för en process.

Arrangement Initialiserad RSS RSS efter arbetsbelan
Tiktade objekt ♫ + ♫ JS-snapshot ♫ ♫
JSON interop 107.3 MiB M 124.9 MiB
gRPC

Det här är medianskapbilder efter den första korrekta sökningen och efter uppvärmningarna och tidiga arbetslader.. Ingen tvångsmässig V-kollektivation utförs.

Den skrivna vägen minskade inte RSS jämfört med JSON här. Att ta bort textbuffer kan kompenseras genom skötta omloppsmaskiner , kopierade objekt och deras livslängder. En RSS-snapshot kan inte isolera fördelningen av serialiseringskostnader

För gRPC, lägger tabellen till nodesclienten's RSS till bobåten 's arbetslådaM SK3 Att bara titta på klientet skulle gömma större delen av arrangemanget . Uppskattad RSS kan räkna ut delade sidorna mer än en gång MSC5 och samblandningstimmar påverkar bevarade minnen M SK6 De är inte unika fysiska data,

De råresultaten bevarar varje process, ', mätningarna separat.., behållare, ,, GC-inställningar, M SK3, last, Mska4, påladung och en kantbil som delar sig av flera noderprocesser kan ändra jämförelsen.

Synkroniserade samtal blockerar fortfarande Node's händelseloop

Båda iprocesssökningsmetoderna körs synkroniserat på den som ropar på nodertråden... Att ge tillbaka ett skrivet objekt ändrar inte var söket körs. .. gRPC-clienten väntar på ett svar medan arbetet sker i den andra processen.

Grejen programmerar en 10 ms timer , sedan utsläpper | 100 | sökningar |. | Zusätzliche timerverzögerung var ungefär 31–53 ms för inskrivna objekt, 30–33 ms för JSON interop, och 0–0.9 ms genom gRPC. Bresten tar bort de återlämnade datan , inklusive det skrivna ögonblicksbildet eller JSON-testet M SK2 men utelämnar latens-loopen ' s per MSC4 samtalets påståenden och tidning MST5

Den sprickningen skulle också skjuta upp orelaterade återkopplingar på samma nodersträng.

Reproduera mätningarna

npm run build:bench
npm run bench
npm run bench:summary

Lämparen startar och stannar med sin egen loopback-bilar.,, använder färska klienter, ,, och kontrollerar resultatets jämlikhet. råresultat including trial values, environment details and hashes of the measured assemblies BENCH_TRIALS och BENCH_ITERATIONS konfigurera loppet.

De här mätningarna täcker sökningar och en kontrollensändning.

Den bakåtgående riktningen: C# kallar vår JavaScript-modul

Den existerande nodesappen har också JavaScript som vi kanske vill ringa från .NET. Båda provapplikationerna använder samma Buchungsformatorn . CM SK3 applikationen laddar den genom en inbyggd nodesruntime och passerar objekt direkt

var offer = salon.FindTogether(new SearchWindow
{
    Start = "2030-06-03T10:00:00Z",
    End = "2030-06-03T12:00:00Z"
});

var text = runtime.Run(() =>
    new BookingFormatter(runtime.Import(modulePath)).Format(offer));

modulePath pekar på format-booking.cjs. Den BookingFormatter-adaptator skapar JSObject och JSArray värden från det skrivna förslaget, så väcker den modulen's format funktionen genom Node-API. Den här omvända adaptern använder explicit objektkonstruktion snarare än den genererade modulen

JavaScript formatter läser offer.appointments direkt och återvänder:

format-booking.cjs: 11:00 London: alice: gels with sarah; beth: pedicure with anna

samtalet kör inuti runtime.Run, på JS-omgivningstråden . Alla JS objekt finns kvar i detta återkopplingsmönster Format(SearchOffer) handtekening, medan dess implementering hanterar de ursprungliga JS-värdena .

kör den med npm run reverse. Den att bygga in ett program hanterar plattformskapande och infödda-vägsselection. den använder Microsoft.JavaScript.LibNode 20.1800.203, parningen som testats här med Node API 0.9.36.

Den här gången, ,, är NET-applikationen som äger processen och har värden embedding support förblir experimentell, med en version libnode binär betyder inte att ' nödvändigtvis levererar denna wrapper, ', inbäddade exporter och .

Det omvända exemplet ser till att objekt passerar och formaterar.

Att paketera integreringen

Den projektfile möjliggör CopyLocalLockFileAssemblies så att de skötta beroendena följer DLL. fasad löser också SQLite's inhemska bibliotek explicitt. De detaljerna var nödvändiga i den testade nodeshändern native- laddande dokumentation förklarar mekanismen.

En inhemsk AOT .node addon skulle kunna ta bort den separat installerade .NET runtimeanforderungen. MicrosoftM SK2s C# Dev Kit exempel visar att angreppet är möjligt. Den skrivna Buchungspfad avoiderar JSON serialiseringen , men paketabhängighetens grafen, skapade bindningar och SQLite-tillgångar behöver fortfarande separat AOT-validation . Den här instruktionen publicerar inte eller mäter varianten

I' startar med den genererade modulen för denna kalenderapp om dess sökningar är tillräckligt korta för att fungera på nodertrådet och jag kan paketera de ursprungliga beroendena med appn . I' använder en kantbil om jag behöver process isolering , oberoende uppgraderingar eller en maskin som delar med sig av flera klienter

Båda funktionella demonstreringar, reservkontroller och benchmarks utfördes på macOS ARM64. Kalendern - händelseförspelning är undersöktM SK3 men ingen komplett webblader-applikation är tillgänglig

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.