Question Dites à un emballeur natif de regarder un fichier non javascript


J'utilise un plugin babel pour charger des variables d'environnement à partir d'un .env déposer dans un projet React Native, mais les changements à la .env fichier ne sont pas chargés jusqu'à ce que le fichier javascript les important. Je voudrais un moyen de dire au gestionnaire de paquets natif de recompiler si ce fichier change. J'accepterais une réponse qui:

  1. Recopie simplement le projet entier lorsqu'un fichier spécifique (.env) changements.
  2. Re-transpose uniquement les fichiers contenant une chaîne spécifique, par exemple foo

Y a-t-il un moyen simple de le faire en écrivant un plugin / un middleware? Peut-être un script d'arrière-plan distinct qui déclenche des événements pour le guetteur que le gestionnaire de paquets natif réagit à l'écoute?

[EDIT en réponse à un commentaire]

Mon actuel .babelrc est le suivant, où babel-plugin-react-native-config est un plugin que j'ai écrit pour faire un échange de variables à chaud en même temps que le react-native-config paquet.

{
  "presets": [
    "react-native"
  ],
  "plugins": [
     ["babel-plugin-espower", {
       "sourceRoot": "./App"
     }],
     "transform-flow-strip-types"
  ],
  "env": {
    "production": {
      "plugins": [
        "babel-plugin-unassert",
      ]
    },
    "development": {
      "plugins": [
        ["babel-plugin-react-native-config", { envfile: ".env" }]
      ]
    }
  }  
}

Le problème est que le conditionneur réactif ne surveille que les fichiers javascript. Je ne pense pas que changer ma configuration de babel aidera, à moins que Babel puisse parler d’une façon ou d’une autre à react-native ou watchman pour l’informer que certains fichiers doivent être recompilés ...

[EDIT 2]

J'ai déterminé que le conditionneur réactif utilise un gardien pour regarder les fichiers. Par exemple, quand je fais watchman watch-list après avoir commencé le conditionneur (et après avoir fait une watchman watch-del-all), Je reçois

{
    "version": "4.6.0",
    "roots": [
        "/path/to/my/project"
    ]
}

De plus, quand je supprime cette montre alors que le conditionneur est en cours d'exécution, rien ne se passe (de son point de vue, le js ne change pas car il ne reçoit aucune mise à jour), .

Donc, il semble que, à moins d'une meilleure solution, je dois créer un déclencheur de surveillance pour (1) tuer le réactif-emballeur (2), tuer la montre sur mon répertoire d'applications (3) et redémarrer le gestionnaire de paquets. Cela semble lent et piraté, mais j'aimerais voir si cela peut même fonctionner.

Je n'ai pas tout à fait compris que cela fonctionne de manière générique, mais j'expérimente diverses choses.


10
2018-02-13 19:47


origine


Réponses:


Depuis que j'ai posé cette question il y a deux semaines, je vais poster la solution (un peu terrible) que j'ai pu bricoler. Je vais laisser cette question sans réponse, et accepter toute nouvelle réponse qui est meilleure (moins pirate) que celle-ci.

La réaction du conditionneur natif utilise watchman pour surveiller les modifications du système de fichiers, et après avoir reçu un événement indiquant que certains fichiers JS ont été modifiés, il vérifie si le fichier a réellement été modifié, puis retransmet si oui. Cela m'empêche de faire quelque chose de simple comme un déclencheur de gardien qui touches le fichier JS approprié, car le gestionnaire de réaction pense qu'il est si intelligent qu'il peut ignorer les mises à jour sans diff. Peu importe.

Donc, ma solution est de créer un déclencheur de gardien sur .env changer quels appels make clear_env_cache, où clear_env_cache est la cible suivante (bidon) dans un Makefile.

# get the PID of the react packager
pid := $(shell lsof -i:8081 | grep node | awk '{print $$2;}' | head -n 1)

# Kill files that the packager uses to determine whether it needs to 
# re-transpile a js file, then restart the packager
clear_env_cache:
    find ${TMPDIR}/react-native-packager-cache-* -name "my_pattern" | xargs rm
    kill -9 $(pid) || echo "no packager running"
    nohup node node_modules/react-native/local-cli/cli.js start > /dev/null 2>&1 &

Notez que my_pattern changera en fonction de la mise en page de votre projet. Pour moi il y a un fichier important tous les envvars appelés Settings.js, donc le motif est "*Settings*". Notez que cette cible tue et redémarre aussi l’empaqueteur chaque fois que le fichier est modifié. nohups le gestionnaire de paquets pour ne plus voir le processus. Pas un gros problème à moins que vous ayez besoin de voir la sortie du conditionneur.

La commande watchman-cli pour déclencher ceci est watchman-make --root . -p .env -t clear_env_cache et pour plus de commodité, j'ai mis en place une cible qui nohups cette commande:

# Run `make hotswap_env` to allow envvar changes to show up in the react-native packager.
hotswap_env:
    nohup watchman-make --root . -p .env -t clear_env_cache > /dev/null 2>&1 &

Maintenant, je peux (une fois par démarrage du système) exécuter make hotswap_env et il se déclenchera chaque fois que .env modifications et assurez-vous que le serveur de conditionnement fonctionne en permanence.

Avertissement: Ce script n'est probablement pas portable et est définitivement fragile. Caveat emptor et YMMV et IANAL et tout ça. Les améliorations suggérées pour la portabilité sont les bienvenues.


2
2018-02-27 23:20