You are completely right that it should be the same artifacts that are deployed to all environments. Especially in npm, dependencies tend to be loosely defined so a updated dependency could easily break the build just by building at different times. Even if you don't use hat or tilde in packages.json transient dependencies could be less strict with versioning.
What is suggested in the other answer regarding dotenv will not work unless you buildcombine it multiple times or host eg. express to serve and transform indexwith #2 og #3 from this answer.html
Basically you have a few options.
Switch on the url in order to find the current environment you are in. This is a complete hack. Do not do this!!
Have some server side code replace global vars in index.html on each request. The simplest solution depends on what you have installed on your server. It could be php or even something simple as SSI if you are on IIS. You will want to keep you index.html as valid html so you still can do local development. SSI is nice in this regard since it works inside comments. If you do php, keep your index.html and make a index.php which reads index.html but replaces your vars. A html parser works well for this replacement.
Setup your release to generate a transformed index.html from the original index.html created during build. This transformed index contains a snapshot of variables for a given environment when release is run on the environment.
If your needs are simply configuration variables, I would recommend #3. If you need something a little more advanced, go for #2.