Front-end engineering practice-React project configuration pre-release environment and production environment (3)

Front-end engineering practice-React project configuration pre-release environment and production environment (3)

This is the 8th day I participated in the Wenwen Challenge. For details of the event, please view: Wenwen Challenge

I. Introduction

After completing the project initialization, first we configure different environments for project packaging.

Scenario 1: After the front-end project is developed, it must be launched. Often the test environment interface and the production environment interface domain name are different. If you manually modify the interface domain name that needs to be called for each deployment, it is easy to make mistakes and is not conducive to engineering. In practice, here is how to configure different packaging environments during the project development process.

Scenario 2: Sometimes the project does not correspond to a back-end service. If your front-end project needs to connect to the interface of multiple domain names, how should you configure it so that the code is clear and the multiple domain names do not conflict with each other.

Since the most important reason for general configuration of environment variables is to call interfaces under different domain names on the back-end through different environments. If there is no configuration, the project code will be confused, which is not conducive to later maintenance. Here we show how to distinguish different environment builds through configuration.

Ready to work:

  • Several front-end projects used for testing are all initialized through CRA
  • Install Docker locally and use Docker to test which configuration is accessed by the packaged file

2. Principle description

No matter how many environments are needed, the purpose is to make the pre-release environment read the configuration of the pre-release environment and the production environment to read the configuration of the production environment. Then various methods can be used, as long as this goal can be achieved.

Common operations in the project are:

  1. Manually modify the packaging configuration for each deployment (time-consuming and error-prone)
  2. Execute the build command, pass in the corresponding parameters, store them in a variable, and read them when needed.
  3. The project branch is associated with the CI configuration, and the corresponding environment is automatically built when building.
  4. other

Method one, it will be used when deploying temporary projects or small projects. The cost of modification is relatively low. A larger project is not applicable because it wastes time and is prone to errors.

Method two is the most commonly used way to execute build commands, such as

npm run build:pre
,
npm run build:prod
Different environments can be built, the configuration is simple, and there are many ways to implement it. At the same time, the current branch can be read to avoid making the wrong branch.

Method 3: Trigger project configuration through CI, no manual construction is required, but it involves more knowledge and the configuration is the most complicated. It is a required solution for super large projects. General projects can be used, but it is not necessary.

Knowing the principle and purpose, then other implementation methods are not difficult:

  • Modify environment variables, distinguish different configuration files through environment variables
  • by
    shell
    , Create multiple configuration files under the project
    .env .env_pre .env_production .env_local
    , In packaging
    production
    Back up the environment first
    .env
    ,by
    cp
    Command copy
    .env_production
    The file is
    .env
    , Restore after packaging is complete
    .env
    Files to realize the configuration of different environments
  • Through the node, fs file module, forcibly write environment variables to achieve
  • You can even build the project first, and then introduce the configuration file outside the project

Below we choose several commonly used methods, specific configuration and demonstration, how to build different packaging environments.

The project used below is the last article, the most basic project template we built through CRA. For specific project demos , we use different branches to demonstrate.

two,
cross-env
Modify variables (recommended)

Demonstration use of this link

environment/cross-env
Branching will also be the main packaging method of the project.

1. Cross-env description

cross-env is a script file that can cross-platform settings and modify project environment variables

Version 6 of cross-env only supports Node.js 8 and higher

2. Install plugins that modify environment variables

yarn add cross-env -D duplicated code

3. Modify the package.json startup script

"scripts": { "start": "cross-env REACT_APP_ENV=development react-app-rewired start", "build:pre": "cross-env REACT_APP_ENV=development react-app-rewired build", "build:prod": "cross-env REACT_APP_ENV=production react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" } Copy code

Can be used here

REACT_APP_
Any variable at the beginning

4. Execute different commands and start different environments

  • yarn start
    REACR_APP_ENV will be set to development at startup, which is used as a local development
  • yarn build:pre
    Package the pre-release environment code, set REACR_APP_ENV to development, which is the same as the local execution environment, of course you can configure it yourself
  • yarn build:prod
    Package the production environment code, set REACR_APP_ENV to production

You can configure these environment variables for general projects, and you can also add other environments.

5. Read variables in the project

console.log(process.env.REACR_APP_ENV) Copy code

Just use it directly in the project, and then we configure the interface requests in different environments.

6. Configure different access addresses for the interface

Create new in the src directory

config
Folder, new file

const version = require("../../package.json")//Get the current version export const development = {//Configure pre-release and local environment interface env: "development", version, links: { upm: "/api/test", case: "/api/forward" }, apis: { api: "/api/test", case: "/user" } } export const production = {//Configure the production environment interface address env: "production", version, links: { upm: "/production/api/test", case: "/production/api/forward" }, apis: { api: "/production/api/test", case: "/production/user" } } Copy code

You should know what you are doing by looking at the file configuration. There are usually variables used in different environments in the project, such as

  • version number
  • Jump links within the page
  • The most important interface request domain name

Here are unified introduction under this file to facilitate subsequent expansion of more configurations

Next is to create another file in the same path

index.tsx

import * as config from "./environment" class Config { static DEV:string = "development"; static PRODUCTION:string = "production"; static allKeys:string[] = ["development", "pre", "production"]; static currentDev: string = process.env.REACT_APP_ENV || Config.PRODUCTION static isDev(): boolean { return Config.currentDev === Config.DEV; } static isProduction(): boolean { return Config.currentDev === Config.PRODUCTION; } static getUrlLinks(key:string):string{ return config[Config.currentDev].links[key]; } static getApiUrl(key: string):string { return config[Config.currentDev].Apis[key]; } static getVersion():string { return config[Config.currentDev].version; } } export default Config Copy code

7. Obtain current environment variables through this file, and package functions to obtain different configuration information

