Introduktion til Packem: en superhurtig eksperimentel bundler skrevet i Rust

Packem er en eksperimentel prækompileret JavaScript-modulbundter, der primært implementeres i Rust. Det kan også håndtere en række andre filtyper som YAML / TOML, fragment shader-filer og meget mere. Tjek hjemmesiden eller GitHub-siden for hurtigt at komme i gang.

Packem løser et moduls afhængigheder og rehydrerer dem til en modulgraf, en flad liste indeholdende modulgrænseflader, der i det væsentlige henviser til hukommelsesbaserede mutable datastrukturer i hukommelsen, der indeholder specielle metadata for et modul i modulgrafen.

Det meste af forretningslogikken er abstraheret i Rust ved hjælp af FFI-bindinger for at muliggøre lavt niveau interaktioner mellem begge ender. Rusty binære filer er tilgængelige som forudkompilerede Node C / C ++ addons i Packems repo. En skybaseret CI bruges til at køre et par scripts med pre-gyp-installationer, hvilket giver OS-specifikke binære filer med understøttelse af senere Node-versioner (8, 9, 10).

Dette lag af Packems kerne er det, der kaldes den logiske kontekst (LC) . Alle de andre operationer, der ikke er eksplicit prioriteret , regresseres til Nodes generelle driftstid, hvilket i Packems udtryk er Runtime Context (RC) . Læs mere om sammenhænge her.

Teoretisk holdes modulgrafen fladt for at undgå almindelige faldgruber, der ville føre til unødvendige traversaler, hvis et træ blev brugt på plads. Dette gør det muligt for RC at holde styr på sager som dybe cirkulære afhængigheder eller stærkt indlejrede dynamiske import (kodedeling), blandt andet, passende med minimale ydeevneimplikationer eller bivirkninger som muligt.

Flere detaljer kan findes på Packems README.md.

Jeg har haft denne idé i tankerne, men har aldrig planlagt at udføre den, før jeg gik sammen med Saddam M. Det har virkelig været i min interesse at se modulbundtning som et koncept, der er sikkert for alle at lære, forstå og implementere. At få folk til at kæmpe med konfigurationer, dokumentation og plugins var ekstremt forfærdelige, og jeg vil gerne tage chancen for at ændre det. Med dig. Med Packem.

Hurtig historie

Jeg tog mig tid til at udtømme de fleste bundlere skrevet i et ikke-JavaScript-miljø. Jeg fandt ud af, at de fleste af dem glemte, at de skulle være en bundler og ikke et C / C ++ - bibliotek fra de mørke år 19.

Hvad jeg ønskede var en bundler, der udfører det meste af tungtløftningen på et tæt metal- sprog for brugeren uden at kræve nogen interaktion med dens interne. Så fandt jeg Rust. Et smart og kortfattet systemsprog, der viser nogle prisværdige funktioner som en frygtløs samtidighedsmodel, typesikkerhed og meget mere! Jeg forventer lige så meget af at bruge C / C ++, men jeg vil hellere holde fast i Rust, da det er ret ligetil, når det kommer til hukommelsesstyring.

Hvorfor en anden bundler?

Så hvad tager det her? Hvorfor har vi brug for et andet byggeværktøj, da vi allerede har fantastiske, som webpack, Parcel, Rollup osv.? Jeg tager dig med et par grunde til, hvorfor. Måske har du måske dine egne interesser i at få din udvikling og produktionstider reduceret kraftigt.

Det er 2019, vi har ikke brug for langsomme værktøjer ikke mere

Selvom Packem er hurtigere end webpack 4, er det mere end dobbelt så hurtigt som Parcel (med multicore-kompilering) . I en benchmark test bundlede vi Lodash v4.17.1 med både Packem og Parcel, og dette var resultatet:

Tag aldrig bænke til pålydende værdi. Du kan teste det selv her.

Årsagen til, at jeg ikke gider benchmarking af Parcel mod webpack, var fordi webpack 4 er dybt hurtigere end Parcel. Jeg beviste dette ved at bruge Sean T. Larkins egne bænke og en tråd til det på Twitter kan findes her.

