告诉反应本机包装器看一个非javascript文件。

时间:2021-02-14 20:52:27

I'm using a babel plugin to load environment variables from a .env file into a React Native project, but changes to the .env file are not loaded until the javascript file importing them changes. I'd like a way to tell the react-native packager to recompile in the event that this file changes. I would accept an answer that:

我正在使用一个babel插件将环境变量从.env文件加载到一个React Native项目中,但是对.env文件的修改直到导入它们的javascript文件发生改变后才被加载。我想要一种方法,告诉在这个文件发生变化的情况下,本地包装器重新编译。我愿意接受这样的回答:

  1. Simply re-transpiles the entire project when a specific file (.env) changes.
  2. 当一个特定的文件(.env)发生变化时,只需将整个项目重新传输。
  3. Re-transpiles only those files containing a specific string, say foo
  4. 只转发那些包含特定字符串的文件,比如foo

Is there a simple way to do this by writing a plugin/middleware? Maybe a separate background script that fires events to watchman that the react-native packager is listening for?

是否有一种简单的方法通过编写插件/中间件来实现这一点?也许是一个单独的后台脚本,它向watchman发送事件,而这个watcht -native packager正在监听这些事件?

[EDIT in reply to a comment]

[在回复评论时进行编辑]

My current .babelrc is the following, where babel-plugin-react-native-config is a plugin I wrote to do hot variable swapping in conjunction with the react-native-config package.

我现在的。babelrc是这样的,其中的babel-plug - in- reactor -native-config是我编写的一个插件,它与反应堆本机-config包一起进行热变量交换。

{
  "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" }]
      ]
    }
  }  
}

The problem is that the react-native packager only watches javascript files. I don't think changing my babel configuration will help, unless babel can somehow speak upwards to react-native or watchman to inform it that some file needs recompiling...

问题是,这些本地的包装器只监视javascript文件。我不认为改变我的babel配置会有什么帮助,除非babel可以通过某种方式向反应器本地或watchman发出通知,告诉它某个文件需要重新编译……

[EDIT 2]

[编辑2]

I determined that the react-native packager uses watchman to watch files. E.g., when I do watchman watch-list after starting the packager (and after doing a watchman watch-del-all), I get

我确定,堆本地包装器使用watchman监视文件。当我在启动了包装器后(在做了一个值班员值班之后),我就得到了。

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

Moreover, when I delete this watch while the packager is running, nothing happens (from its perspective, the js isn't changing because it doesn't receive any updates), but then when I restart the packager it recreates this watch and transpiles everything.

此外,当我在packager运行时删除这个手表时,什么也没有发生(从它的角度来看,js没有变化,因为它没有收到任何更新),但是当我重新启动packager时,它会重新创建这个手表并传输所有内容。

So it seems that, unless there's a better way, I have to create a watchman trigger to both (1) kill the react-packager (2) kill the watch on my app directory (3) restart the node packager. This seems slow and hacky, but I would like to see if it can even work.

因此,似乎除非有更好的方法,否则我必须创建一个watchman触发器来同时(1)杀死我的应用程序目录(3)上的watch。这似乎很慢,很陈腐,但我想看看它是否能奏效。

I haven't quite gotten this to work in a generic way, but I'm experimenting with various things.

我还没有让它以一种通用的方式工作,但是我正在尝试各种各样的东西。

1 个解决方案

#1


2  

Since it's been two weeks since I've asked this question, I'm going to post the (kind of terrible) workaround I was able to cobble together. I will leave this question unanswered, and accept any new answer that is better (less hacky) than this one.

自从我问了这个问题以来已经两周了,我要把(这类糟糕的)工作安排在一起。我将不回答这个问题,接受任何比这个更好(不那么陈腐)的新答案。

The react native packager uses watchman to watch for filesystem changes, and upon getting an event that some JS file has changed, it looks to see if the file has actually changed, and then retranspiles if so. This prevents me from doing something simple like a watchman trigger that touches the relevant JS file, because the react packager thinks it's so smart that it can ignore updates with no diff. Whatever.

react native packager使用watchman监视文件系统的更改,在获得某个JS文件已经更改的事件后,它会查看文件是否确实更改了,然后再进行转发。这使我无法做一些简单的事情,比如使用watchman触发器来触发相关的JS文件,因为react packager认为它非常智能,可以不带任何差异地忽略更新。

So my solution is to create a watchman trigger on .env changing which calls make clear_env_cache, where clear_env_cache is the following (phony) target in a Makefile.

