{"id":18074,"date":"2023-09-08T15:54:30","date_gmt":"2023-09-08T20:54:30","guid":{"rendered":"http:\/\/carterembry.com\/?p=18074"},"modified":"2025-08-05T09:28:55","modified_gmt":"2025-08-05T14:28:55","slug":"web-workers-react-app-parcel-wo-eject","status":"publish","type":"post","link":"https:\/\/carterembry.com\/fr\/2023\/web-workers-react-app-parcel-wo-eject\/%20","title":{"rendered":"Ajoute des travailleurs Web \u00e0 create-react-app \u00e0 l'aide de Parcel (l'\u00e9jection n'est pas n\u00e9cessaire)."},"content":{"rendered":"<div id=\"pl-18074\"  class=\"panel-layout\" ><div id=\"pg-18074-0\"  class=\"panel-grid panel-no-style\" ><div id=\"pgc-18074-0-0\"  class=\"panel-grid-cell\" ><div id=\"panel-18074-0-0-0\" class=\"so-panel widget widget_sow-headline panel-first-child\" data-index=\"0\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-headline so-widget-sow-headline-default-d6db24c2db75-18074\"\n\t\t\t\n\t\t><div class=\"sow-headline-container\">\n\t\t\t\t\t\t\t<h2 class=\"sow-headline\">\n\t\t\t\t\t\tVue d'ensemble\t\t\t\t\t\t<\/h2>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"decoration\">\n\t\t\t\t\t\t<div class=\"decoration-inside\"><\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n<\/div><\/div><div id=\"panel-18074-0-0-1\" class=\"so-panel widget widget_sow-editor\" data-index=\"1\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-editor so-widget-sow-editor-base\"\n\t\t\t\n\t\t>\n<div class=\"siteorigin-widget-tinymce textwidget\">\n\t<p style=\"padding-left: 40px;\">J'ai travaill\u00e9 sur <a href=\"https:\/\/www.fidgetmap.com\/\">FidgetMap<\/a> depuis un certain temps. Je pense que je pourrais acc\u00e9l\u00e9rer beaucoup de processus (y compris la boucle de rendu de base) en ajoutant <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\">Travailleurs du Web<\/a> pour g\u00e9rer une grande partie des t\u00e2ches de rendu de mani\u00e8re asynchrone. L'ensemble du jeu est dessin\u00e9 en \u00e9crivant les donn\u00e9es RVB dans des tableaux puis en les composant sur <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Canvas_API\">une toile<\/a>Il s'agit donc d'un candidat id\u00e9al pour le programme <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\">Travailleurs du Web<\/a>. C'est assez fou de penser qu'il est arriv\u00e9 jusqu'ici sans aucun fil conducteur, mais nous y sommes.<\/p>\n<p>Je ne vais pas me lancer dans une le\u00e7on d'histoire sur les Web Workers, mais je me contenterai de dire qu'ils me permettront de passer une grande partie du rendu \u00e0 un thread d'arri\u00e8re-plan (plusieurs threads d'arri\u00e8re-plan dans mon cas) afin de lib\u00e9rer le thread d'ex\u00e9cution principal. L'ensemble du jeu devrait \u00eatre plus rapide avec certaines t\u00e2ches compartiment\u00e9es en arri\u00e8re-plan.<\/p>\n<p>La partie principale du jeu est dessin\u00e9e directement sur un<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Canvas_API\"> toile<\/a>, comme mentionn\u00e9 ci-dessus, mais les contr\u00f4les de l'interface utilisateur tels que le menu et les boutons interactifs sont \u00e9crits en React. Inutile de r\u00e9inventer la roue en ce qui concerne le texte et le rendu de style flex. J'ai donc construit le projet en utilisant <a href=\"https:\/\/create-react-app.dev\/\">cr\u00e9er une application-react<\/a> (avec Typescript). Je veux \u00e9crire mes Web Workers dans le m\u00eame style, de pr\u00e9f\u00e9rence dans le m\u00eame code source. Mais tu ne peux pas simplement importer des modules Web Worker et les transformer en travailleurs. Tu dois instancier un travailleur avec une URL vers un fichier JavaScript s\u00e9par\u00e9 (ou un bundle).<\/p>\n<p>CRA est g\u00e9nial. Il cache toute configuration et rend super facile le d\u00e9marrage d'un projet React. Mais il n'est pas si g\u00e9nial pour les configurations avanc\u00e9es comme celle-ci, o\u00f9 tu dois compiler ton appli en un fichier JS et potentiellement plusieurs Web Workers dans des fichiers s\u00e9par\u00e9s. La recommandation habituelle est de <a href=\"https:\/\/create-react-app.dev\/docs\/available-scripts#npm-run-eject\">\u00e9jecter de create-react-app<\/a>. Cela te permet de jouer avec la configuration selon tes besoins, mais un grand pouvoir implique une grande responsabilit\u00e9. Une fois que tu as \u00e9ject\u00e9, tu dois maintenir la configuration et les scripts toi-m\u00eame. Il n'y a plus de mise \u00e0 jour facile d'un projet bien test\u00e9.<\/p>\n<p>Alors comment faire pour avoir des cibles de compilation diff\u00e9rentes pour des points d'entr\u00e9e diff\u00e9rents ? <a href=\"https:\/\/parceljs.org\/\">Parcelle<\/a> \u00e0 la rescousse.\u00a0 <a href=\"https:\/\/parceljs.org\/\">ParcelJS<\/a> est un outil de construction \u00e0 configuration z\u00e9ro qui fonctionne avec Typescript pr\u00eat \u00e0 l'emploi. Tu dis juste \"hey Parcel, ce fichier d'entr\u00e9e\" et il fait la chose\u2122. Assez parl\u00e9, laisse-moi te montrer comment j'ai fait.<\/p>\n<\/div>\n<\/div><\/div><div id=\"panel-18074-0-0-2\" class=\"so-panel widget widget_sow-headline\" data-index=\"2\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-headline so-widget-sow-headline-default-d6db24c2db75-18074\"\n\t\t\t\n\t\t><div class=\"sow-headline-container\">\n\t\t\t\t\t\t\t<h2 class=\"sow-headline\">\n\t\t\t\t\t\tLa solution\t\t\t\t\t\t<\/h2>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"decoration\">\n\t\t\t\t\t\t<div class=\"decoration-inside\"><\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n<\/div><\/div><div id=\"panel-18074-0-0-3\" class=\"so-panel widget widget_sow-button\" data-index=\"3\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-button so-widget-sow-button-atom-27e09ad139d7-18074\"\n\t\t\t\n\t\t><div class=\"ow-button-base ow-button-align-center\"\n>\n\t\t\t<a\n\t\t\t\t\thref=\"https:\/\/github.com\/slobaum\/cra-workers-parcel\"\n\t\t\t\t\tclass=\"sowb-button ow-icon-placement-left ow-button-hover\" target=\"_blank\" rel=\"noopener noreferrer\" \t>\n\t\t<span>\n\t\t\t<span class=\"sow-icon-fontawesome sow-far\" data-sow-icon=\"&#xf1c9;\"\n\t\tstyle=\"\" \n\t\taria-hidden=\"true\"><\/span>\n\t\t\tVisite le repo avec cette d\u00e9mo compl\u00e8te\t\t<\/span>\n\t\t\t<\/a>\n\t<\/div>\n<\/div><\/div><div id=\"panel-18074-0-0-4\" class=\"so-panel widget widget_sow-editor panel-last-child\" data-index=\"4\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-editor so-widget-sow-editor-base\"\n\t\t\t\n\t\t>\n<div class=\"siteorigin-widget-tinymce textwidget\">\n\t<p>Commen\u00e7ons par le commencement. Utilise <a href=\"https:\/\/create-react-app.dev\/docs\/adding-typescript\/\">create-react-app pour d\u00e9marrer un nouveau projet avec Typescript<\/a>. Va dans le r\u00e9pertoire de ton projet et cr\u00e9e une nouvelle application comme suit :<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">npx create-react-app workers-example --template typescript<\/pre>\n<p>Va maintenant dans le r\u00e9pertoire et installe Parcel.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">cd travailleurs-exemple\nnpm i --save-dev parcel<\/pre>\n<p>Rad, maintenant nous travaillons techniquement avec deux syst\u00e8mes de construction ; celui int\u00e9gr\u00e9 dans create-react-app et Parcel que nous venons d'ajouter. Cr\u00e9ons un nouveau r\u00e9pertoire \u00e0 la racine du projet appel\u00e9 \"workers\". C'est l\u00e0 que nous mettrons le code source de workers. Il se trouve dans un r\u00e9pertoire distinct de src puisqu'ils seront chacun leur propre petit paquet. Nous y ajouterons \u00e9galement un exemple de travailleur.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">mkdir travailleurs\ncd travailleurs\ntouch sampleWorker.ts<\/pre>\n<p>Mettons quelque chose dans notre exemple de travailleur pour que nous puissions voir que cela fonctionne.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">self.onmessage = (e : MessageEvent) =&gt; {\n    self.postMessage(\"hello, world from the worker\") ;\n} ;<\/pre>\n<p>Nous allons maintenant ajouter un nouveau script \u00e0 notre package.json afin de pouvoir cr\u00e9er des travailleurs \u00e0 l'aide de npm. Nous allons construire tous les travailleurs dans le r\u00e9pertoire public sous un sous-r\u00e9pertoire afin que notre application puisse facilement les utiliser \u00e0 partir de l\u00e0.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">{\n\/\/ ...reste du fichier\n  \"scripts\" : {\n    \/\/ ... reste des scripts\n    \"worker:build\" : \"parcel build --dist-dir public\/workers --\"\n  }\n}<\/pre>\n<p>Ok, maintenant nous pouvons construire des travailleurs ! Ex\u00e9cute ceci pour voir la magie :<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">npm run worker:build workers\/sampleWorker.ts<\/pre>\n<p>Parcel utilisera sampleWorker.ts comme point d'entr\u00e9e. Il verra qu'il s'agit de Typescript et fera ce qu'il faut sans aucun plugin ou configuration suppl\u00e9mentaire. Lorsque la commande se termine, tu devrais trouver ton travailleur nouvellement construit dans public\/workers ainsi qu'une carte des sources. C'est super !<\/p>\n<\/div>\n<\/div><\/div><\/div><\/div><div id=\"pg-18074-1\"  class=\"panel-grid panel-no-style\" ><div id=\"pgc-18074-1-0\"  class=\"panel-grid-cell\" ><div id=\"panel-18074-1-0-0\" class=\"so-panel widget widget_sow-headline panel-first-child\" data-index=\"5\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-headline so-widget-sow-headline-default-d6db24c2db75-18074\"\n\t\t\t\n\t\t><div class=\"sow-headline-container\">\n\t\t\t\t\t\t\t<h2 class=\"sow-headline\">\n\t\t\t\t\t\tVois-le en action\t\t\t\t\t\t<\/h2>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"decoration\">\n\t\t\t\t\t\t<div class=\"decoration-inside\"><\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n<\/div><\/div><div id=\"panel-18074-1-0-1\" class=\"so-panel widget widget_siteorigin-panels-builder panel-last-child\" data-index=\"6\" ><div id=\"pl-w64fe020f727a5\"  class=\"panel-layout\" ><div id=\"pg-w64fe020f727a5-0\"  class=\"panel-grid panel-no-style\" ><div id=\"pgc-w64fe020f727a5-0-0\"  class=\"panel-grid-cell\" ><div id=\"panel-w64fe020f727a5-0-0-0\" class=\"so-panel widget widget_sow-editor panel-first-child panel-last-child\" data-index=\"0\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-editor so-widget-sow-editor-base\"\n\t\t\t\n\t\t>\n<div class=\"siteorigin-widget-tinymce textwidget\">\n\t<p>Mettons \u00e0 jour le fichier App automatique pour que nous puissions voir notre nouveau travailleur en action. Copie\/colle ceci dans ton App.tsx pour interfacer avec le travailleur que nous avons construit.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nimport React, { FC, useCallback, useEffect, useRef } from &#039;react&#039; ;\n\nconst App : FC = () =&amp;gt; {\n  const workerRef = useRef&lt;worker&gt;() ;\n\n  const sendMessageToWorker = useCallback(() =&amp;gt; {\n    workerRef.current ?.postMessage({}) ;\n  }, []) ;\n\n  useEffect(() =&amp;gt; {\n    workerRef.current = new Worker(&quot;\/workers\/sampleWorker.js&quot;) ;\n\n    workerRef.current ?.addEventListener(&#039;message&#039;, (event) =&amp;gt; {\n      alert(&#039;message re&ccedil;u du travailleur : &#039; + JSON.stringify(event.data)) ;\n    }) ;\n\n    return () =&amp;gt; workerRef.current ?.terminate() ;\n  }, []) ;\n\n  return (\n    &lt;div&gt;\n      &lt;button type=&quot;button&quot; onclick=&quot;{sendMessageToWorker}&quot;&gt;\n        Envoyer un message au travailleur\n      &lt;\/button&gt;\n    &lt;\/div&gt;\n  ) ;\n}\n\nexport default App ;\n<\/pre>\n<p><\/worker><\/p>\n<\/div>\n<\/div><\/div><\/div><div id=\"pgc-w64fe020f727a5-0-1\"  class=\"panel-grid-cell\" ><div id=\"panel-w64fe020f727a5-0-1-0\" class=\"so-panel widget widget_media_image panel-first-child panel-last-child\" data-index=\"1\" ><a href=\"\/wp-content\/uploads\/2023\/09\/Screenshot-from-2023-09-08-21-21-50.png\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"500\" src=\"https:\/\/carterembry.com\/wp-content\/uploads\/2023\/09\/Screenshot-from-2023-09-08-21-21-50-500x500.png\" class=\"image wp-image-18095  attachment-medium size-medium\" alt=\"\" style=\"max-width: 100%; height: auto;\" srcset=\"https:\/\/carterembry.com\/wp-content\/uploads\/2023\/09\/Screenshot-from-2023-09-08-21-21-50-500x500.png 500w, https:\/\/carterembry.com\/wp-content\/uploads\/2023\/09\/Screenshot-from-2023-09-08-21-21-50-375x375.png 375w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/div><\/div><\/div><\/div><\/div><\/div><\/div><div id=\"pg-18074-2\"  class=\"panel-grid panel-no-style\" ><div id=\"pgc-18074-2-0\"  class=\"panel-grid-cell\" ><div id=\"panel-18074-2-0-0\" class=\"so-panel widget widget_sow-headline panel-first-child\" data-index=\"7\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-headline so-widget-sow-headline-default-d6db24c2db75-18074\"\n\t\t\t\n\t\t><div class=\"sow-headline-container\">\n\t\t\t\t\t\t\t<h2 class=\"sow-headline\">\n\t\t\t\t\t\tAller plus loin - construire automatiquement\t\t\t\t\t\t<\/h2>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"decoration\">\n\t\t\t\t\t\t<div class=\"decoration-inside\"><\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t<h3 class=\"sow-sub-headline\">\n\t\t\t\t\t\tConstruis les travailleurs lors de la construction de l'application\t\t\t\t\t\t<\/h3>\n\t\t\t\t\t\t<\/div>\n<\/div><\/div><div id=\"panel-18074-2-0-1\" class=\"so-panel widget widget_sow-editor\" data-index=\"8\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-editor so-widget-sow-editor-base\"\n\t\t\t\n\t\t>\n<div class=\"siteorigin-widget-tinymce textwidget\">\n\t<p>Maintenant, nous pouvons construire des travailleurs de la mani\u00e8re la plus basique. Il serait pr\u00e9f\u00e9rable de ne pas ajouter les travailleurs compil\u00e9s \u00e0 notre source, mais de les construire avec le paquet normal. Nous pouvons y parvenir assez facilement.<\/p>\n<p>Tout d'abord, ajoutons le r\u00e9pertoire des travailleurs publics (et le r\u00e9pertoire de cache des colis) \u00e0 notre .gitignore afin de ne pas les commettre.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ dans .gitignore\n.parcel-cache\npublic\/workers\n<\/pre>\n<p>Ensuite, nous allons ajouter une commande pour construire tous les travailleurs dans ton r\u00e9pertoire de travailleurs. De retour dans package.json...<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">{\n\/\/ ...reste du fichier\n  \"scripts\" : {\n    \/\/ ... reste des scripts\n    \"worker:build\" : \"parcel build --dist-dir public\/workers --\",\n    \"workers:build:all\" : \"npm run worker:build .\/workers\/*\"\n  }\n}<\/pre>\n<p>Parcel sauve une fois de plus la situation. Il utilisera chaque fichier du r\u00e9pertoire des travailleurs comme point d'entr\u00e9e et cr\u00e9era un paquet s\u00e9par\u00e9 pour chacun d'entre eux. Cela te permet d'avoir des travailleurs compl\u00e8tement compartiment\u00e9s. Chacun peut importer des node_modules et ces d\u00e9pendances feront partie du paquet final pour chaque travailleur.<\/p>\n<p>Mais nous ne voulons pas avoir \u00e0 lancer une commande de construction s\u00e9par\u00e9e. Nous voulons qu'elle le fasse en m\u00eame temps que la commande npm run build la plus basique. Nous pouvons y parvenir en utilisant un autre paquetage appel\u00e9 npm-run-all. Il te permet d'ex\u00e9cuter plusieurs commandes npm \u00e0 la fois, soit en s\u00e9quence, soit en parall\u00e8le.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">npm i --save-dev npm-run-all<\/pre>\n<p>Maintenant, de retour dans package.json, nous allons d\u00e9placer la commande de construction existante vers un nom diff\u00e9rent afin que nous puissions faire en sorte que la commande de construction normale fasse plusieurs choses<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">{\n\/\/ ...reste du fichier\n  \"scripts\" : {\n    \/\/ ... reste des scripts\n    \"build\" : \"npm-run-all --sequential workers:build:all rs:build\",\n    \"rs:build\" : \"react-scripts build\",\n    \"worker:build\" : \"parcel build --dist-dir public\/workers --\",\n    \"workers:build:all\" : \"npm run worker:build .\/workers\/*\"\n  }\n}<\/pre>\n<p>D'accord ! Maintenant, chaque fois que tu construiras, tu construiras d'abord tous tes travailleurs puis tu ex\u00e9cuteras la construction normale react-scripts qui cr\u00e9e ton paquet create-react-app.<\/p>\n<p>Maintenant, tu peux utiliser tes travailleurs enti\u00e8rement transpos\u00e9s et regroup\u00e9s n'importe o\u00f9 dans ton paquetage d'applications existant en faisant :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n    const worker = new Worker(\"\/workers\/sampleWorker.js\") ;\n<\/pre>\n<\/div>\n<\/div><\/div><div id=\"panel-18074-2-0-2\" class=\"so-panel widget widget_sow-headline\" data-index=\"9\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-headline so-widget-sow-headline-default-2b1d44ffeaae-18074\"\n\t\t\t\n\t\t><div class=\"sow-headline-container\">\n\t\t\t\t\t\t\t<h3 class=\"sow-headline\">\n\t\t\t\t\t\tConstruis les travailleurs en d\u00e9veloppement \u00e0 chaque fois qu'ils changent\t\t\t\t\t\t<\/h3>\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"decoration\">\n\t\t\t\t\t\t<div class=\"decoration-inside\"><\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n<\/div><\/div><div id=\"panel-18074-2-0-3\" class=\"so-panel widget widget_sow-editor\" data-index=\"10\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-editor so-widget-sow-editor-base\"\n\t\t\t\n\t\t>\n<div class=\"siteorigin-widget-tinymce textwidget\">\n\t<p>La derni\u00e8re pi\u00e8ce du puzzle est la construction des workers lorsque tu ex\u00e9cutes `npm start`. Parcel dispose d'une commande \"watch\" int\u00e9gr\u00e9e, mais elle suppose que ton fichier s'ex\u00e9cute dans un environnement dot\u00e9 d'une variable `window`, ce qui n'est pas le cas des workers. Nous pouvons donc facilement mettre en place notre propre observateur en utilisant un paquetage appel\u00e9 `node-watch`. Commence par l'installer :<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">npm i --save-dev node-watch<\/pre>\n<p>Maintenant, cr\u00e9e un nouveau script appel\u00e9 `watchWorkers.js`. Je l'ai plac\u00e9 dans un sous-r\u00e9pertoire appel\u00e9 \"scripts\". Copie ceci dans watchWorkers.js<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">var watch = require('node-watch') ;\nvar { spawn } = require('child_process') ;\n\n\/\/ ceci construira les travailleurs initialement lorsque le script sera ex\u00e9cut\u00e9\nspawn(\n    'npm',\n    ['run', 'workers:build'],\n    { stdio : 'inherit' }\n) ;\nwatch('.\/workers\/', { recursive : true }, function(evt, name) {\n    \/\/ ceci construira chaque travailleur individuel au fur et \u00e0 mesure qu'il est mis \u00e0 jour\n    spawn(\n        'npm',\n        ['run', 'worker:build', name],\n        { stdio : 'inherit' }\n    ) ;\n}) ;\n<\/pre>\n<p>Nous avons maintenant un script qui reconstruira chaque travailleur au fur et \u00e0 mesure qu'il change. Une fois de plus, modifions package.json pour qu'il fasse partie de notre processus normal<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">{\n\/\/ ...reste du fichier\n  \"scripts\" : {\n    \/\/ ... reste des scripts\n    \"start\" : \"npm-run-all --parallel workers:watch rs:start\",\n    \"rs:start\" : \"react-scripts start\",\n    \"build\" : \"npm-run-all --sequential workers:build:all rs:build\",\n    \"rs:build\" : \"react-scripts build\",\n    \"worker:build\" : \"parcel build --dist-dir public\/workers --\",\n    \"workers:build:all\" : \"npm run worker:build .\/workers\/*\",\n    \"workers:watch\" : \"node .\/scripts\/watchWorkers.js\"\n  }\n}<\/pre>\n<p>Maintenant, chaque fois que tu lanceras `npm start`, tu ex\u00e9cuteras le start react-scripts normal qui surveillera les changements du bundle d'app, mais tu ex\u00e9cuteras aussi ton propre worker watch qui retranspilera chaque worker au fur et \u00e0 mesure qu'il sera mis \u00e0 jour.<\/p>\n<\/div>\n<\/div><\/div><div id=\"panel-18074-2-0-4\" class=\"so-panel widget widget_sow-button panel-last-child\" data-index=\"11\" ><div\n\t\t\t\n\t\t\tclass=\"so-widget-sow-button so-widget-sow-button-atom-27e09ad139d7-18074\"\n\t\t\t\n\t\t><div class=\"ow-button-base ow-button-align-center\"\n>\n\t\t\t<a\n\t\t\t\t\thref=\"https:\/\/github.com\/slobaum\/cra-workers-parcel\"\n\t\t\t\t\tclass=\"sowb-button ow-icon-placement-left ow-button-hover\" target=\"_blank\" rel=\"noopener noreferrer\" \t>\n\t\t<span>\n\t\t\t<span class=\"sow-icon-fontawesome sow-far\" data-sow-icon=\"&#xf1c9;\"\n\t\tstyle=\"\" \n\t\taria-hidden=\"true\"><\/span>\n\t\t\tVisite le repo avec cette d\u00e9mo compl\u00e8te\t\t<\/span>\n\t\t\t<\/a>\n\t<\/div>\n<\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Je travaille sur FidgetMap depuis un certain temps d\u00e9j\u00e0. Je pense que je pourrais acc\u00e9l\u00e9rer beaucoup de processus (y compris la boucle de rendu de base) en ajoutant des Web Workers pour g\u00e9rer une grande partie des t\u00e2ches de rendu de mani\u00e8re asynchrone. Le jeu entier est dessin\u00e9 en \u00e9crivant des donn\u00e9es RVB dans des tableaux puis en les composant sur un canevas, donc [...]<\/p>","protected":false},"author":3,"featured_media":21450,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"default","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[10,5,7],"tags":[665,841,175,840,838,839],"class_list":["post-18074","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-about-daniel","category-professional-opinions","category-technical-jargon","tag-665","tag-create-react-app","tag-javascript","tag-parcel","tag-typescript","tag-web-worker"],"_links":{"self":[{"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/posts\/18074","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/comments?post=18074"}],"version-history":[{"count":80,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/posts\/18074\/revisions"}],"predecessor-version":[{"id":21451,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/posts\/18074\/revisions\/21451"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/media\/21450"}],"wp:attachment":[{"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/media?parent=18074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/categories?post=18074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/carterembry.com\/fr\/wp-json\/wp\/v2\/tags?post=18074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}