(1) in

src/index.tsx
in,

import Config from'src/config' console.log("Get Environment", Config.env) Copy code

(2) Then execute

yarn build:pre
,can be seen
build
The file is deployed successfully.

(3) Start the local docker service (the docker command description is at the end ), and then run

docker run -d -v/Users/user /Desktop/mine/fronted-demo/build:/usr/share/nginx/html -p 8000: 80 --name nginx-fronted1 nginx duplicated code

(4) Visit in the browser

http://localhost:8000

(5) Implementation

yarn build:prod
, Restart the docker container, access
http://localhost:8000
, You will find that what is printed at this time is

We can see that different addresses can be requested by passing in different variables.

In the same way, modifying the environment corresponding to build:pre and build:prod can ensure the separation of the production environment and the development environment.

See the environment/cross-env branch for detailed code

3. use the .env configuration file under the project

Method 1: Use only the environment configuration that comes with the project

1. Cra itself has been configured with different environments, we only need to configure under the project

.env
.env.production
File on it, when executed
yarn start
, The project will read
.env
Configuration, when executed
yarn build
The project will read the .env.production file, so if your project is not complicated, you can completely omit this step of configuration and directly use the configuration that comes with the project

.env

REACT_APP_ENV = environment duplicated code

.env.production

REACT_APP_ENV = production copy the code

2. Restore

package.json

3. Print content

Execute at this time

yarn build
, Deploy docker, open the browser
localhost:8000

See the environment/env branch for detailed code

Method 2: Combine dotenv-cli to modify the packaging environment

This method is demonstrated under the environment/env-dotenv-cli branch

1. Install dotenv-cli

yarn add dotenv-cli -D

dotenv-cli is a very simple script that can help the project to read different

.env
file.

2. Create a new .env .env.pre .env.production file in the root directory

.env

REACT_APP_ENV = development REACT_APP_API_REST = https://localhost:9000 REACT_APP_API_USER = https://localhost:9001 Copy code

.env.pre

REACT_APP_ENV = pre REACT_APP_API_REST = https://www-pre.baidu.com REACT_APP_API_USER = https://www-pre.nihao.com Copy code

.env.production

REACT_APP_ENV = production REACT_APP_API_REST = https://www.baidu.com REACT_APP_API_USER = https://www.nihao.com Copy code

3. Modify package.json

"scripts": { "start": "react-app-rewired start", "build:pre": "dotenv -e .env.pre react-app-rewired build", "build:prod": "dotenv -e .env.production react-app-rewired build" } Copy code

in

build:pre
Added to the instruction,
dotenv -e .env.pre

The execution can be seen here

yarn build:pre
Read the configuration content of .env.pre, so that the project can read different configurations, you can see this method is to put the configuration file in the env, the above method is to put the file in In the js file, there is little difference.

Demo code, branch environment/env-dotenv-cli

4. directly use the node package to write variables

This branch uses the environment/env-create-fs branch to demonstrate

Through the plug-in we write variables, which means that as long as we have a configuration, we can identify the current environment, so we can create a new .env file in the project root directory and declare a variable

REACT_APP_BUILD_ENV = development duplicated code

At this time, reading the variable will be

development
, You only need to modify this variable before packaging.

The specific operation is created in the root directory

config-env.js
File, one thing to note here is
commander
There are changes in the syntax of the high and low versions of, you need to pay attention to the documentation

const fs = require('fs'); const program = require('commander'); program.option('-e, --env <type>','set build env','pre'); program.parse(process.argv); const params = program.opts() const $1 = params.env; if (['development','pre','production','proxy'].includes($1)) { try { fs.writeFileSync('.env', `REACT_APP_BUILD_ENV ='${$1}'`,'utf-8'); } catch (error) { console.error(error); return; } } else { console.error('The parameter does not meet the requirements'); return; } Copy code

Modify the package.json file

"scripts": { "start": "node ./config-env.js && react-app-rewired start", "build:prod": "node ./config-env.js -e production && react-app-rewired build", "build:pre": "node ./config-env.js -e pre && react-app-rewired build" } Copy code

Here you can see the execution of the packaging command, and then run

config-env.js
File, the file refers to the node's fs module and commander package, reads the incoming environment variables, and then uses the fs method to modify the environment variables of the file, and run directly

Because the project reads by default

.env
File, so we just need to execute
node./config-env.js -e production
File see
.env
The environment variable can be modified successfully.

For the sample code of specific configuration, see the branch environment/env-create-fs

5.points to note

1. Ts obtains the corresponding value through the variable, and reports an error, the solution?

static getUrlLinks(key:string):string{ return config[Config.currentDev].links[key]; } Copy code

Here ts syntax will report an error

The solution is to temporarily block it directly, add configuration in tsconfig.json

{ "compilerOptions": { "suppressImplicitAnyIndexErrors": true } } Copy code

2. The .env* file needs to be

REACR_APP_
At the beginning, can be read in the project

3. Start the docker image

nginx

docker run -d -v/Users/user /Desktop/mine/fronted-demo2/build:/usr/share/nginx/html -p 8000: 80 --name nginx-fronted2 nginx duplicated code
  • Where -d follows
    /Users/user/Desktop/mine/fronted-demo/build:/usr/share/nginx/html
    Separate by a colon, and the address of my local project is in front
  • build is the folder where the files are located after the project is packaged, followed by the path accessed by the nginx container, and run the project by mounting
  • -p 8000:80 means that local access is through port 8000, port 80 used by the container
  • --name nginx-fronted Name the container to be started
  • Nginx is the name of the image that starts the container, and it will not be pulled locally from the remote docker warehouse.

4. Other available plug-ins www.npmjs.com/package/env...

6. github project example