因此,我的解决方案是在.env上创建一个watchman触发器,该触发器调用make clear_env_cache,其中clear_env_cache是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 &

Note that my_pattern will change depending on your project layout. For me there's one file importing all the envvars called Settings.js, so the pattern is "*Settings*". Note this target also basically kills and reboots the packager every time the file changes, and it nohups the node packager so you won't be able to see the process anymore. Not a big deal unless you need to view the output of the packager.

注意,my_pattern将根据项目布局进行更改。对于我来说,有一个文件导入所有的envars,叫做Settings。所以模式是“*Settings*”。注意,这个目标基本上也会在每次文件更改时杀死并重新引导包装器,并且它不会影响节点包装器,因此您将无法再看到这个过程。没什么大不了的,除非您需要查看packager的输出。

The watchman-cli command to trigger this is watchman-make --root . -p .env -t clear_env_cache and for convenience I set up a make target that nohups this command:

watchman-cli命令触发这是watchman-make -root。-p .env -t clear_env_cache为方便起见,我设置了一个make目标,不包含以下命令:

# 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 &

Now I can (once per system boot) run make hotswap_env and it will trigger whenever .env changes and ensure the packager server is continuously running.

现在,我可以(每次系统启动)运行make hotswap_env,它会在任何时候触发.env更改并确保packager服务器持续运行。

Disclaimer: This script is probably not portable, and is definitely brittle. Caveat emptor and YMMV and IANAL and all that. Suggested improvements for portability are welcome.

免责声明:该脚本可能不具有可移植性,而且肯定很脆弱。emptor, YMMV, IANAL等等。建议的可移植性改进是受欢迎的。

#1


2  

Since it's been two weeks since I've asked this question, I'm going to post the (kind of terrible) workaround I was able to cobble together. I will leave this question unanswered, and accept any new answer that is better (less hacky) than this one.

自从我问了这个问题以来已经两周了,我要把(这类糟糕的)工作安排在一起。我将不回答这个问题,接受任何比这个更好(不那么陈腐)的新答案。

The react native packager uses watchman to watch for filesystem changes, and upon getting an event that some JS file has changed, it looks to see if the file has actually changed, and then retranspiles if so. This prevents me from doing something simple like a watchman trigger that touches the relevant JS file, because the react packager thinks it's so smart that it can ignore updates with no diff. Whatever.

react native packager使用watchman监视文件系统的更改,在获得某个JS文件已经更改的事件后,它会查看文件是否确实更改了,然后再进行转发。这使我无法做一些简单的事情,比如使用watchman触发器来触发相关的JS文件,因为react packager认为它非常智能,可以不带任何差异地忽略更新。

So my solution is to create a watchman trigger on .env changing which calls make clear_env_cache, where clear_env_cache is the following (phony) target in a Makefile.

因此,我的解决方案是在.env上创建一个watchman触发器,该触发器调用make clear_env_cache,其中clear_env_cache是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 &

Note that my_pattern will change depending on your project layout. For me there's one file importing all the envvars called Settings.js, so the pattern is "*Settings*". Note this target also basically kills and reboots the packager every time the file changes, and it nohups the node packager so you won't be able to see the process anymore. Not a big deal unless you need to view the output of the packager.

注意,my_pattern将根据项目布局进行更改。对于我来说,有一个文件导入所有的envars,叫做Settings。所以模式是“*Settings*”。注意,这个目标基本上也会在每次文件更改时杀死并重新引导包装器,并且它不会影响节点包装器,因此您将无法再看到这个过程。没什么大不了的,除非您需要查看packager的输出。

The watchman-cli command to trigger this is watchman-make --root . -p .env -t clear_env_cache and for convenience I set up a make target that nohups this command:

watchman-cli命令触发这是watchman-make -root。-p .env -t clear_env_cache为方便起见,我设置了一个make目标,不包含以下命令:

# 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 &

Now I can (once per system boot) run make hotswap_env and it will trigger whenever .env changes and ensure the packager server is continuously running.

现在,我可以(每次系统启动)运行make hotswap_env,它会在任何时候触发.env更改并确保packager服务器持续运行。

Disclaimer: This script is probably not portable, and is definitely brittle. Caveat emptor and YMMV and IANAL and all that. Suggested improvements for portability are welcome.

免责声明:该脚本可能不具有可移植性,而且肯定很脆弱。emptor, YMMV, IANAL等等。建议的可移植性改进是受欢迎的。