Since joining the new company, I took over vUE project in the first month, AngularJS project in the second month, and React reconstruction project in the third month. Xinsheng sighs: Business-driven learning is an efficient way to learn, keep curious, and grow fast in the business!

The new project has a proxy field in package.json, which I have never seen before, so this article was born. I used create-react-app to create a new project in its original state. Learn about proxy fields and create-react-app entanglements.

In nPM-Configuration, proxy is explained as follows:

The default value is null and the type is URL, a proxy for sending HTTP requests. If the HTTP__PROXY or http_proxy environment variable is already set, the proxy setting is implemented by the underlying request library.

Proxying API Requests in Development, Proxying API Requests in Development, Proxying API Requests in Development, React-scripts should do some encapsulation based on the HTTP_PROXY environment variable.

After reading this article, you will learn one thing:

  • How to gracefully configure a Proxy server for a front-end project
  • Read HTTP’s Definitive Guide to proxies before revisiting them
  • New insights into the limitations of easy-mock use
  • I was shocked that process.env could be displayed directly in the React layer
  • You learned about the dotenv and expand-env libraries that can be extended to process.env

It is mainly divided into three parts:

  • Proxy API request Settings during development
  • Manually Configuring proxy
  • Configure Proxy using environment variables

Proxy API request Settings during development

Note: This feature is available in [email protected] and later versions.

People typically serve front-end React applications as well as hosts and ports that will serve back-end implementations. For example, after an application is deployed, the production configuration looks like this:

/ - Static server returns React app and index.html /todos - Static server returns React app and index.html/API /todos - Server uses backend implementation to handle all/API /* requestsCopy the code

But this setting is not necessary. However, if you do have such a setting, it is normal to write requests like FETCH (‘/ API /todos’) without considering redirecting them to other host and port development environments.

To tell the development environment server to proxy any requests unknown in the development environment to our own API server, add a proxy field to package.json, for example:

"proxy":"http://localhost:4000"
Copy the code

Use this form, when you are in a development environment using fecth (‘ API/todos’), the development environment of the server will recognize this is not a static resource, then agent forward your request to the http://localhost:4000/api/todos as a callback. Production servers can only proxy requests without text/ HTML in the Accept header.

Conveniently, this avoids CORS problems and error messages like the one below.

Fetch API cannot load http://localhost:4000/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Copy the code

Keep in mind that proxies only have side effects in a development environment, and it’s up to us to see if urls like/API /todos point correctly in a production environment. You don’t need to use the/API prefix. Any unrecognized requests without text/HTML request headers will be proxied to the configured server.

The proxy option supports HTTP, HTTPS, and WebSocket connections. If the proxy option isn’t flexible enough, you can customize it:

  • Configure the proxy yourself (not tested)
  • Enable CORS on the server side (express and KOA can be implemented, koA can use KOA-CORS directly)
  • Inject the correct server and port to the application using environment variables (not tested)

To illustrate the point, let’s take a local experiment:

  • Start the service
npx creat-react-app my-app
cd my-app
npm run start
Copy the code
  • Import AXIos and send the request
npm i axios --save
Copy the code
componentDidMount(){
    axios.get('/foo')
        .then(function (response) {
          console.log(response);
        })
        .catch(function (error) {
          console.log(error);
        });
}
Copy the code

Request: “http://localhost:3000/foo” error message: 404

We added a proxy server for package.json:

"Proxy" : "http://0.0.0.89:7300"Copy the code

CTRL + S react-code update does not take effect, still error 404.

NPM run start After the local service is restarted, the proxy server takes effect and returns normal data.

Automatic forwarding of “http://localhost:3000” requests to the server of “http://0.0.0.89:7300”.

I don’t know if you’re smart enough to notice, but we don’t have a CORS problem, because in the browser’s eyes, we still send the request to “http://localhost:3000”, It doesn’t know that creat-React-app has forwarded the request to “http://0.0.0.89:7300”, another Origin that supposedly triggers the browser’s CORS security policy.

Naive browser:

segmentfault.com/img/bVbdNRf

Request path: “http://localhost:3000″ →”http://0.0.0.89:7300/foo”

Response Path: “http://0.0.0.89:7300/foo” →”http://localhost:3000″ Note: 1. You need to run the NPM run start command again to restart the local service. Otherwise, the proxy configured in package.json will not be detected and take effect. 2. The server can be the Node service started on a VM on the Intranet, or a mock server such as Easy-Mock (only the Intranet deployment version is supported, but the Dasoche online server does not support it).

So we come to a conclusion:

Creat-react-app scaffolding can be combined with a proxy in package.json to implement request forwarding.

Successful experiment!

Manually Configuring proxy

Note: This feature is available in [email protected] and later versions.

If the default configuration of the proxy is not flexible enough, you can customize an object in package.json that looks like this. You can also do http-proxy-middleware or HTTP-proxy.

{" proxy ": {"/API" : {" target ":" < url > ", "ws" : true}}}Copy the code

All requests that match this path will be forwarded by the proxy. This includes text/ HTML type requests, which are not supported by the standard Proxy option.

If you need to configure multiple agents, you need to define several entries. The matching rules remain the same, so that you can match multiple paths using regex.

{/ /... "proxy": { // Matches any request starting with /api "/api": { "target": "<url_1>", "ws": true // ... }, // Matches any request starting with /foo "/foo": { "target": "<url_2>", "ssl": true, "pathRewrite": { "^/foo": "/foo/beta" } // ... }, // Matches /bar/abc.html but not /bar/sub/def.html "/bar/[^/]*[.]html": { "target": "<url_3>", // ... }, // Matches /baz/abc.html and /baz/sub/def.html "/baz/.*/.*[.]html": { "target": "<url_4>" // ... }} / /... }Copy the code

