Compressing the same unchanging JavaScript bundle on every request is work done thousands of times that could have been done once.
gzip_static on;
gzip_vary on;
# and in the build
# find public/build -name '*.js' -o -name '*.css'
# | xargs -P4 -I{} gzip -9 -k {}
With gzip_static on, nginx serves app.js.gz when it exists and the client accepts gzip, and falls back to compressing on the fly when it does not. Level 9 at build time is affordable and level 9 per request is not, so the served file is smaller as well as cheaper. gzip_vary is what stops a shared cache handing the compressed bytes to a client that did not ask for them, and omitting it is a subtle way to break exactly one proxy somewhere.