Fordi vi kan. Enhver kan, ikke?

Selvfølgelig, hvad der giver mest mening, er fordi vi kan . Vi havde ideen om at have hurtigere bundttider med en Rusty-interface, enten med FFI eller WASM (var dengang stadig usikker). FFI var mere rimelig med hensyn til hastighed og DX, så vi gik med at få Packem implementeret i Rust FFI-bindinger.

Vi oplevede et par trådrelaterede problemer, så vi brugte ikke meget de tilgængelige ressourcer. Som et resultat brugte vi flere node-underordnede processer (med node-worker-farm ) , den samme teknik, som Parcel bruger til multicore-kompilering, men til større modulgrafer, da det tilføjer en betydelig opstartstid oven på Node's oppetid, når den bruges med mindre modulgrafer .

Konfigurationsstil

Dette var en vanskelig del. Der var mange spørgsmål, der havde brug for et godt svar for at kompensere for at vælge den rigtige konfigurationsstil. Statisk eller dynamisk? JSON / YAML / TOML? Vores valg var udelukkende baseret på, om vi havde brug for Packem til at:

  1. Har en pænere konfigurationsstil, og
  2. Vær agnostiker over andre brugerdefinerede brugerkonfigurationer som .babelrc eller package.json .

Bundlinjen fortsatte vi med en statisk konfigurationsstil, da vi fandt det nøjagtigt det, vi havde brug for. Noget, der erklærende kan fortælle Packem, hvordan man styrer bundtecyklussen . Alle grænser for at have en statisk konfiguration blev gjort klare.

Et andet aspekt af interesse var den type fil, vi skulle bruge til konfigurationen. JSON, der er mere almindeligt for et overvældende flertal af JavaScript-udviklere eller YAML / TOML / XML-stil, som er mindre almindelige, men som har deres egen fordel (er). Der blev stadig fremsat et forslag til JSON-support (nr. 5).

JSON skar bare ikke ud på grund af alle de unødvendige strengcitater, krøllede & blokere seler, hvilket giver mening, da det er et dataudvekslingsformat . En XML-ish-tilgang fortjener ingen respekt med hensyn til at blive brugt som et konfigurationsformat, da det gør tingene værre end JSON for så vidt angår unødvendige tegn. TOML introducerede mange nye linjer, og fejlfinding af indlejrede indstillinger syntes ikke at være tiltalende, da vi vidste, at Packem-plugins kunne blive virkelig pæn.

Den endelige vinder var YAML! Det var i stand til at passere alle aspekter af at være et korrekt konfigurationsformat (i det mindste for Packem). Det:

  1. Gør konfigurationen smertefri.
  2. Bruger en elegant tilgang.
  3. Er stadig kendt for JavaScript-øjet
  4. Blev designet specielt til denne brugskasse (konfigurationer) .

Her er et eksempel på en typisk Packem-konfiguration ( packem.config.yml) . Kontroller selv og overvej at skrive det samme indhold i en JSON / TOML / XML-stil.

FYI, kun de to første muligheder er nødvendige! ?

Udvidelse af Packem

Denne funktion er endnu ikke implementeret.

Nogle gange er vi muligvis nødt til at bruge en funktion, der endnu ikke findes , muligvis ikke implementeres i Packem eller er meget specifik for vores projekt . I så fald har du to måder at løse dine behov på:

  1. Opret et Packem-plugin til din brugssag (som er den anbefalede mulighed).
  2. Byg en brugerdefineret RC oven på Packems binære filer.

Brug af Rust giver os chancen for at reformere LC til andre binære formater, såsom WebAssembly, som gør det muligt for Packem at udstille flere kompileringsmål:

  1. En NAPI-baseret C / C ++ addon med platformsspecifikke binære filer krævet af Packems standard RC.
  2. En WebAssembly-baseret binær, der er på tværs af platforme og indsprøjtes i RC.
  3. Packems standard standalone, der bruger WebAssembly med en browser-kompatibel implementering af RC.