Engineering male persistent, continue to do an experiment:

The above my-app project is still used, and the proxy configuration is as follows:

"Proxy" : {"/API ": {" target" : "http://0.0.0.89:7300", "ws" : true}, "/ foo" : {" target ":" http://0.0.11.22:8848 ", "ws" : true, "pathRewrite": { "^/foo": "/foo/beta" } } }Copy the code

The code is as follows:

    axios.get('/api')
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });
    axios.get('/foo')
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    });
Copy the code

Result: The API interface is the same as before, and we focus on the foo interface for orientation.

Request path: “http://localhost:3000” > “http://0.0.11.22:8848/foo” > “http://0.0.11.22:8848/foo/beta”

Response to return path: “http://0.0.11.22:8848/foo/beta” – > “http://localhost:3000”

Two proxies can be configured. Here we use two proxy servers “http://0.0.0.89:7300” and “http://0.0.11.22:8848”, among which “http://0.0.0.89:7300” provides API interface. “http://0.0.11.22:8848” provides the foo interface. And we can redirect the interface on the proxy server.

So we come to a conclusion:

Creat-react-app scaffolding can be combined with proxies in package.json, which can be configured to pair proxies, and we can redirect interfaces on the proxy server.

Successful experiment!

Configure proxy using environment variables

This feature is available in [email protected] and later versions.

React projects can use already declared environment variables, which act like local variables defined in your JS files. By default, there is already a default NODE_ENV environment variable, as well as other environment variables prefixed with REACT_APP_.

** Environment variables are embedded during build. ** Because the Create React App provides static HTML/CSS/JS packaging, it cannot be read at Runtime. In order to read the environment variable during runtime, you need to also enter the HTML into the Server’s memory and replace a placeholder at runtime, as described here: Injecting Data from the Server into the Page. In addition, you can rebuild the application any time you change them.

You need to use REACT_APP_ to create generic environment variables. Any variables other than NODE_ENV are ignored, to avoid exposing a private key on the machine that could have the same name. Whenever you change environment variables during runtime, you need to restart the development server.

These environment variables will be defined in process.env. For example, there is an environment variable called REACT_APP_SECRET_CODE, which can be exposed in our javascript file via process.env.react_app_secret_code.

We also have a built-in environment variable called NODE_ENV. You can read it via process.env.node_env. When you run NPM start, NODE_ENV has a value of development, when you run NPM test, NODE_ENV has a value of test, and when you run NPM run build to build a package for the production environment, it is usually production. ** You cannot override NODE_ENV manually. ** This prevents developers from mistakenly deploying code from the development environment to the production environment.

These environment variables can be used to conditionally display information based on where the project is deployed or using sensitive data beyond version control.

First, you need a defined environment variable. For example, say you want to control a secret variable in the form form.

