[{"data":1,"prerenderedAt":430},["ShallowReactive",2],{"DefaultLayoutnl":3,"language-blog-slug-design-system-bouwen-react-webcomponenten-i18n-slugs":132,"language-blog-slug-nl-design-system-bouwen-react-webcomponenten":139},{"app":4,"menu":31,"footer":66},{"githubUrl":5,"youtubeUrl":6,"linkedinUrl":7,"phoneNumber":8,"emailAddress":9,"legal":10,"addresses":20},"https:\u002F\u002Fgithub.com\u002Fvoorhoede\u002F","https:\u002F\u002Fwww.youtube.com\u002Fchannel\u002FUCzHuhQVYFRixtQN2-swcuGg","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fde-voorhoede","+31 20 2610 954","post@voorhoede.nl",[11,14,17],{"title":12,"value":13},"KvK","56017235",{"title":15,"value":16},"BTW","NL851944620B01",{"title":18,"value":19},"IBAN","NL14TRIO0320142078",[21,26],{"address":22,"city":23,"googleMapsLink":24,"postalCode":25},"Koivistokade 70","Amsterdam","https:\u002F\u002Fwww.google.com\u002Fmaps\u002Fplace\u002FDe+Voorhoede+%7C+Front-end+Development\u002F@52.396847,4.8700823,17z\u002Fdata=!3m1!4b1!4m5!3m4!1s0x47c5e21d502d2d59:0xbf570944a96ebf45!8m2!3d52.347647!4d4.8502154","1013 BB",{"address":27,"city":28,"googleMapsLink":29,"postalCode":30},"Koornmarkt 22","Delft","https:\u002F\u002Fwww.google.nl\u002Fmaps\u002Fplace\u002FKoornmarkt+22,+2611+EG+Delft\u002F@52.0093477,4.3573054,17z\u002F","2611 EG",{"title":32,"callToActions":33,"links":39},"Site Menu",[34],{"id":35,"title":36,"link":37},"163140903","Contact",{"__typename":38},"ContactRecord",[40,46,51,56,61],{"id":41,"title":42,"link":43},"163140909","Impact",{"__typename":44,"slug":45},"PageRecord","impact",{"id":47,"title":48,"link":49},"163140910","Services",{"__typename":50},"ServiceOverviewRecord",{"id":52,"title":53,"link":54},"163140911","Cases",{"__typename":55},"CaseOverviewRecord",{"id":57,"title":58,"link":59},"163140913","Over ons",{"__typename":44,"slug":60},"about-us",{"id":62,"title":63,"link":64},"NnUFs73_Saa8XE_jYZFHcw","Werken bij",{"__typename":44,"slug":65},"work-at",{"links":67,"copyrightTitle":93,"copyrightLabel":94,"copyrightLink":95,"privacyTitle":96,"privacyLabel":97,"privacyLink":98,"certificatesGrid":99},[68,71,74,77,82,85,88],{"id":69,"title":42,"link":70},"144185271",{"__typename":44,"slug":45},{"id":72,"title":48,"link":73},"144185272",{"__typename":50},{"id":75,"title":53,"link":76},"144185273",{"__typename":55},{"id":78,"title":79,"link":80},"144185274","Blog",{"__typename":81},"BlogPostOverviewRecord",{"id":83,"title":58,"link":84},"144185275",{"__typename":44,"slug":60},{"id":86,"title":36,"link":87},"144185276",{"__typename":38},{"id":89,"title":90,"link":91},"144185277","FAQ",{"__typename":44,"slug":92},"faq","Creative Commons licentie en disclaimer","CC BY 4.0","https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby\u002F4.0\u002F","PDF bestand van De Voorhoede privacy statement","Privacy statement","https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1763455427-vh-isms-007-privacy-statement-de-voorhoede-nl.pdf",[100,112,122],{"id":101,"image":102,"link":107},"Xq4bBfg_TZ6Fkjax9mkbLQ",{"url":103,"alt":104,"width":105,"height":106},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1687353463-b-corp-logo-black-rgb.png",null,404,680,{"__typename":108,"id":109,"title":110,"url":111},"ExternalLinkRecord","fGW1ak8XQYaYDLkBSyncog","B Corp","https:\u002F\u002Fwww.bcorporation.net\u002Fen-us\u002Ffind-a-b-corp\u002Fcompany\u002Fde-voorhoede\u002F",{"id":113,"image":114,"link":118},"c5mCXRTiSraRIB25fw1p7Q",{"url":115,"alt":104,"width":116,"height":117},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1687353461-dda-boxlogo-black.png",627,480,{"__typename":108,"id":119,"title":120,"url":121},"P6Jh7B0cTv2cKyNEeKVWVQ","Dutch Digital Agencies","https:\u002F\u002Fdutchdigitalagencies.com\u002Fleden\u002Fde-voorhoede\u002F",{"id":123,"image":124,"link":127},"MT5SCyNxSTSr_v5eeATMZw",{"url":125,"alt":104,"width":126,"height":126},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1775730283-dnv.png",518,{"id":128,"title":129,"link":130},"BRtNB5HnT5i-7HkA8IYzBw","DIV",{"__typename":44,"slug":131},"impact\u002Fdigitale-producten-privacy-by-design",[133,136],{"locale":134,"value":135},"en","building-design-system-react-web-components",{"locale":137,"value":138},"nl","design-system-bouwen-react-webcomponenten",{"page":140},{"slug":138,"i18nSlugs":141,"social":144,"title":149,"subtitle":79,"isArchived":150,"headerIllustration":151,"date":155,"authors":156,"introTitle":173,"items":174,"pivots":368,"relatedBlogPosts":384,"tags":399,"onMountedScript":159,"onUnmountedScript":159},[142,143],{"locale":134,"value":135},{"locale":137,"value":138},{"title":145,"description":146,"image":147},"Design System bouwen met React Webcomponenten ","Ontdek hoe je een universeel design system bouwt met React en Webcomponenten om te gebruiken in elke webapplicatie of framework.",{"url":148},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1714383267-linkedin-blog-5.jpg","Een Design System bouwen met React Webcomponenten",false,{"url":152,"alt":104,"width":153,"height":154},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686922189-design_system_web_components-1.svg",455,425,"2023-06-19T02:00:00.000+02:00",[157,165],{"name":158,"lastName":159,"slug":160,"image":161},"Jasper","","jasper",{"url":162,"alt":104,"width":163,"height":164},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1683535518-jasper.jpg",1892,2523,{"name":166,"lastName":167,"slug":168,"image":169},"Sjoerd","Beentjes","sjoerd",{"url":170,"alt":104,"width":171,"height":172},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1683534892-sjoerd.jpg",1637,2182,"Wat als je een universeel design system zou kunnen bouwen met React en dit kan gebruiken in elke webapplicatie of framework? Het lukte ons door React om te zetten naar webcomponenten. Dit is hoe.",[175,179,183,193,196,201,204,208,211,214,218,221,224,227,231,235,239,246,249,252,255,258,261,264,268,272,275,278,281,284,287,290,294,298,305,308,311,314,317,320,323,326,330,336,339,342,345,349,356,364],{"__typename":176,"id":177,"title":159,"body":178},"TextSectionRecord","SIVCYKotSE-p6cKIka0fcQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Voor het \u003Ca href=\"https:\u002F\u002Fwww.voorhoede.nl\u002Fnl\u002Fservices\u002Fdesign-system\u002F\">design system\u003C\u002Fa> van een klant zochten we een universele oplossing om de componenten eenmaal te maken en ze te gebruiken in verschillende webapplicaties die zijn gebouwd met verschillende web frameworks. Ons idee was simpel: componenten maken in &eacute;&eacute;n framework - React - en een combinatie van wrappers, polyfills en tools gebruiken om ze te laten werken in elke context. De implementatie bleek iets lastiger dan we hadden verwacht. Maar we zijn blij met het resultaat en delen graag wat we hebben geleerd tijdens het proces.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":180,"title":181,"body":182},"J2B-FNwBQTG8YwxQNWgiyA","Het concept","\u003Cp>\u003Cspan style=\"font-weight: 400;\">In ons blog &lsquo;\u003Ca href=\"https:\u002F\u002Fwww.voorhoede.nl\u002Fen\u002Fblog\u002Fhow-to-select-framework-design-system-components\u002F\">Hoe selecteer je een Framework voor Design System componenten\u003C\u002Fa>&rsquo; beschreven we verschillende concepten om universele componenten te maken, waarvan er &eacute;&eacute;n React gebruikte. Kort uitgelegd: we maken componenten in React (.tsx-bestanden) en zetten deze om naar webcomponenten met behulp van wrappers (.wc.ts-bestanden) in combinatie met \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fpreactjs\u002Fpreact-custom-element\">Preact Custom Element\u003C\u002Fa>. Hierdoor is het design system beschikbaar als React-componenten voor React-toepassingen en als webcomponenten voor alle andere toepassingen:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":185,"image":186,"caption":191,"fullWidth":150,"captionPosition":192},"ImageRecord","PlzYeidRS6qhpxvt3ZMFnQ",{"url":187,"alt":188,"width":189,"height":190},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686736834-image8.png","React components + Preact Custom Element Wrapper = Web components en React Components",1752,1999,"Componenten ontwikkelen met behulp van React en ze omzetten naar Web Components met behulp van een Preact-wrapper","bottom",{"__typename":176,"id":194,"title":159,"body":195},"Kxy9JSRQRfq-nBIWoofd9g","\u003Cp>\u003Cspan style=\"font-weight: 400;\">We richten ons op de webcomponenten om het design system universeel beschikbaar te maken. Laten we wat dieper ingaan op hoe dit concept werkt.&nbsp;\u003C\u002Fspan>\u003Cspan style=\"font-weight: 400;\">Allereerst, \u003C\u002Fspan>\u003Ca href=\"https:\u002F\u002Fpreactjs.com\u002Fguide\u002Fv10\u002Fswitching-to-preact\u002F\">\u003Cspan style=\"font-weight: 400;\">Preact kan React vervangen\u003C\u002Fspan>\u003C\u002Fa>\u003Cspan style=\"font-weight: 400;\"> en heeft het twee opmerkelijke voordelen: \"De kleine omvang van Preact en de op standaarden gebaseerde benadering maken het een \u003C\u002Fspan>\u003Ca href=\"https:\u002F\u002Fpreactjs.com\u002Fguide\u002Fv10\u002Fweb-components\u002F\">\u003Cspan style=\"font-weight: 400;\">uitstekende keuze voor het bouwen van webcomponenten\u003C\u002Fspan>\u003C\u002Fa>\u003Cspan style=\"font-weight: 400;\">\". Omdat een Design System meestal niet de toeters en bellen nodig heeft die React biedt, is Preact een goede optie voor ons.\u003C\u002Fspan>\u003C\u002Fp>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Het vervangen van React door Preact bereik je met toolconfiguratie zoals in Vite, Rollup of een package.json:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":198,"language":199,"body":200},"CodeBlockRecord","Y5aCj4BLS9Sro_aCMsIaXQ","json","{\n  ...\n  \"alias\": {\n    \"react\": \"preact\u002Fcompat\",\n    \"react-dom\": \"preact\u002Fcompat\",\n    \"react\u002Fjsx-runtime\": \"preact\u002Fjsx-runtime\"\n  },\n  ...\n}",{"__typename":176,"id":202,"title":159,"body":203},"RrYIbyE2RKagg3xgIU9cGg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Nu Preact is geconfigureerd kunnen we een React-component omzetten in een web component. We bundelen alle gerelateerde bestanden in een directory. Neem bijvoorbeeld een component om een waarschuwingsbericht aan de gebruiker te tonen:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":205,"language":206,"body":207},"boYnz1_VSRuDa-415_j6XA","txt","components\u002Falert\u002F\n    alert.tsx    ← React component\n    alert.css    ← component styles\n    alert.wc.ts  ← Web Component wrapper",{"__typename":176,"id":209,"title":159,"body":210},"ZGGxEWKkRGm-T_G9iBCbIQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Opmerking: We gebruiken altijd TypeScript om design systems te maken om de beste ervaring te bieden voor ontwikkelaars die met packages van design systems werken. Om onze voorbeelden eenvoudig en beknopt te houden, hebben we hun typen weggelaten. We noemen ons voorbeeld Design System ACME en gebruiken overal 'acme' als voorvoegsel.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":212,"title":159,"body":213},"AoOlFwSbR7S9O7pUuUlZ0A","\u003Cp>\u003Cspan style=\"font-weight: 400;\">alert.tsx - \u003C\u002Fspan>\u003Cspan style=\"font-weight: 400;\">maak een component met React:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":215,"language":216,"body":217},"b8Hewj6aSAm51y0BioaRKQ","js","\u002F\u002F alert.tsx\nimport '.\u002Falert.css’\n\nconst Alert = ({ children, type = ‘info’ }) => (\n  \u003Cdiv className={`\n    alert \n    alert--type-${ type }\n  `}>\n    { children }\n  \u003C\u002Fdiv>\n)",{"__typename":176,"id":219,"title":159,"body":220},"IysVVzTPQt6QAHSLe0pGiQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">alert.wc.ts - registreer React-component als webcomponent met behulp van \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fpreactjs\u002Fpreact-custom-element\">Preact Custom Element\u003C\u002Fa>:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":222,"language":216,"body":223},"AX8gZ2eXQcufwf_0p5pRsQ","\u002F\u002F alert.wc.ts:\nimport register from 'preact-custom-element'\nimport Alert from ‘.\u002FAlert.tsx’\n\nregister(Alert, 'acme-alert’, [‘type’], { shadow: true })",{"__typename":176,"id":225,"title":159,"body":226},"YnRLXJa1TUuI6Pwu4djJlg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Gebruik als webcomponent in elke HTML-pagina of ander framework:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":228,"language":229,"body":230},"W2BEeHXTT9ii0NsA9sTNHQ","html","\u003C!-- in any HTML page: -->\n\u003Cacme-alert type=”warning”>My message.\u003C\u002Facme-alert>",{"__typename":176,"id":232,"title":233,"body":234},"PvwlVcODR3OzxeV53XLZgQ","De werkelijkheid","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Toen we begonnen met het bouwen van onze componenten, kwamen we al snel tot de conclusie dat preact-custom-element niet aan onze behoeften voldeed. Het lijkt te zijn ontworpen om op zichzelf staande (web)componenten te bouwen, terwijl wij een systeem van componenten willen bouwen dat stijlen bevat en met elkaar communiceert. Om dit te bereiken hebben we preact-custom-element aangepast en functionaliteit toegevoegd om event handling te ondersteunen en stijlen op te nemen.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":236,"title":237,"body":238},"C126er9rSkqWujewzMSXVQ","Ondersteuning toevoegen voor event handling","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Omdat onze componenten fungeren als bouwstenen, willen we dat ze met elkaar communiceren. Attributen worden al omgezet in props door preact-custom-element, maar we moeten ook de andere kant op communiceren:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":240,"image":241,"caption":159,"fullWidth":150,"captionPosition":192},"DRov26IcQTuWytilT1RrVA",{"url":242,"alt":243,"width":244,"height":245},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686742123-image5.png","original preact-custom-element and our adapted preact-custom-element",856,454,{"__typename":176,"id":247,"title":159,"body":248},"AS33jEYoRJOj3Pb4etKceQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Bijvoorbeeld, we willen een wegklikknop toevoegen aan ons waarschuwingscomponent:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":250,"language":216,"body":251},"Jy7cjx-JSa6SgKV5S1UXpA","\u002F\u002F alert.tsx\nimport '.\u002Falert.css’\n\nconst Alert = ({ children, type = ‘info’, onDismiss }) => (\n  \u003Cdiv className={`\n    alert \n    alert--type-${type}\n  `}>\n     { children }\n\t   \u003Cbutton type=”button” onClick={onDismiss}>\n        Dismiss\n     \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n)",{"__typename":176,"id":253,"title":159,"body":254},"RYvce3bHSRmf6hRKtaP7gg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Om dit te laten werken hebben we een configuratieoptie toegevoegd genaamd eventNames:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":256,"language":216,"body":257},"a39dgyr0RVKa3JAMGAAqTg","\u002F\u002F alert.wc.ts:\nimport register from '@acme\u002Fregister'\nimport Alert from ‘.\u002FAlert.tsx’\n\nregister({\n  component: Alert,\n  tagName: 'acme-alert',\n  propNames: [‘type'],\n  eventNames: ['onDismiss'],\n  shadow: true,\n});\n",{"__typename":176,"id":259,"title":159,"body":260},"N2-SnvwuQ-asz60gjAXtQw","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Dit werkt als volgt: we maken een proxyfunctie voor deze callbacks, die een aangepast event stuurt wanneer deze functie wordt aangeroepen. De naam van dit aangepaste event wordt gegenereerd uit de waarde die wordt doorgegeven aan eventNames. In ons geval wordt &lsquo;onDismiss&rsquo; &lsquo;acme-dismiss&rsquo;. Dit is een aangepaste eventnaam om conflicten te voorkomen met bubbelende events van het webcomponent, die verschillen van de verzonden events. Met deze wijziging ondersteunen we nu event handling en het kan als volgt worden gebruikt:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":262,"language":229,"body":263},"NpI0xQWORuSqCHCnCCEV7g","\u002F\u002F anywhere\n\u003Cacme-alert type=”warning”>My message.\u003C\u002Facme-alert>\n\u003Cscript>\ndocument.querySelector(‘acme-alert’)\n  .addEventListener(‘acme-dismiss’, (event) => ...)\n\u003C\u002Fscript>",{"__typename":176,"id":265,"title":266,"body":267},"JvwIVADrTKmgDqJjda9BVg","Ondersteuning toevoegen om stijlen op te nemen","\u003Cp>\u003Cspan style=\"font-weight: 400;\">De webcomponenten die we bouwen mogen niet worden vervuild door bestaande stijlen op een pagina, omdat we willen dat onze design system componenten overal bruikbaar zijn. Hoewel preact-custom-element het mogelijk maakt om Shadow DOM in te schakelen om ongewenste stijlen buiten te houden, biedt het geen manier om de stijlen op te nemen die we wel willen. Dus hebben we ons preact-custom-element helper verder aangepast:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":269,"image":270,"caption":159,"fullWidth":150,"captionPosition":192},"Nhk2EPvtRxir7eTtpO4vNQ",{"url":271,"alt":243,"width":244,"height":245},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686745142-image2.png",{"__typename":176,"id":273,"title":159,"body":274},"PR6vaKJCQgW91ZaDP0yJRg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">We staan toe dat een nieuwe webcomponent wordt geregistreerd met een lijst met ingesloten stijlen:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":276,"language":216,"body":277},"By04VE2jR7OLpNIvkX1nHA","\u002F\u002F alert.wc.ts:\nimport register from '@acme\u002Fregister'\nimport Alert from ‘.\u002FAlert.tsx’\nimport alertStyles from '.\u002Falert.css?inline'\n\nregister({\n  component: Alert,\n  tagName: 'acme-alert',\n  propNames: [‘type'],\n  eventNames: ['onDismiss'],\n  styles: [alertStyles],\n  shadow: true,\n});",{"__typename":176,"id":279,"title":159,"body":280},"PcnKpqx1QTGwT4QysDon1w","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Hoewel ons voorbeeldcomponent slechts &eacute;&eacute;n stylesheet heeft, kunnen andere componenten afhankelijk zijn van meerdere stylesheets, zoals een invoercomponent die invoer- en (gedeelde) labelstijlen vereist. Stylesheets die vereist zijn door alle componenten in het design system (zoals resetstijlen) zijn opgenomen in de registerhelper zelf, zodat ze niet in elk afzonderlijk component hoeven te worden geregistreerd. Binnen de registerhelper worden alle stijlen gecombineerd tot een \u003C\u002Fspan>\u003Ca href=\"https:\u002F\u002Fweb.dev\u002Fconstructable-stylesheets\u002F\">\u003Cspan style=\"font-weight: 400;\">Constructible Stylesheet\u003C\u002Fspan>\u003C\u002Fa>\u003Cspan style=\"font-weight: 400;\">. Het ziet er ongeveer zo uit:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":282,"language":216,"body":283},"AKtOmbMDQaaKIH_bFMBusQ","\u002F\u002F handling styles inside @acme\u002Fregister:\nconst sheets = [\n  resetStyles,\n  otherHelperStyles,\n  ...this.styles, \u002F\u002F passed via register\n].map((styles) => {\n  const sheet = new CSSStyleSheet();\n  sheet.replaceSync(styles);\n  return sheet;\n});\n\nthis.root.adoptedStyleSheets = sheets;",{"__typename":176,"id":285,"title":159,"body":286},"J5DH0O15T3urkb12_KnQgg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Ondersteuning voor \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FCSSStyleSheet#browser_compatibility\">Constructible Stylesheets in Safari is op dit moment experimenteel\u003C\u002Fa>, daarom gebruiken we voor nu een polyfill:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":288,"language":216,"body":289},"PvqhVBt-TiqLeN7YmDmseg","import 'construct-style-sheets-polyfill'",{"__typename":176,"id":291,"title":292,"body":293},"YxfCAtQrRuWNpLGyOsJtdQ","De optimalisatie","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Op dit punt zetten we onze React-componenten met succes om naar webcomponenten, dus we zouden hier kunnen stoppen. Maar omdat we altijd streven naar het leveren van projecten met hoge performance, hebben we nog werk te doen.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":295,"title":296,"body":297},"bGeei7mCRlCA0835ui04XQ","An app provider for shared JS dependencies","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Met onze werkende setup bundelt elke component zijn eigen Preact-runtime. Hoewel Preact met 4 kB minified en gzipped klein is in vergelijking met React's 45 kB (kern + DOM), telt het toch op wanneer we tientallen componenten hebben.\u003C\u002Fspan>\u003C\u002Fp>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Het bundelen van Preact in elk component heeft als voordeel dat elk component afzonderlijk kan functioneren. Het betekent ook dat als een team tien van onze componenten implementeert, ze 40 kB (gecomprimeerd) aan hun bundel zouden toevoegen. Deze extra bundelgrootte bestaat alleen uit tien keer dezelfde instantie van Preact. Tijd om dit te optimaliseren!\u003C\u002Fspan>\u003C\u002Fp>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Om dit op te lossen hebben we een 'app-provider' gemaakt die Preact &eacute;&eacute;n keer importeert en beschikbaar maakt voor al zijn child componenten:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":299,"image":300,"caption":159,"fullWidth":150,"captionPosition":192},"BWea-mP8SbK6sh5v-Tt9LA",{"url":301,"alt":302,"width":303,"height":304},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686745402-image1.png","Before: each component has its own JS deps and After: app provider exposes shared JS deps",857,378,{"__typename":176,"id":306,"title":159,"body":307},"GER4N7QwR26fp3U6aAFmfQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">We kunnen het als volgt gebruiken:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":309,"language":229,"body":310},"BPJ6JxkcTvesKixAtKkiLw","\u002F\u002F provider loads and exposes Preact\n\u003Cacme-app-provider>\n  \u003Cacme-component-a>...\u003C\u002Facme-component-a>\n  \u003Cacme-component-b>...\u003C\u002Facme-component-b>\n  \u003Cacme-component-c>...\u003C\u002Facme-component-c>\n\u003C\u002Facme-app-provider>",{"__typename":176,"id":312,"title":159,"body":313},"LaBK-bBTQWyNCAXDoWTPHQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">De 'app-provider' importeert React en ReactDOM (die worden gealiast naar Preact, zoals hierboven beschreven) en voegt het toe aan het window-object. We voegen er een voorvoegsel aan toe met onze bibliotheeknaam om mogelijke conflicten met bestaande eigenschappen uit te sluiten.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":315,"language":216,"body":316},"P29rOjtERxu1cNtSKHeWiw","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport { register } from '@acme\u002Fregister'\n\n\u002F\u002F we also include other shared dependencies, like:\nimport 'construct-style-sheets-polyfill'\n\nwindow.__ACME__React = React\nwindow.__ACME__ReactDOM = ReactDOM\n\nconst AppProvider = ({ children }) => {\n  return \u003C>{children}\u003C\u002F>\n}\n\nregister({\n  component: AppProvider,\n  tagName: ‘acme-app-provider'\n  options: { shadow: true },\n})",{"__typename":176,"id":318,"title":159,"body":319},"YUTwjocjRc2KATDfaDNOHQ","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Omdat we aliassen hebben geconfigureerd voor React naar Preact, bundelt de app-provider eigenlijk Preact. Ten slotte is de (Rollup) build voor alle andere componenten geconfigureerd om de wereldwijd blootgestelde React(DOM) te gebruiken:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":321,"language":216,"body":322},"Xf6P1QQsRBeHfUfNo0BoaA","return {\n  output: {\n  format: 'iife',\n  \u002F\u002F add an exception for our app-provider, as\n  \u002F\u002F it provides React instead of consuming it\n  ...(!isAppProvider && {\n    globals: {\n      'react': '__ACME__React',\n      'react-dom': '__ACME__ReactDOM',\n    },\n  }),\n  \u002F\u002F ...\n}",{"__typename":176,"id":324,"title":159,"body":325},"IYR5kCciRF-3CeZXcDj1dg","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Nu delen alle componenten die in de app-provider zitten dezelfde versie van elke JS-afhankelijkheid.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":327,"title":328,"body":329},"Wj6GIvdiQby1gNGE2NwJJw","Een thema-provider voor gedeelde CSS","\u003Cp>\u003Cspan style=\"font-weight: 400;\">De Shadow DOM voorkomt dat we gemeenschappelijke CSS delen tussen componenten op dezelfde manier als we doen voor JS-afhankelijkheden. Maar al onze design system tokens - gedefinieerd als aangepaste CSS-eigenschappen - kunnen door de Shadow DOM gaan. We halen daarom deze aangepaste CSS-eigenschappen uit alle componenten en maken ze beschikbaar via een gedeelde thema-provider:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":331,"image":332,"caption":159,"fullWidth":150,"captionPosition":192},"fHYH73suRWWFvFRDLFgm7g",{"url":333,"alt":334,"width":244,"height":335},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686746289-image6.png","Before: each component includes same CSS variables and After: theme provider injects shared CSS variables",366,{"__typename":176,"id":337,"title":159,"body":338},"Z1JTOsc_T4GYV8KNHKCy8A","\u003Cp>\u003Cspan style=\"font-weight: 400;\">We gebruiken het als volgt:\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":197,"id":340,"language":229,"body":341},"evTKyI-TRQifeuWBtNtpIg","\u002F\u002F provider includes and exposes CSS variables:\n\u003Cacme-theme-provider>\n  \u003Cacme-component-a>...\u003C\u002Facme-component-a>\n  \u003Cacme-component-b>...\u003C\u002Facme-component-b>\n  \u003Cacme-component-c>...\u003C\u002Facme-component-c>\n\u003C\u002Facme-theme-provider>",{"__typename":176,"id":343,"title":159,"body":344},"XCXKqzMFRFm4vnOy9oiApA","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Een extra voordeel van deze thema-provider is dat we in de toekomst gemakkelijker een licht\u002Fdonker thema-schakelaar kunnen toevoegen.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":176,"id":346,"title":347,"body":348},"dPNQTv6AReK3IeBFM_jGXQ","Optimalisatie van CSS class names","\u003Cp>\u003Cspan style=\"font-weight: 400;\">We willen nog &eacute;&eacute;n ding optimaliseren: CSS class names. We hechten waarde aan duidelijke benaming van onze componenten en al hun onderdelen, vooral in een design system. Hoewel dit belangrijk is tijdens ontwikkeling en documentatie, geven we prioriteit aan de gebruikerservaring in productie. En voor productie kunnen deze class names alles zijn, omdat ze afgebakend zijn en geen conflicten kunnen veroorzaken. Omdat lange class names de HTML en stylesheets opblazen, hebben we besloten ze te minimaliseren voor productie, wat ongeveer nog eens 5% van de totale bundelgrootte van ons design system bespaart.\u003C\u002Fspan>\u003C\u002Fp>",{"__typename":184,"id":350,"image":351,"caption":355,"fullWidth":150,"captionPosition":192},"dAAyxzj3TAWwBcNSsLuUKQ",{"url":352,"alt":353,"width":189,"height":354},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686749028-screenshot-2023-06-14-at-15-20-16.png","Code met lange class names",1006,"Tijdens ontwikkeling: lange class names met betekenis",{"__typename":184,"id":357,"image":358,"caption":363,"fullWidth":150,"captionPosition":192},"epB9kBHnRCulct-WWlxMhg",{"url":359,"alt":360,"width":361,"height":362},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1686749113-screenshot-2023-06-14-at-15-23-06.png","Code met korte class names",1730,950,"In productie: efficiënte class names die 5% bundelgrootte besparen",{"__typename":176,"id":365,"title":366,"body":367},"eBJefKUCRputdTDsmsCGGQ","Afsluitend","\u003Cp>\u003Cspan style=\"font-weight: 400;\">Door dit alles samen te voegen, hebben we nu een \u003Ca href=\"https:\u002F\u002Fwww.voorhoede.nl\u002Fnl\u002Fservices\u002Fdesign-system\u002F\">design system\u003C\u002Fa> met componenten die overal kunnen worden gebruikt. We hebben een aangepaste omzetter om React-componenten om te zetten naar webcomponenten met ondersteuning voor afgebakende stijlen en event handling. En we hebben onze setup uitgebreid met een gedeelde app- en thema-provider om de bundelgrootte van ons design system te optimaliseren.\u003C\u002Fspan>\u003C\u002Fp>",[369],{"title":370,"body":371,"links":372,"mailchimpValue":159,"mailchimpName":159,"mailchimpId":159,"formType":380,"contactPerson":381},"Hulp nodig met jouw design system?","\u003Cp>Ontdek wat wij voor je kunnen doen voor jouw digitale product.\u003C\u002Fp>\n",[373],{"__typename":374,"id":375,"title":376,"link":377},"InternalLinkRecord","135155041","Lees meer over onze service",{"__typename":378,"slug":379},"ServiceRecord","design-system","none",{"name":158,"lastName":159,"jobTitle":382,"image":383},"CTO, Co-founder",{"url":162,"alt":104,"width":163,"height":164},[385,392],{"slug":386,"title":387,"date":388,"authors":389},"kiezen-framework-design-system-componenten","Hoe kies je een framework voor design system componenten","2022-12-12T01:00:00.000+01:00",[390],{"name":158,"image":391},{"url":162,"alt":104,"width":163,"height":164},{"slug":393,"title":394,"date":395,"authors":396},"kick-start-design-system-design-inventory-workshop","Kick-start jouw Design System met een Design Inventory Workshop","2021-09-16T02:00:00.000+02:00",[397],{"name":158,"image":398},{"url":162,"alt":104,"width":163,"height":164},[400],{"id":401,"title":402,"slug":403,"blogPosts":404},"JBiZUe8mQVujxlNVR5gx8Q","Design Systems","design-systems",[405,412,419],{"slug":406,"title":407,"date":408,"authors":409},"toegankelijkheid-in-design-systems","Toegankelijkheid in Design Systems","2025-06-17T14:15:56.000+02:00",[410],{"name":166,"image":411},{"url":170,"alt":104,"width":171,"height":172},{"slug":413,"title":414,"date":415,"authors":416},"design-system-op-maat-of-kant-en-klaar","Design System: op maat of kant-en-klaar?","2024-11-19T13:16:02.759+01:00",[417],{"name":158,"image":418},{"url":162,"alt":104,"width":163,"height":164},{"slug":420,"title":421,"date":422,"authors":423},"schrijf-code-eenmalig-en-gebruik-het-overal-met-mitosis-een-mooie-droom-of-werkelijkheid","“Schrijf code eenmalig en gebruik het overal” met Mitosis; een mooie droom of werkelijkheid?","2024-09-16T13:04:31.307+02:00",[424],{"name":425,"image":426},"Wessel",{"url":427,"alt":425,"width":428,"height":429},"https:\u002F\u002Fwww.datocms-assets.com\u002F6524\u002F1721035942-wessel.jpg",2135,2868,1776256147937]