De sidste to er endnu ikke på radaren, da interne refaktorer stadig sorteres.

Den avancerede guide forventes snart at vise dig, hvordan du bygger et brugerdefineret buildværktøj ved hjælp af Packems binære filer, der passer til dine egne behov, hvis du har brug for Packem uden for browser- og Node-miljøer. Disse binære filer kompletterer hele grafgenereringen og duplikerer filtrering og andre grafrelaterede aspekter. Dette betyder, at du kan bruge din brugerdefinerede serializer, filovervågning, pluginsystem osv. Det ligner meget hvordan du kan opbygge din brugerdefinerede renderer over OpenGL.

  1. Du kan stadig omfavne Packems pluginsystem, da det giver dig mulighed for at integrere Packems økosystem af plugins med din brugerdefinerede bundler.
  2. Hvis du er usikker på, om du skal bygge en brugerdefineret bundler eller ej, skal du vide, at du ikke altid har brug for det. Prøv først at arkivere et problem.
  3. Det er en garanti for, at disse binære filer vil fremskynde din arbejdsgang afhængigt af dine specifikke brugssager.

Nuværende tilstand

  • ✂ Kodedeling til udviklings- og produktionstilstande.
  • ? Forbedret CLI (`- verbose`) for bedre information om bundtningscyklus.
  • ? Modulgrænseflader for at muliggøre let manipulation af modulgrafen.
  • ✔ Korrekt prioritet. Native funktioner passer perfekt ind i LC. Dette betyder, at der er større chancer for hurtige opbygninger.
  • ? Eksporter N ativeUtils til ekstern brug af native funktionaliteter inklusive g, enerateModuleGraph som kører processen med at generere en modulgraf. Det er tungt, men stadig nyttigt i tilfælde, hvor du har brug for en klon af den aktuelle aktive modulgraf. Brug af det betyder en fordobling af byggetiden, så brug den med omhu.

Hvad er det næste?

Dette er de funktioner, vi håber snart har i de kommende udgivelser. Med din indsats kunne vi få bundtet gjort på den rigtige måde . Når Packem er på 1.0 , forventer vi at have fuld support til alle nedenstående funktioner og de andre, der er nævnt i Packems køreplan.

  • En browser-kompatibel uafhængig af Packem med LC i WebAssembly til tættere integration med det underliggende system. Axel Rauschmayer fremsatte allerede en funktionsanmodning om at have en Node-kompatibel version i WASM. For ordens skyld arbejder vi snart på begge dele.
  • Treeshaking, men avanceret. At løse navngivne / unavngivne importer og fjerne den døde kode bør være en leg. Dette betyder, at du kan bruge biblioteker som lodash i stedet for lodash-es uden at bekymre dig om, hvorvidt din kode bliver elided eller ej.
  • Automatisk konfiguration. Ligesom Zero Config, men standardorienteret for ekstra fleksibilitet.
  • Avancerede CLI-muligheder for at gøre udvikling med Packem til en anden natur.
  • Bedre fejlrapportering.
  • Flere miljømål. Packem kan kun pakke til browseren fra nu af. Til sidst forventer vi også at understøtte Node CJS og andre formater.
  • Flere plugins. Vi har brug for flere plugins! Packem har et sæt almindelige plugins for at komme hurtigere i gang. Men for at vokse et samfund har vi brug for et godt økosystem med plugins. Tjek de almindelige tilgængelige plugins eller plugins sektionen på webstedet for at begynde at udvikle et plugin med det samme.
  • Og meget mere…

Ressourcer

  • Packem på GitHub
  • Køreplan- og funktionsanmodninger
  • Packems officielle side
  • Oprettelse af plugins med Packem
  • Opdeling af kode med Packem
  • Modulgrafen

Packem har ikke nået 1.0 endnu . Hvis du overhovedet har fundet Packem som interessant for dig, kan du prøve at bidrage til Packem selv ved at oprette plugins, opdatere dokumentationen, støtte os økonomisk, repræsentere Packem på konferencer eller andre måder. Vi sætter pris på din indsats!

God bundling! ???