Render (){return (<div> <small> Your application runs in <b>{process.env.node_env}</b> mode. </small> <form> <input type="hidden" defaultValue={process.env.REACT_APP_SECRET_CODE} /> </form> </div> ); }Copy the code

During build, process.env.react_app_secret_code will be replaced by the current value in the environment variable. Remember that NODE_ENV is an automatically set variable.

When you view input in a browser, it is already set to ABCDE (or empty). The form above searches for a variable named REACT_APP_SECRET_CODE from the environment variable. To use this value, we need to define it in the environment. There are two ways to do this, either in a shell definition or in an. Env file.

Some operations can be controlled using NODE_ENV:

if(process.env.NODE_ENV ! == 'production'){ analytics.disable(); }Copy the code

When you compile your app using NPM run Build, it will make the file smaller.

Referencing environment variables in HTML:

Note: This feature is used in [email protected] and later versions.

You can get environment variables prefixed with REACT_APP_ in public/index.html. Such as:

Matters needing attention:

  • Except for the built-in variables (NODE_ENV and PUBLIC_URL), variable names must start with REACT_APP_ to work properly.
  • Environment variables can be injected during build. If you want to inject them at runtime, use this method: Generating Dynamic Tags on the Server

Adding temporary environment variables to the shell The environment variables are set differently for different operating systems. But more importantly, this is the way variables are created only if the current shell Session window is valid.

Linux and macOS (Bash)

REACT_APP_SECRECT_CODE=abcdef npm start
Copy the code

There is also a way to create an.env file that defines environment variables.

Env files will be checked for source control.

How will other. Env files be used?

This feature is only available in [email protected] and higher

You can use dotenv to inject values from. Env into process.env. Such as:

require('dotenv').config()
Copy the code

Define an. Env file at the root of your project and type the following:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
Copy the code

This can then be accessed in process.env:

const db = require('db')
db.connect({
  host: process.env.DB_HOST,
  username: process.env.DB_USER,
  password: process.env.DB_PASS
})
Copy the code
.env: Default. .env.local: Local overrides. Load environment variables other than test. .env.development,.env.test,.env.production: public environment variables. Local,.env.test.local,.env.production. Local: local environment variable.Copy the code

The one on the left has higher priority than the one on the right:

npm start: .env.development.local, .env.development, .env.local, .env
npm run build: .env.production.local, .env.production, .env.local, .env
npm test: .env.test.local, .env.test, .env (note .env.local is missing)
Copy the code

How to extend system environment variables to.env files under our project using:

Use dotenv – expand

REACT_APP_VERSION=$npm_package_version
# also works:
# REACT_APP_VERSION=${npm_package_version}
Copy the code

Variables can also be used inside the. Env file:

DOMAIN=www.example.com
REACT_APP_FOO=$DOMAIN/foo
REACT_APP_BAR=$DOMAIN/bar
Copy the code

Engineering male persistent:) do a simple experiment:

touch .env
code .env
Copy the code

Type:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
Copy the code

Code:

console.log("process.env.DB_HOST-->%s,process.env.DB_USER-->%s,process.env.DB_PASS-->%s",process.env.DB_HOST,process.env .DB_USER,process.env.DB_PASS)Copy the code

Experimental results:

process.env.DB_HOST-->undefined,process.env.DB_USER-->undefined,process.env.DB_PASS-->undefined
Copy the code

The results are not always satisfactory, the problem is not knowing where require(‘dotenv’).config() might need to be introduced in the Node layer, or something like webpack might be needed to make it accessible to the View layer.

The experiment failed. To sum up:

  • Proxy API request Settings during development (default selection, for most situations)
  • Manually configure Proxy (multi-proxy, redirection)
  • Environment variable Proxy configuration (temporary variable mode is easy to use,.env mode is more complex, can use configuration file instead)

I am looking forward to communicating with you and making progress together. Welcome to join the technical discussion group I created which is closely related to front-end development:

  • SegmentFault technosphere :ES new specification syntax sugar
  • SegmentFault column: Be a good front-end engineer while you’re still young
  • Zhihu column: Be an excellent front-end engineer while you are still young
  • Github blog: Personal blog 233 while You’re Still Young
  • Front-end development QQ group: 660634678
  • excellent_developers

Strive to be an excellent front-end engineer!