React 17 system intensive lecture combined with TS to create a tourism e-commerce platform
-
- 2-2 [Environment Construction] Start our first React project
- 2-3 [Project Start] Use create-react-app to quickly build React
- 2-5 [TypeScript configuration] tsconfig.json detailed explanation
- 2-6 [Extended reading] tsconfig.json compiler configuration document
- 2-7 【TypeScript configuration】Dig deep into the TS compilation process
- 3-1 Learning with questions
- 3-2 Chapter Overview
- 3-3 [Conceptual understanding] The past and present of React
- 3-4 [Componentization] First understanding of React functional components
- 3-5 [Conceptual understanding] JSX programming thinking
- 3-6 [Componentization] Configuring CSS modules for React
- 3-7 【Extended reading】CSS in JS (JSS)
- 3-8 [Resource configuration] Load media and font files
- 3-10 [Extended reading] React's inline style and CSS
- 3-11 [Conceptual understanding] State vs Props
- 3-12 [Event-driven] React Event event processing
- 3-13 [Asynchronous processing] Get network API data
- 3-14 [Asynchronous processing] Asynchronous development of setState
- 3-15 [Death and Rebirth] Exploring the life cycle of React components
- 3-16 [Conceptual understanding] React 17 version changes
- 4-1 Learning with questions
- 4-2 [Conceptual understanding] What are hooks?
- 4-3 [State Hook] Use useState to manage component state
- 4-4 [Concept understanding] side effects
- 4-5 [Side Effect Hook] Use useEffect to get data asynchronously
- 4-6 [Side Effect Hook] useEffect User Guide
- 4-7 [Global data transfer] Context and useContext
- 4-8 [Global Data Transfer] Component Context Provider
- 4-9 [High-level component HOC] withAddToCart()
- 4-10 [Custom Hook] useAddToCart()
- 5-2 [Project Planning] Website Development and Design Guidelines
- 5-3 [Project Start] System Design and Project Initialization
- 5-4 [Home Page Development] Header, Footer
- 5-5 [Project Refactoring] Componentization Thought and Practice
- 5-6 [Home page development] Multiple menus of carousel and sidebar
- 5-7 [Home Page Development] Recommended Popular Products
- 5-9 [Discussion Questions] Software Development Life Cycle
- 6-1 Learning with questions
- 6-2 [Concept Understanding] Routing and SPA
- 6-3 [Routing initialization] Configure react-router
- 6-4 [Routing Architecture] Basic Routing System
- 6-5 [routing construction] page navigation
- 6-6 [routing construction] withRouter and useRouter
- 7-2 [Concept understanding] What is redux?
- 7-3 【Create state】createStore
- 7-4 [Access state] Get store data
- 7-5 [Update state] Action and Reducer processing
- 7-6 [Subscription state] store connection and subscription
- 7-7 [i18n] complete website language switching
- 7-8 [redux refactoring] action splitting and unification
- 7-9 [redux package] use react-redux in class components
- 7-10 [redux package] use react-redux in functional building
- 7-11 [Discussion Question] In-depth analysis of redux
- 8-1 Learning with questions
- 8-2 [Concept understanding] RESTful
- 8-3 [API Description] Where is the backend of the course?
- 8-4 [API connection] AJAX asynchronously obtains recommendation data
- 8-5 [Conceptual understanding] Redux vs MVC
- 8-6 【reducer管理】combineReducers
- 8-7 [Middleware] Use redux-thunk middle price to realize asynchronous action
- 8-8 [Middleware] What is middleware
- 8-9 [Middleware] Custom middleware actionLog
- 8-10 [RESTful Advanced (Elective)] Richardson Maturity Model and HATOAS
- 9-2 Chapter Overview (redux-toolkit)
- 9-3 [Detail page construction 1] Page frame, details and date selection
- 9-4 [Detail page construction 2] Page frame, details and date selection
- 9-5 [Concept understanding] What is redux-toolkit
- 9-6 【redux-toolkit】createSlice、reducer、与immer
- 9-7 [Concept understanding] The theoretical basis of createAsyncThunk
- 9-8 [redux-toolkit] sotre configuration (configureStore) and asynchronous processing (createAsyncThunk)
- 9-9 【Comprehensive use】Search page
- 10-2 [Layout Refactoring] Page Layout
- 10-3 [Registration page] Antd + ts form processing
- 10-4 [Registration page] Registration business logic processing
- 10-5 [Concept understanding] The importance of Status Code
- 10-6 [Login page] User login form and layout
- 10-7 【Concept understanding】JWT principle analysis
- 10-8 [JWT example] JWT and single sign-on example explanation
- 10-9 【Login page】SignIn login business processing
- 10-10 [Login page] SignOut logout business processing
- 10-11 [redux-persist] login persistence
- 11-1 Learning with questions
- 11-2 [Advanced Routing] Build Private Routing
- 11-3 [UI Construction] Shopping Cart Page Initialization
- 11-4 [Redux Creation] Shopping Cart Slice
- 11-5 [redux connection] load shopping cart
- 11-6 [Complete the shopping module] Place an order in the shopping cart
- 11-7 [UI Construction] Online Payment Page Initialization
- 11-8 [Redux Creation] Order Slice
- 11-9 [redux connection] complete online payment
- 12-2 [Chapter Overview] Deployment Solution Introduction
- 12-3 [Static deployment] local server hosting
- 12-4 [Concept understanding] 5 minutes to take you to know Docker
- 12-5 [Cheat Sheet] Commonly used docker commands
- 12-6 [Environment Construction] Containerization Solution and Docker Configuration
- 12-7 【Cheat sheet】Dockerfile syntax
- 12-8 [Container transformation] Understand the whole process of Dockerfile
- 12-9 【Containerized Online】Realize Alibaba Cloud Deployment
- recommended reading
勤学如春起之苗,不见其增,日有所长;
辍学如磨刀之石,不见其损,日有所亏。
Each lesson is submitted to Code Cloud separately. If you want to see the code content of a specific section, you can find the corresponding submission record on Code Cloud.
查看代码改动
Code cloud warehouse address :
https://gitee.com/WebJianHong/react-travel
2-2 [Environment Construction] Start our first React project
Scaffolding create-react-app
node version:14.15.0 LTS
npx create-react-app my-app
2-3 [Project Start] Use create-react-app to quickly build React
2-5 [TypeScript configuration] tsconfig.json detailed explanation
TS pain points
- The learning cost is very high and the learning curve is very steep
Use create-react-app
the react project that builds TS
npx create-react-app my-app-ts --template typescript
TypeScript
- TypeScript is a superset of JS
- Add static type checking to native JS
- Like ES6, it cannot be directly read by mainstream browsers
Compilation of TypeScript
- Compiler
babel-loader
(create-react-app project comes with it) - configuration file:
tsconfig.json
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": false, // 不需要显示地声明变量的类型any
"target": "es5", // 编译后目标JS版本
"lib": [
"dom", // document.getElementById("root")
"dom.iterable",
"esnext"
],
"allowJs": true, // 允许混合编译JS文件
"skipLibCheck": true,
"esModuleInterop": true, // 允许我们使用commonjs的方式import默认文件 import React from 'react'
// "esModuleInterop": false, import * as React from 'react'
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext", // 配置的是我们代码的模块系统 常见的有Node.js的CommonJS ES6标准的esnext requestJs的AMD
"moduleResolution": "node", // 决定了我们编译器的工作方式
"resolveJsonModule": true,
"isolatedModules": true, // 编译器会将每个文件作为单独的模块来使用
"noEmit": true, // 表示当编译发生错误的时候 编译器不要生成ES5或者ES6 JS代码
"jsx": "react-jsx" // 允许编译器编译react代码
},
"include": [
"src"
]
}
2-6 [Extended reading] tsconfig.json compiler configuration document
[Extended reading] tsconfig.json
Compiler configuration documentation
Generally speaking, TS编译器配置
the entirety of the project is stored in 项目根目录下的tsconfig.json文件
.
When the compiler starts, it first reads tsconfig.json
for instructions on how to compile the project (for example, which source files to compile, where to store the output, etc.).
However, if the compiler configuration file is saved in the location, we can also tell the specific location of the compiler configuration file 其他特殊位
by using : Now, let's study the more common compiler options that appear in the above figure:-p选项
/tsconfig
- “target”: “es5”
This attribute defines you 编译后的目标javascript版本
,
Generally speaking, we need to compile it to es5 so that it can be interpreted by mainstream browsers.
Of course, you said that my react code is not for the browser to read. For example, if you are using a react-native
mobile phone app, you can choose the options here es6
.
In addition to es5 and es6, we have many other common options, ES5, ES6/ES2015, ES2016, ES2017, ES2018, ES2019, ES2020, ESNext, etc.
2. “lib”: [“dom”, “dom.iterable”, “esnext”]
This property lists 编译期间需要被包括进来的库文件
, through these library files, tells the TypeScript compiler which functions are available.
For example, we have a dom library file here, this file will tell the compiler the interface of the dom api, so when we use dom in the ts code, for example, when executing this sentence, the compiler will know “document.getElementById("root")”
the How to check.
If we don't set this option, then the compiler also has its own default list of library files, generally speaking, ["dom", "es6","DOM.Iterable"]
etc.
- “allowJs”: true
allow混合编译JavaScript文件
- “esModuleInterop”: true
This option allows us 使用ES6的方式import默认文
pieces. For example, when this option is not enabled, we need to write like this to reference react:
import * as React from 'react'
But when we enable this option, the import method is no different from ordinary JavaScript, which can be written as:
import React from 'react'
It is more natural to handle project imports this way.
- “module”: “esnext”
What is configured here is the module system of our code, the more common ones are Node.js的CommonJS系统
, ES6标准的esnext系统
, and requirejs的AMD系统
. We are using the ES6 standard esnext system here, but it is also possible to replace it with CommonJS.
- “moduleResolution”: “node”
This option 决定了我们编译器的工作方式
also determines us 各个文件之间调用
, import的工作流程
. There used to be two options, "node" and "classic", but the "classic" option was deprecated in December 2019.
- “isolatedModules”: “node”
After enabling this option, 编译器
it will be used 每个文件作为单独的模块
in the future .
-
"noEmit": true,
enabling this option means that when an error occurs, the compiler will not generate JavaScript code. -
“jsx”: “react”
Obviously, this option允许编译器支持编译react代码
- “include”: [“src/**/*”]
Use this option to list our 需要编译的文
files, the "File Path" option requires a relative or absolute path to the file, for example:
- "**" - any subdirectory
- "*" - any filename
= "?" - as long as a character follows a "?", this character is considered an ignorable character (e.g., "src/*.tsx?"则同时指代"src/*.tsx"与"src/*.ts"
)
- “files”: [“./file1.ts”, “./file2.d.ts”, …]
Use this option to list 编译器应始终包含在编译中的文件
. All files included with this option will be compiled regardless of whether the "exclude" option is used.
- “exclude”: [“node_modules”, “**//.test.ts”]
This option will be listed 从编译中排除的文件
. It takes the same pattern as the "include" option, we can use this option to filter the files specified with the "include" option. However, the "exclude" option does not affect the "files" option.
Typically, we exclude node_modules
, 测试文件
, and 编译输出目录
.
If this option is omitted, the compiler will use outDir
the folder specified by the " " option.
If both the "files" and "include" options are not specified, the compiler will compile all TS files in the root directory and any subdirectories, excluding files specified with the "exclude" option.
2-7 【TypeScript configuration】Dig deep into the TS compilation process
The video talks about how to change js project to ts project
3-1 Learning with questions
3-2 Chapter Overview
Typescipt + React
3-3 [Conceptual understanding] The past and present of React
React Features
one-way data flow
- Data and interface binding
- one-way rendering
- Just like a function with the same input and the same output
Virtual DOM
Componentization
3-4 [Componentization] First understanding of React functional components
Create a new project
npx create-react-app robot-gallert --template typescript
In the tsconfig.json file
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
There are the following two attributes in the tsx file to import the JSON file in order to be normal, otherwise an error will be reported
"moduleResolution": "node",
"resolveJsonModule": true,
3-5 [Conceptual understanding] JSX programming thinking
React believes that the essence of view is the internal unity of rendering logic and UI view performance
React couples HTML and rendering logic to form JSX
Use TSX file suffix
- File extension.tsx
tsconfig.json
Enable jsx option in configuration
{
"compilerOptions": {
"jsx": "react-jsx"
}
}
3-6 [Componentization] Configuring CSS modules for React
File location
CSS files and component files are placed in the same directory
Naming conventions
.module.css
React project introduces css in two ways
- Directly import the entire css file (prone to global style pollution)
import './index.css'
<div className="app" />
- JSS modular import components
import style from './index.css'
<div className={
style.app} />
Additional configuration is required
TS definition statement
- *.d.ts (.d.ts files will be automatically recognized by ts)
- Contains only type declarations without logic
- Will not be compiled nor packaged by webpack
Create a new custom.d.ts file under the src path
src/custom.d.ts
declare module "*.css" {
const css: {
[key: string]: string
};
export default css;
}
Only with the above files can it be used normally
import style from './index.css'
This way is js dynamic injection style
CSS in JS(JSS)
plug-intypescript-plugin-css-modules
Parse the css file to generate the reference type corresponding to ts
tsconfig.json configuration
{
"compilerOptions": {
"plugins": [
{
"name": "typescript-plugin-css-modules"
}
]
}
}
vscode configuration (introduce ts sdk)
.vscode/settings.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
After the configuration is complete, a smart prompt such as styles.app will appear after accessing styles
css file name suffix specification.module.css
// App.tsx
import React from 'react';
// import './App.css';
import robots from './mockdata/robots.json'
import Robot from './components/Robots';
import styles from './App.module.css'
console.log('styles:', styles);
function App() {
return (
<div className={
styles.app}>
<div className={
styles.robotList}>
{
robots.map(r => (
<Robot id={
r.id} name={
r.name} key={
r.id} email={
r.email}></Robot>
))
}
</div>
</div>
);
}
export default App;
styles is an object similar to the following
styles= {
App: "App_App__2UtqW",
App-header: "App_App-header__127PR",
App-link: "App_App-link__1y4cp",
App-logo: "App_App-logo__2zsEF",
App-logo-spin: "App_App-logo-spin__2uRb4",
app: "App_app__12zEe",
robotList: "App_robotList__3DmDk"
}
3-7 【Extended reading】CSS in JS (JSS)
What is JSS
To put it simply, in one sentence CSS in JS (JSS)
, it is "inline style" (inline style) and "inline script" (inline script).
Because, since the emergence of React, based on the requirements of componentization, it is mandatory to bundle HTML, CSS, and JavaScript together, and encapsulate the structure, style, and logic in the same file.
Although this violates the principle of "separation of concerns" in the early days of HTML invention, it is more conducive to the isolation between components. And each component contains all the code that needs to be used, does not need to depend on the external environment, and there is no coupling between components. Therefore, with the popularity of React and the popularity of the component model, the principle of "separation of concerns" has gradually faded out of people's vision, and the principle of "mixing of concerns" brought by React has gradually become the mainstream. [1]
React's encapsulation of CSS is very simple, that is, it follows the style attribute object of DOM. CSS-in-JS is a technique (technique), not a specific library implementation (library). 简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面
, instead of being independent files such as .css, .scss or less, so that you can use some language features belonging to JS such as module declaration, variable definition, function call and conditional judgment in CSS to provide flexible and reliable Extended style definitions.
It is worth mentioning that although CSS-in-JS is not a very new technology, its popularity in China does not seem to be very high. It first appeared because of some component-based Web frameworks (such as React, Vue and Angular) make developers also want to encapsulate the CSS style of the component into the component to solve a series of problems in native CSS writing. In addition, CSS-in-JS is the most popular in the React community. This is because React itself does not care about how users define styles for components, while Vue and Angular have their own set of definition styles that belong to the framework. plan. [2]
Benefits of JSS
-
- Local Styles - Scoping Styles
-
- Avoid useless CSS style accumulation
- 3 Critical CSS
-
- State-Based Style Definition
-
- A better packaged component library
Disadvantages of JSS
-
- steep learning curve
-
- runtime consumption
-
- poor code readability
-
- There is no unified industry standard
3-8 [Resource configuration] Load media and font files
Scaffolding automatically helps to declare different types of files
node_modules\react-scripts\lib\react-app.d.ts
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="react-dom" />
declare namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test';
readonly PUBLIC_URL: string;
}
}
declare module '*.avif' {
const src: string;
export default src;
}
declare module '*.bmp' {
const src: string;
export default src;
}
declare module '*.gif' {
const src: string;
export default src;
}
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.webp' {
const src: string;
export default src;
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<
SVGSVGElement
> & {
title?: string }>;
const src: string;
export default src;
}
declare module '*.module.css' {
const classes: {
readonly [key: string]: string };
export default classes;
}
declare module '*.module.scss' {
const classes: {
readonly [key: string]: string };
export default classes;
}
declare module '*.module.sass' {
const classes: {
readonly [key: string]: string };
export default classes;
}
3-10 [Extended reading] React's inline style and CSS
How to add CSS class to component?
render() {
return <span className="menu navigation-menu">Menu</span>
}
It's common for a CSS class to depend on a component's props or state:
render() {
let className = 'menu';
if (this.props.isActive) {
className += ' menu-active';
}
return <span className={
className}>Menu</span>
}
React 会自动添加 ”px” 后缀到内联样式为数字的属性后。
To use units other than "px", set the value to a string of numbers and the desired units. For example:
// Result style: '10px'
<div style={
{
height: 10 }}>
Hello World!
</div>
// Result style: '10%'
<div style={
{
height: '10%' }}>
Hello World!
</div>
But not all style properties are converted to pixel strings. Some style properties are unitless (eg zoom, order, flex).
From a performance perspective, CSS classes are usually better than inline styles.
3-11 [Conceptual understanding] State vs Props
State updates are asynchronous
- The state will not change immediately after calling setState, which is an asynchronous operation
- Do not rely on the current state to calculate the next state
props are read-only
3-12 [Event-driven] React Event event processing
event object
- target describes the element on which the event occurs
- currentTarget describes the element to which the event handler is bound
3-13 [Asynchronous processing] Get network API data
The interface data can be obtained at the following address
https://jsonplaceholder.typicode.com/users
interface Props {
}
interface State {
robotGallery: any[]
}
class App extends React.Component<Props, State> {
constructor(props) {
super(props)
this.state = {
robotGallery: []
}
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json()).then((data) => {
console.log('data:', data);
this.setState({
robotGallery: data
})
})
}
render(): React.ReactNode {
return (
<div className={
styles.app}>
<div>
<img src={
logo} className={
styles.appLogo} alt="" />
<h1>这里是标题这里是标题这里是标题</h1>
</div>
<div className={
styles.robotList}>
{
this.state.robotGallery.map(r => (
<Robot id={
r.id} name={
r.name} key={
r.id} email={
r.email}></Robot>
))
}
</div>
</div>
);
}
}
export default App;
3-14 [Asynchronous processing] Asynchronous development of setState
Asynchronous updates performed synchronously
setState() itself is not asynchronous, but the state processing mechanism gives people an asynchronous illusion. State processing generally occurs when the statement cycle changes.
this.setState({
count: this.state.count + 1})
// 此时this.state.count的值还是更新之前的值
console.log('this.state.count:', this.state.count);
<button onClick={
()=> {
this.setState((prevState, prevProps)=> {
console.log('prevProps:', prevProps)
console.log('prevState:', prevState)
return {
count: prevState.count + 1}
})
}}按钮
</button>
<span>{
this.state.count}</span>
<button onClick={
()=> {
this.setState({
count: this.state.count + 1}, ()=> {
// 更新state后的回调函数
console.log('this.state.count:', this.state.count);
})
}}>按钮</button>
<span>{
this.state.count}</span>
3-15 [Death and Rebirth] Exploring the life cycle of React components
- Mounting: Create virtual DOM to render UI
- Updating: Update the virtual DOM and re-render the UI
- Unmounting: remove virtual DOM remove UI
Initialization => Build function => getDerivedStateFromProps => render(): render UI => componentDidMount
getDerivedStateFromProps=>shouldComponentUpdate=>render: rendering UI=>update=>componentDidUpdate
componentWillUnmount => destroy
3-16 [Conceptual understanding] React 17 version changes
- The event delegation mechanism is changed (the old version adds a new one on the document and operates on the virtual DOM)
- Closer to the native browser (onScroll onFocus ...)
- delete event pool
- useEffect cleaning operation changed to asynchronous operation
- JSX cannot return undefined
- Delete some private APIs (mainly used in React Native)
4-1 Learning with questions
4-2 [Conceptual understanding] What are hooks?
A special class of functions to inject special functionality into your functional components
Some class components are lengthy and complex and difficult to reuse
The purpose of Hooks is to add state to functional components
4-3 [State Hook] Use useState to manage component state
4-4 [Concept understanding] side effects
pure function
Passing the same parameters to a function will always return the same data
Enter the same parameters (props) to the react component, and the rendered UI should always be the same
Side effects are the opposite of pure functions, which means that a function handles things that have nothing to do with the return value
4-5 [Side Effect Hook] Use useEffect to get data asynchronously
4-6 [Side Effect Hook] useEffect User Guide
Using async await in useEffect
useEffect(()=> {
const fetchData = async () => {
const res = await fetch("https://jsonplaceholder.typicode.com/users")
console.log({res});
const data = await res.json()
console.log({data});
}
fetchData()
})
4-7 [Global data transfer] Context and useContext
4-8 [Global Data Transfer] Component Context Provider
4-9 [High-level component HOC] withAddToCart()
HOC
const hoc = higherOrder(wrappedComponent)
- A high-level component (HOC) is a function that returns a component
- Add more functions to subcomponents through component nesting
- Takes a component as a parameter and returns a new, modified component
The naming convention
begins withAddToCard with
4-10 [Custom Hook] useAddToCart()
- Hooks are functions
- name starts with "use"
- Other Hook functions can be called internally
- Not a React feature
5-2 [Project Planning] Website Development and Design Guidelines
5-3 [Project Start] System Design and Project Initialization
Create a project using scaffolding
npx create-react-app react-travel --template typescript
Reuse the tsconfig.json vscode configuration and custom.d.ts of the test project
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": false,
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"plugins": [
{
"name": "typescript-plugin-css-modules"
}
]
},
"include": [
"src"
, "custom.d.ts" ]
}
custom.d.ts
declare module "*.css" {
const css: {
[key: string]: string
};
export default css;
}
setting.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
Install a css dependency only used in the development environment
npm install typescript-plugin-css-modules --save-dev
Change src/App.css to src/App.module.css according to the specification
modular reference css
src\App.tsx
import style from './App.modulce.css';
function App() {
return (
<div className={
style.App}>
<header className={
style["App-header"]}>
<img src={
logo} className={
style["App-logo"]} alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className={
style["App-link"]}
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
5-4 [Home Page Development] Header, Footer
Introduce ant Design UI framework
yarn add antd @ant-design/icons
//
cnpm install antd @ant-design/icons --save
5-5 [Project Refactoring] Componentization Thought and Practice
5-6 [Home page development] Multiple menus of carousel and sidebar
5-7 [Home Page Development] Recommended Popular Products
5-9 [Discussion Questions] Software Development Life Cycle
The correct way to start a project is always to start with the business, summarize the business requirements, establish a business model, determine the business process of the website through the business model, and finally start with the business process to determine the relationship and quantity of pages, and the last step of business analysis is UI Layout. Through the study of this chapter, let's discuss several issues:
- What's the first thing you need to do with a new website
- Could you please analyze the business needs of the course project?
- Please students supplement the BRD and SRS of the course project.
6-1 Learning with questions
6-2 [Concept Understanding] Routing and SPA
SPA (Single Page Website Application)
- JS CSS HTML is packaged into a super large file and thrown to the browser at one time
- JS hijacks browser routing to generate virtual routing to dynamically render page DOM elements
- In line with the trend of front-end and back-end separation, the server is not responsible for UI output but focuses on data support
- At the same time, it supports desktop App, mobile App and URL App
The routing system used by React websites is all virtual
- There is no one-to-one relationship with the back-end server and the actual file
- Home page http://localhost:3000
- Search page http://localhost:3000/search
- Tourist route details page localhost:3000/touristRoutes/{id}
React routing framework
- Comprehensive routing framework react-router
- Browser routing framework react-keeper
- Mobile app framework (react-native): react-navigation
This project uses react-router,
the most mainstream and complete React routing solution
6-3 [Routing initialization] Configure react-router
Install
version 5
cnpm install react-router-dom --save
ts support
The ts type definition will only be used during the development process and will not be used for compilation and online
cnpm install @types/react-router-dom --save-dev
react-router
- react-router-dom is used by the browser to process the routing of Web App
- react-router-native is used for React Native to handle the routing of mobile apps
- react-router-redux provides the integration of routing middleware processing redux
- react-router-config is used to statically configure routing
After installing react-router-dom
- The react-router core framework will be installed automatically
- Components can render labels
-
- Components use H5 Api to implement routing switching
- Components use window.location.hash in native JS to implement routing switching
The course uses "react-router-dom": "^5.2.0", and the latest version "react-router-dom": "^6.0.2", the
syntax is a bit different
Here it is better to install according to the version of the course so that learning will be smoother
“react-router-dom”: “^5.2.0”,
import React from 'react'
import styles from './App.module.css'
import {BrowserRouter, Route} from 'react-router-dom'
import {HomePage} from './pages'
function App() {
return (
<div className={styles.App}>
<BrowserRouter>
<Route path="/" component={HomePage}/>
</BrowserRouter>
</div>
)
}
export default App
“react-router-dom”: “^6.0.2”
Refer to the tutorial
https://github.com/remix-run/react-router/blob/main/docs/getting-started/tutorial.md
https://github.com/remix-run/react-router/blob/main/docs/getting-started/installation.md
import React from 'react'
import styles from './App.module.css'
import {BrowserRouter,Routes, Route} from 'react-router-dom'
import {HomePage} from './pages'
function App() {
return (
<div className={styles.App}>
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />}/>
</Routes>
</BrowserRouter>
</div>
)
}
export default App
6-4 [Routing Architecture] Basic Routing System
Website Routing System Requirements
- Routing navigation is consistent with native browser operation behavior
- The path analysis principle of routing is consistent with that of native browsers, which can automatically identify url paths
- Path switching is done in units of pages without page stacking
6-5 [routing construction] page navigation
routing parameters
6-6 [routing construction] withRouter and useRouter
Parameter passing between different routes
Passing data across components
- Use the context object context to achieve
- HOC Higher Order Components
- Functional components, using hooks
Chapter 7 [Introduction to Redux] Practical project architecture design
7-2 [Concept understanding] What is redux?
React is really just a Ui framework
- Generate dynamic dom rendering UI through JSX
- No Architecture No Templates No Design Patterns No Routing No Data Management
Design Patterns
- MVC MVVM MV*
- For React projects there is Redux
- Angular Observable(RxJS)
- Vue: Vuex
Redux
- Strip component data (state)
- The data is uniformly stored in the store
- Components subscribe to store to get data
- The store pushes data updates synchronously
Redux saves the data in a unified manner and is responsible for processing data binding while isolating the data and UI
When to use Redux
- When components need to share data
- When a state needs to be accessible from anywhere at any time
- When a component needs to change the state of another component
- Language switching Dark mode switching User login Global data sharing
Redux workflow
- React components (UI)
- Actions
- Store
- Reducer
7-3 【Create state】createStore
cnpm install redux --save
7-4 [Access state] Get store data
src/redux/store.ts
import {createStore} from 'redux'
import languageReducer from './languageReducer'
const store = createStore(languageReducer)
export default store;
src/redux/languageReducer.ts
export interface LanguageState {
language: "en" | "zh",
languageList: {
name: string,
code: string
}[];
}
const defaultState:LanguageState = {
language: 'zh',
languageList: [
{
name: '中文',code: 'zh'
},
{
name: 'English', code: 'en'
}
]
}
export default (state=defaultState, action) => {
return state
}
class component
src\components\header\Header.class.tsx
import store from '../../redux/store'
import {
LanguageState} from '../../redux/languageReducer'
interface State extends LanguageState {
}
class HeaderComponent extends React.Component<RouteComponentProps, LanguageState> {
constructor(props) {
super(props)
const storeState = store.getState()
this.state = {
language: storeState.language,
languageList: storeState.languageList
}
}
7-5 [Update state] Action and Reducer processing
7-6 [Subscription state] store connection and subscription
class component
import store from '../../redux/store'
import { LanguageState } from '../../redux/languageReducer'
interface State extends LanguageState { }
class HeaderComponent extends React.Component<RouteComponentProps, LanguageState> {
constructor(props) {
super(props)
const storeState = store.getState()
this.state = {
language: storeState.language,
languageList: storeState.languageList
}
store.subscribe(this.handleSubscribe)
}
handleSubscribe = ()=> {
const storeState = store.getState()
this.setState(
{
language: storeState.language,
languageList: storeState.languageList
}
)
}
menuClick = (e)=> {
if (e.key === "add_new") {
const action = {
type: 'add_language',
payload: {
name: '新语言', code: 'new'
},
}
store.dispatch(action)
} else {
const action = {
type: 'change_language',
payload: e.key
}
store.dispatch(action)
}
}
src\redux\languageReducer.ts
export interface LanguageState {
language: "en" | "zh",
languageList: {
name: string,
code: string
}[];
}
const defaultState:LanguageState = {
language: 'zh',
languageList: [
{
name: '中文',code: 'zh'
},
{
name: 'English', code: 'en'
}
]
}
export default (state=defaultState, action) => {
switch (action.type) {
case 'add_language':
return {
...state, languageList: [...state.languageList, action.payload]
}
case 'change_language':
return {...state, language: action.payload}
default:
return state
}
}
7-7 [i18n] complete website language switching
[i18n]
Internationalization There are 18 characters between the first and last characters in
Display the corresponding interface according to different languages and regions
principle
- The language pack is saved separately as a static resource xml json
- One file per language
- When switching language settings, the language file will also switch
I18n tools
- i18next: Currently the most mainstream framework
- react-i18next: React plugin for i18next
react-i18next official documentation
// installer dependencies
npm install react-i18next i18next --save
Both plugins support native TS
7-8 [redux refactoring] action splitting and unification
Action Creator (factory mode)
https://www.runoob.com/design-pattern/factory-pattern.html
7-9 [redux package] use react-redux in class components
React-redux
React Redux 7.1+ requires React 16.8.3 or later, in order to make use of React Hooks.
cnpm install react-redux --save
cnpm install @types/react-redux --save-dev
7-10 [redux package] use react-redux in functional building
7-11 [Discussion Question] In-depth analysis of redux
By using the redux architecture, we can strip the state in the component, that is, strip the component data, and manage all the data in a unified manner. Through the study of this chapter, let's discuss several issues:
- How to implement subscription and push of redux state?
- Please describe the workflow of redux?
- Please give an example to describe what the factory pattern is?
- What is the relationship between redux and react-redux?
Chapter 8 [Attack on Redux] Asynchronous AJAX and redux middleware
8-1 Learning with questions
8-2 [Concept understanding] RESTful
REST
REpresentational State Transfer
representative state transfer
Basic Features
-
no status
-
Oriented "resource"
paths will generally not have verbs
-
Verbs using HTTP
-
HATOAS Hypertext
As The En-gine Of Application State
Easy to use: facing objects (resources) such as adding, deleting, modifying and checking
Not easy to use: facing process such as login
8-3 [API Description] Where is the backend of the course?
Request header
x-icode: 12623592D652DDFC valid for 30 days
8-4 [API connection] AJAX asynchronously obtains recommendation data
Use Axios
- Easy to use API is close to Jquery and simpler than native fetch
- Compatible browsers can be compatible with IE7. If you use fetch, you have to handle the compatibility yourself.
- Good versatility, can use the same API in node and browser
cnpm install axios --save
8-5 [Conceptual understanding] Redux vs MVC
current design pattern
- mash up
- The Header navigation bar uses the redux architecture
- The content of the homepage is more inclined to the MVC architecture
What is MVC
- An architectural pattern is also an idea
- Model Model View View and Controller Controller
- Separate business operation UI display logic control
ViewView
- user interface
- Only display data without processing data
- JSX code for React project
Model Model
- The core of the MVC architecture
- Represents a business model or data model
- Business logic, such as algorithm implementation, data management, output object encapsulation, etc.
Controller Controller
- Accept user input and call models and views to complete user request processing
- do not process data
- React -> MVVM 或 MV*(whatever)
React projects do not advocate the use of MVC architecture
Data two-way binding can lead to an infinite loop
Redux Architecture
8-6 【reducer管理】combineReducers
This course realizes the transformation from MVC to Redux
8-7 [Middleware] Use redux-thunk middle price to realize asynchronous action
8-8 [Middleware] What is middleware
functional programming
conform to function code
const hello = function(x) {
return `Hello, ${
x}`
}
const happy = function(x) {
return `${
x}:)`
}
const compose = function (f, g) {
return function(x) {
return f(g(x))
}
}
const happyHello = compose(hello, happy)
happyHello('阿莱克斯') // 'Hello, 阿莱克斯:)'
Currying
const curriedAdd = (a) => {
return (b) => {
return a + b}
}
const addTen = curriedAdd(10)
addTen(12) // 22
Why do you need middleware
- The core of redux is to control and manage all data input and output
- So there is a store reducer and action dispatch
Assuming the following requirements
- We are required to record the action information of each dispatch
- Each dispatch has to record the data state of the current store
- Not only to print the current state but also to print the updated state
Solution: Encapsulate dispatch
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
console.log('当前state', store.getState())
next(action)
console.log('更新后的state', store.getState())
}
Future extension packages
const applyMiddleware = function (middleware) {
let next = store.dispatch;
// 这里传入store 因为中间件有可能会用到getState方法获取数据 比如打印store
store.dispatch = middleware(store)(next)
}
applyMiddleware(dispatcAndLog)
Redux middleware mechanism
- A total of one opportunity to classify and process actions
The following is the case without asynchronous operations
After adding middleware, you can do additional processing on the action
Asynchronous processing in Redux
- redux-thunk
- redux-promise
- redux-saga
The implementation principles of the three plug-ins are basically the same
Redux middleware announcement
const middleware = (store) => (next) => (action) => {
}
8-9 [Middleware] Custom middleware actionLog
8-10 [RESTful Advanced (Elective)] Richardson Maturity Model and HATOAS
Chinese translation of Martin's blog
9-2 Chapter Overview (redux-toolkit)
The author highly recommends redux-toolkit (RTK) to reduce template code
- RTK has become a very mainstream redux architecture pattern
- React official and redux official support
The default architecture of create-react-app is RTK
9-3 [Detail page construction 1] Page frame, details and date selection
9-4 [Detail page construction 2] Page frame, details and date selection
JSX handles html strings directly
<div dangerouslySetInnerHTML={
{__html: product.features}}
style={
{
margin: 50}}
>
</div>
9-5 [Concept understanding] What is redux-toolkit
9-6 【redux-toolkit】createSlice、reducer、与immer
cnpm install @reduxjs/toolkit
9-7 [Concept understanding] The theoretical basis of createAsyncThunk
redux-toolkit的createAsyncThunk
9-8 [redux-toolkit] sotre configuration (configureStore) and asynchronous processing (createAsyncThunk)
9-9 【Comprehensive use】Search page
10-2 [Layout Refactoring] Page Layout
10-3 [Registration page] Antd + ts form processing
10-4 [Registration page] Registration business logic processing
10-5 [Concept understanding] The importance of Status Code
HTTP status code
- The user can know whether the server has processed the request normally or if something went wrong
- A three-digit status code and a status message in string format
- Numeric codes are easier for programs to process and message strings are easier for programmers (humans) to understand
HTTP status codes are divided into 5 categories
Common HTTP Status Codes
10-6 [Login page] User login form and layout
10-7 【Concept understanding】JWT principle analysis
- JSON Web Token
- The role of JWT is user authorization (Authorization) rather than user authentication (Authentication)
Authorization VS Authentication
- User authentication refers to the use of username and password to verify the identity of the current user (error status code: 401 Unauthorized)
- User authorization means that the current user has sufficient permissions to access specific resources (error status code: 403 forbidden (forbidden)
Traditional Session login (stateful login)
- After the user logs in, the server will save the logged in session information
- Session ID will be passed to the front end through cookie
- HTTP requests will be accompanied by cookies
JWT changes the process of user authorization and authentication
- replace cookies
- JWT information only needs to be saved on the client
- stateless login
Stateful login (Session) VS stateless login (JWT)
stateful login
Stateless login (JWT)
If the JWT is valid, the server returns the resource
Session VS JWT
- Session needs to be saved on the server and the Session ID is saved in the front-end Cookie
- JWT information only needs to be saved on the client
- Advantages of stateless login: distributed deployment
10-8 [JWT example] JWT and single sign-on example explanation
Asymmetric encryption algorithm RSA private key in the server
Advantages of JWT
- Stateless, simple and convenient, perfectly supports distributed deployment
- Asymmetric encryption Token is highly secure
Disadvantages of JWT
- Once the stateless token is released, it cannot be canceled (no solution)
- The security of passing Token in clear text is low (it can be solved by using https)
10-9 【Login page】SignIn login business processing
10-10 [Login page] SignOut logout business processing
Decode JWT (jwt-decode plugin)
import jwt_decode, {
JwtPayload as DefaultJwtPayload } from 'jwt-decode'
interface JwtPayload extends DefaultJwtPayload {
username: string
}
useEffect(() => {
if (jwt) {
const token = jwt_decode<JwtPayload>(jwt)
console.log('jwt decode:', token)
setUserName(token.username)
}
}, [jwt])
10-11 [redux-persist] login persistence
cnpm install redux-persist --save
Cookie、session和web Storage
Stateless login: JWT
- You can only choose to use cookies or web storage to save
- The course uses web storage for data persistence
Benefits of Web Storage
- Effectively reduce network traffic
- Quickly display data
- temporary storage
Types of Web Storage
- SessionStorage: valid only until the current browser window is closed
- localStorage: always valid window or browser is closed and saved
const persistConfig = {
key: 'root',
storage,
whitelist: ['user'] // 白名单 只存白名单列表里的 黑名单 除了黑名单列表 其他都存
}
11-1 Learning with questions
11-2 [Advanced Routing] Build Private Routing
11-3 [UI Construction] Shopping Cart Page Initialization
11-4 [Redux Creation] Shopping Cart Slice
11-5 [redux connection] load shopping cart
11-6 [Complete the shopping module] Place an order in the shopping cart
11-7 [UI Construction] Online Payment Page Initialization
11-8 [Redux Creation] Order Slice
11-9 [redux connection] complete online payment
12-2 [Chapter Overview] Deployment Solution Introduction
deployment plan
- Option 1 uses a local server to host the website (node)
- Solution 2 Containerized Deployment
Course launch plan
- Containerization solution
- Use Alibaba Cloud to handle containerized services
Alibaba Cloud is online
- ECS instance
- Linux64
- docker repository
12-3 [Static deployment] local server hosting
Deployment – create-react-app-official website
Static Server
For environments using Node, the easiest way to handle this is to install serve and let it handle the rest:
npm install -g serve
serve -s build
PS: serve -s build
Before execution, you need to package with npm run build. The build folder generated after packaging is the root directory of the local server
serve -s build
Your static site will be served on port 3000. Like many of serve's internal settings, the port can be adjusted with the -l or --listen flag:
serve -s build -l 4000
Run this command for a full list of available options:
serve -h
12-4 [Concept understanding] 5 minutes to take you to know Docker
- Open source containerized virtual technology
- Portable (Developers can package their application dependencies and wait until a portable image package can be freely released to any window or linux or Mac machine)
- Very lightweight (the container itself uses a sandbox mechanism to separate the application from the host system and only share the kernel)
- out of hardware
- The docker container runs directly on the host kernel
Three core concepts of Docker
- Registry image warehouse: such as Docker Hub: https://hub.docker.com/node
- Image image: docker command to pull image docker pull node
- Container container: container start command docker run (docker run -it /bin/base)
Three relationship
Docker common commands
12-5 [Cheat Sheet] Commonly used docker commands
Course related Docker commands
docker installation and setup
#安装 CentOS已经将Docker软件包放在了Extras软件源中,直接利用即可
yum install docker-io -y
#查看docker的版本 version
docker -v
#开启Docker服务
systemctl start docker.service
#开机启动Docker服务
systemctl enable docker.service
#查看Docker服务启动状态
systemctl status docker.service
#重启Docker服务
systemctl restart docker.service
docker image files and container commands
#查看所有镜像
docker images
#删除一个imageid的镜像
docker rmi [IMAE_ID]
#删除所有镜像
sudo docker rmi $(docker images -q)
#查看所有容器运行状态
docker ps -a
docker container ls -all
#删除一个containerid的容器(实例)
docker rm 6f0c67de4b72
#删除所有容器
docker rm $(sudo docker ps -a -q)
容器日志
#查看指定时间后的日志,只显示最后100行:
docker logs -f -t --since="2019-06-08" --tail=100 CONTAINER_ID
#查看某时间之后的日志:
docker logs -t --since="2019-06-08" CONTAINER_ID
#查看某时间段日志:
docker logs -t --since="2019-06-08" --until "2019-06-09" CONTAINER_ID
#查看最近30分钟的日志:
docker logs --since 30m CONTAINER_ID
# 设置启动策略, docker 容器自动启动(在容器退出或断电开机后,docker可以通过在容器创建时的 --restart 来指定重启策略)
#--restart 参数:
# no,不自动重启容器. (默认值)
# on-failure, 容器发生error而退出(容器退出状态不为0)重启容器,可以指定重启的最大次数,如:on-failure:10
# unless-stopped, 在容器已经stop掉或Docker stoped/restarted的时候才重启容器,手动stop的不算
# always, 在容器已经stop掉或Docker stoped/restarted的时候才重启容器
docker run --restart always -it -p {本机端口}:{容器端口} {镜像名称}
#如果容器已经被创建,但处于停止状态,重新启动:
docker start {容器ID}
#如果容器已经被创建,我们想要修改容器的重启策略
docker update --restart always {容器ID}
12-6 [Environment Construction] Containerization Solution and Docker Configuration
12-7 【Cheat sheet】Dockerfile syntax
【Cheat sheet】Dockerfile syntax
Dockerfile syntax consists of two parts, comments and commands + parameters
simple example
#第一行必须指令基于的基础镜像
FROM ubutu
#维护者信息
MAINTAINER docker_user [email protected]
#镜像的操作指令
RUN apt-get update && apt-get install -y ngnix
RUN echo "\ndaemon off;">>/etc/ngnix/nignix.conf
#容器启动时执行指令
CMD /usr/sbin/ngnix
Dockerfile commands
- FROM
The base image can be any image. If the base image is not found, Docker will try to find the image from the Docker image index. The FROM command must be the first command in the Dockerfile. If the same DockerFile creates multiple images, multiple FROM instructions can be used (once for each image)
# Usage: FROM [image name]
FROM ubuntu
- MAINTAINER
Specifies the maintainer's information and should be placed after FROM.
# Usage: MAINTAINER [name]
MAINTAINER authors_name
- RUN
The RUN command is the core part of the Dockerfile to execute commands. It accepts commands as arguments and is used to create images. Unlike the CMD command, the RUN command is used to create a mirror (form a new layer on top of a previously committed layer).
The format is Run or Run ["executable", "Param1", "param2"],
the former runs on the shell terminal, that is, /bin/sh -C, and the latter uses exec to run. For example: RUN ["/bin/bash", "-c", "echo hello"]
Each run command is executed on the current base image, and a new image is submitted. When the command is relatively long, you can use "/" to break the line.
# Usage: RUN [command]
RUN apt-get update
- USER
The format is USER daemon.
Specify the user name or UID when running the container, and subsequent RUN will also use the specified user.
When the service does not require administrator privileges, this command can be used to specify the running user. And you can create the required users before, for example: RUN groupadd -r postgres && useradd -r -g postgres postgres . To gain administrator privileges temporarily, use gosu instead of sudo.
# Usage: USER [UID]
USER 751
- VOLUME
The VOLUME command is used to allow your container to access directories on the host machine.
The format is VOLUME["/data"].
Create a mount point that can be mounted from the local host or other containers, generally used to store databases and data that needs to be kept.
# Usage: VOLUME ["/dir_1", "/dir_2" ..]
VOLUME ["/my_files", "/app_files"]
- WORKDIR
The WORKDIR command is used to set the running directory of the command specified by CMD.
The format is WORKDIR /path/to/workdir .
Configure the working directory for subsequent RUN , CMD , ENTRYPOINT commands.
Multiple WORKDIR directives can be used, and subsequent commands, if the parameter is a relative path, will be based on the path specified by the previous command. For example:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# 最终路径为 /a/b/c 。
- CMD
Three formats are supported:
CMD ["executable", "Param1", "param2"] is executed with exec, CMD command param1 param2 is recommended, and CMD ["Param1", "param2"] is provided to ENTRYPOINT for execution
on /bin/sh
Default parameters.
Each container can only execute one CMD command. When there are multiple CMD commands, only the last one is executed.
# Usage 1: CMD application "argument", "argument", ..
CMD "echo" "Hello docker!"
- ENV
The format is ENV. Specify an environment variable that will be used by subsequent RUN instructions and persisted while the container is running.
ENV TZ "Asia/Shanghai"
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
- ADD
The ADD command takes two parameters, source and destination. Its basic role is to copy files from the file system of the source system to the file system of the target container. If the source is a URL, the content of that URL will be downloaded and copied into the container. If the file is in a recognized compressed format, docker will help decompress it.
# Usage: ADD [source directory or URL] [destination directory]
ADD /my_app_folder /my_app_folder
- COPY (almost indistinguishable from ADD)
COPY copies files from path < src to path inside the container.
COPY <src> <dest>
- EXPOSE
Specify the port specified when docker allows it to be forwarded
EXPOSE <port>[<port>...]
- ENTRYPOINT
Two formats:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中执行)
Configure the command to be executed after the container is started, and cannot be overridden by the parameters provided by docker run.
There can only be one ENTRYPOINT in each Dockerfile. When multiple ENTRYPOINTs are specified, only the last one will take effect.
- ONBUILD
The command specified by ONBUILD is not executed when the image is built, but is executed in its sub-image
source:
https://juejin.cn/post/6844903889301422088
https://github.com/qianlei90/Blog/issues/35
https://www.jianshu.com/p/690844302df5
https://www.jianshu.com/p/5f4b1ade9dfc
12-8 [Container transformation] Understand the whole process of Dockerfile
previous lesson
- Created a doker virtual machine and installed nginx hosting server
- It is also possible to build a Docker image of custom content
- You can directly download the official Nginx Docker image
Two ways to build a Docker image
- docker commit
- docker build + Dockerfile (reproducible standardization)
Dockerfile
files in the root directory
Dockerfile is the script used to build the docker image
# 第一个阶段: 拉取node镜像来打包React项目
## 拉取node镜像 版本14 命名为build
FROM node:14 as build
## 设置docker命令运行目录
WORKDIR /app
## 复制对应文件到app文件夹中 app/
COPY package*.json ./
## 安装项目依赖
RUN npm install
## 复制对应文件到app文件夹中 app/
COPY tsconfig.json ./
## 复制public文件夹并创建public文件夹
COPY public public/
## 复制src文件夹并创建src文件夹
COPY src src/
## 构建react项目
RUN npm run build
# 第二个阶段: 创建并运行Ngnix服务器,并且把打包好的文件复制粘贴到服务器文件夹中
## 拉取nginx服务器镜像 :执行版本
FROM nginx:alpine
## 将第一阶段通过npm run build构建好的react项目复制到nginx服务器镜像中
COPY --from=build /app/build/ /usr/share/nginx/html
## 暴露nginx服务器端口
EXPOSE 80
## 使用CMD命令来启动nginx命令
CMD ["nginx", "-g", "daemon off;"]
Build the image and execute the command in the root directory of the react project
docker build -t react-web .
Docer will execute step by step according to the Dockerfile
After the image is built, you can start deploying
Use the following command to check whether the mirror exists
docker images
Containerized react-web image
12231 is the local port is not limited 80 is the port exposed by the nginx server react-web mirror
docker run -d -p 12231:80 react-web
The following command checks the list of containers to verify successful deployment
docker ps
At this time, you can visit localhost:12231 normally.
12-9 【Containerized Online】Realize Alibaba Cloud Deployment
Each lesson is submitted to Code Cloud separately. If you want to see the code content of a specific section, you can find the corresponding submission record on Code Cloud.
查看代码改动
Code cloud warehouse address :
https://gitee.com/WebJianHong/react-travel
recommended reading
Vue source code learning directory
Vue source code learning complete directory
Connect the dots - the road to front-end growth
Connect the dots - the road to front-end growth
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强