Comience con la contenedorización front-end en 30 minutos

1. Introducción

La contenedorización front-end es una tecnología que empaqueta aplicaciones front-end en contenedores para que puedan implementarse y ejecutarse de manera rápida y eficiente en diferentes entornos.

2. Fondo

La tendencia a separar el front-end y el back-end ha tomado forma. La complejidad de la ingeniería del front-end está aumentando. Habrá diferencias en los entornos y las versiones de Node.js en las que se basan las implementaciones de proyectos nuevos y antiguos. y los archivos de recursos estáticos en el entorno de producción dependen del acceso al servicio de implementación del entorno, la ingeniería front-end no pudo formar una implementación de "artefacto único" y la aparición de contenedores simplificó enormemente el proceso de implementación.

La contenedorización front-end puede administrar fácilmente la inyección de variables del entorno front-end y el entorno de ejecución (diferentes proyectos dependen de diferentes entornos de nodos, la compatibilidad de las versiones de los nodos es un gran problema), ahorra costos de servidor, una reversión de versiones más rápida y conveniente y una implementación de múltiples arquitecturas. .Implementación integrada automatizada de CI/CD, DevOps, etc., los beneficios son más de los que puedas imaginar (risas manuales aquí).

Este artículo se basa en el proyecto React combinado con Docker para compartir los cambios provocados por la introducción de la tecnología de contenedores en el front-end.

3. Aplicación de la contenedorización en github.

Github ha lanzado github-action para realizar ci/cd en contenedores. A continuación mostraré un ejemplo del uso de github-action para realizar una entrega automatizada de paquetes npm:

  • Cree un nuevo archivo .github/workflows/ci.yml en el directorio raíz del proyecto
  • Vaya al sitio web oficial de npm para solicitar un token (específicamente cómo solicitarlo, búsquelo y resuélvalo usted mismo)
  • Pegue este código en el archivo ci.yml
  • ¡Envíe el código a la rama maestra y automáticamente usará ci/cd para la implementación!
name: CI
on:
  push:
    branches:
      - master
jobs:
  build:
    # 指定操作系统
    runs-on: ubuntu-latest
    steps:
      # 将代码拉到虚拟机
      - name: Checkout repository
        uses: actions/checkout@v2
      # 指定node版本
      - name: Use Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16.x'
          registry-url: 'https://registry.npmjs.org'
      # 依赖缓存策略
      - name: Cache
        id: cache-dependencies
        uses: actions/cache@v3
        with:
          path: |
            **/node_modules
          key: ${
    
    {runner.OS}}-${
    
    {hashFiles('**/pnpm-lock.yaml')}}
      - name: Install pnpm
        run: npm install -g [email protected]
      # 依赖下载
      - name: Installing Dependencies
        if: steps.cache-dependencies.outputs.cache-hit != 'true'
        run: pnpm install
      # 打包
      - name: Running Build
        run: pnpm run build
      # 测试
      - name: Running Test
        run: pnpm run test-unit
      # 发布
      - name: Running Publish
        run: npm publish
        env:
          # NPM_TOKEN is access token
         NODE_AUTH_TOKEN: ${
    
    { secrets.NPM_TOKEN }}

4. Cree una imagen de front-end basada en Docker

Antes de aprender cómo construir el proyecto front-end ci/cd, primero aprendamos cómo construir la imagen front-end.

4.1 Instalar la ventana acoplable

Haga clic aquí para volar e instalar Docker.
Una vez completada la instalación, ejecute el siguiente comando para verificar la versión de Docker. Intente traer la versión buildx.

docker -v
Docker version 24.0.2, build cb74dfc

4.2 Escribir un archivo Docker

Aquí primero necesitamos popularizar el conocimiento de ingeniería front-end. Todos sabemos que un proyecto basado en npm requiere un archivo package.json, y luego ejecutar npm run install para descargar el paquete y npm run build para empaquetarlo. El archivo empaquetado no puede ejecutar directamente. Inicie un servicio de nodo para ejecutar, por lo que escribiremos la imagen más básica basada en nodo y nginx. El ejemplo es el siguiente

Agregue un archivo de configuración de nginx en el directorio raíz del proyecto, llamado nginx.conf, con el siguiente contenido

worker_processes  1;
 
events {
    
      
    worker_connections  1024;  
} 
http {
    
      
    sendfile         on;  
    tcp_nodelay       on;  
    keepalive_timeout  30; 
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    server {
    
    
        listen 80;
        server_name localhost;
        root /usr/share/nginx/front/dist;
        autoindex on;   
        autoindex_exact_size off;   
        autoindex_localtime on;
        location / {
    
    
            try_files $uri $uri/ =404;
            index index.html index.htm;
            gzip_static on;
            expires max;
            add_header Cache-Control public;
            if ($request_filename ~* ^.*?\.(eot)|(ttf)|(woff)|(svg)|(otf)$) {
    
    
                add_header Access-Control-Allow-Origin *;
            }
        }
    }
}

Agregue un archivo de configuración de Docker en el directorio raíz del proyecto, llamado Dockerfile, con el siguiente contenido

FROM node:17-buster as builder

WORKDIR /src
COPY ./ /src

RUN npm install -g pnpm \
    && pnpm install \
    && pnpm build

FROM nginx:alpine-slim

RUN mkdir /usr/share/nginx/front \
    && mkdir /usr/share/nginx/front/dist \
    && rm -rf /etc/nginx/nginx.conf
 
COPY --from=builder /src/nginx.conf /etc/nginx/nginx.conf

COPY --from=builder /src/dist /usr/share/nginx/front/dist

EXPOSE 80

A continuación, use Docker Build para empaquetar la imagen (si tiene una herramienta de escritorio, puede verla en la columna de imágenes de la herramienta de escritorio Docker después de que el empaquetado sea exitoso) y Docker Run para ejecutar la imagen (si tiene una herramienta de escritorio). herramienta, puede verlo en la columna de contenedores de la herramienta de escritorio de Docker después de que la ejecución sea exitosa), después de que la ejecución de Docker se haya ejecutado exitosamente, puede abrir el navegador e ingresar: http://localhost para ver

docker buildx build -t webapp-demo:v1 .

docker run -d -p 80:80 webapp-demo:v1

4.3 Cómo realizar el almacenamiento en caché pnpm basado en Dockerfile

Aquí cito un pasaje:
Al usar la compilación de varias etapas, la imagen creada solo contiene la carpeta de destino dist, pero todavía hay algunos problemas. Cuando el archivo package.json cambia, RUN npm i && rm -rf ~/.npm La capa Se volverá a ejecutar y, después de múltiples cambios, se generará una gran cantidad de imágenes de capa intermedia.

Para resolver este problema, podemos imaginar una función similar a un volumen de datos y montar la carpeta node_modules al crear la imagen. Una vez completada la construcción, la carpeta node_modules se desinstalará automáticamente. La imagen real no contiene node_modules. Esto La carpeta nos ahorra el tiempo de obtener dependencias cada vez, aumenta en gran medida la eficiencia de la construcción de imágenes y también evita generar una gran cantidad de imágenes intermedias.

El representante de la clase aquí resume: Es para minimizar la posibilidad de imágenes de capa intermedia y minimizar el tamaño de la imagen acoplable y el tiempo de construcción.

Como estoy usando pnpm para la administración de paquetes npm, revisé la documentación oficial de pnpm sobre esta optimización de la siguiente manera:

FROM node:20-slim AS base

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

COPY . /app
WORKDIR /app

FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile

FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build

FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
EXPOSE 8000
CMD [ "pnpm", "start" ]

Entonces, con el espíritu de copiar la calabaza y usar la configuración de producción de nginx, encontré la imagen de empaquetado de nginx escrita por mi colega. También puede ejecutar Docker Build y Docker Run para verificar, y luego mi código modificado es el siguiente:

FROM node:17-buster AS builder

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

WORKDIR /src
COPY ./ /src

RUN --mount=type=cache,target=/src/node_modules,id=myapp_pnpm_module,sharing=locked \
    --mount=type=cache,target=/pnpm/store,id=pnpm_cache \
        pnpm install

RUN --mount=type=cache,target=/src/node_modules,id=myapp_pnpm_module,sharing=locked \
        pnpm run build

FROM ghcr.io/zboyco/webrunner:0.0.7

COPY --from=builder /src/dist /app

4.4 Cómo usar buildx para crear imágenes de múltiples arquitecturas

La herramienta Docker Buildx, para decirlo sin rodeos, le proporciona la capacidad. Cuando su host tiene una arquitectura x86 64 y desea crear una imagen con una arquitectura ARM64, necesita esta herramienta. Se siente un poco como una compilación cruzada. , como: La compilación cruzada de go build, la compilación de programas ejecutables en win10, se puede utilizar en plataformas Linux específicas

Básicamente, Buildx llama a la API del kit de compilación y la compilación se realiza en el entorno del kit de compilación. Si se admiten múltiples arquitecturas depende del entorno del kit de compilación. Si necesita que el kit de compilación admita múltiples arquitecturas, debe ejecutarlo en la máquina host (por supuesto, esto no es necesario, se controla de acuerdo con los requisitos de compilación). La versión de escritorio no necesita establecer esta configuración):

docker run --privileged --rm tonistiigi/binfmt --install all

Aquí modificamos el código de Dockerfile anterior para admitir múltiples arquitecturas. Dado que la plataforma es experimental, primero debemos ejecutar docker pull docker/dockerfile para extraer la imagen.

# syntax = docker/dockerfile:experimental
# --platform, 会让 builder 只会有一份,且 arch 与宿主机一致
FROM --platform=${BUILDPLATFORM:-linux/amd64} node:17-buster AS builder

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

WORKDIR /src
COPY ./ /src

RUN --mount=type=cache,target=/src/node_modules,id=myapp_pnpm_module,sharing=locked \
    --mount=type=cache,target=/pnpm/store,id=pnpm_cache \
        pnpm install

RUN --mount=type=cache,target=/src/node_modules,id=myapp_pnpm_module,sharing=locked \
        pnpm run build

FROM ghcr.io/zboyco/webrunner:0.0.7

COPY --from=builder /src/dist /app

Antes de ejecutar el comando de imagen del paquete, primero verificamos la instancia del generador predeterminado de nuestra máquina.

docker buildx ls

NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT                              PLATFORMS
default         docker
  default       default         running v0.11.7-0.20230525183624-798ad6b0ce9f linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
desktop-linux * docker
  desktop-linux desktop-linux   running v0.11.7-0.20230525183624-798ad6b0ce9f linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

El uso de buildx para ejecutar el script anterior para empaquetar la imagen informará el siguiente error:

docker buildx build --platform linux/arm,linux/arm64,linux/amd64 -t webapp-official-website:v1 .

ERROR: Multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")

Dado que la instancia del generador predeterminada de Docker no admite la especificación de múltiples plataformas al mismo tiempo, primero debemos crear una nueva instancia del generador. Al mismo tiempo, debido a que extraer imágenes en China es lento, podemos usar la imagen dockerpracticesig/buildkit:master configurada con la dirección de aceleración de la imagen para reemplazar la imagen oficial.

Si tiene un acelerador de imágenes privado, puede crear su propia imagen de kit de compilación basada en https://github.com/docker-practice/buildx y utilizarla.

# 适用于国内环境
$ docker buildx create --use --name=mybuilder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master

# 适用于腾讯云环境(腾讯云主机、coding.net 持续集成)
$ docker buildx create --use --name=mybuilder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master-tencent

# $ docker buildx create --name mybuilder --driver docker-container

$ docker buildx use mybuilder

Elegimos el comando adecuado para el entorno doméstico para crear la solución, puedes ver que hay más instancias llamadas mybuilder-cn.

docker buildx create --use --name=mybuilder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master

docker buildx ls
NAME/NODE       DRIVER/ENDPOINT  STATUS   BUILDKIT                              PLATFORMS
mybuilder-cn *  docker-container
  mybuilder-cn0 desktop-linux    inactive
default         docker
  default       default          running  v0.11.7-0.20230525183624-798ad6b0ce9f linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux    running  v0.11.7-0.20230525183624-798ad6b0ce9f linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

$ docker buildx build --platform linux/arm,linux/arm64,linux/amd64 -t myusername/hello . --push

# 查看镜像信息
$ docker buildx imagetools inspect myusername/hello

Ejecute la imagen en diferentes arquitecturas para obtener información sobre la arquitectura.

$ docker run -it --rm myusername/hello

5. Cómo utilizar la contenedorización para la inyección de variables de entorno front-end

  • Aunque la interfaz no requiere muchas variables de entorno, se necesitan la API básica baseURL, appName y env.
  • Si se trata de un escenario de micro front-end, entonces las URL requeridas de otros sitios web son variables de entorno, y hay muchas.
  • Recuerdo vagamente que cuando entré por primera vez a la industria, el front-end distinguía el entorno de prueba y el entorno en línea se juzgaba directamente por el nombre de dominio, por ejemplo: inlcudes (url, ".com")?, y luego obtuve isProd para obtener las variables de diferentes ambientes configurados en el proyecto, las cuales me parecieron Muy bajas
  • Los marcos como vue y reaccionar aparecieron más tarde. Puede especificar –prod cuando npm ejecuta dev y luego obtener isProd a través del proceso para obtener la configuración correspondiente.
  • Ahora puede inyectar variables de entorno directamente a través de la contenedorización y luego usar nginx para inyectar las variables de entorno en el contenedor en el contenido de la metaetiqueta del html del proyecto front-end y luego obtener las variables de la metaetiqueta.
  • Si es un proyecto monorepo, cuando npm ejecuta la compilación, Dockerfile también necesita usar las variables de entorno en el contenedor para obtener qué proyecto empaquetar.
  • El entorno de prueba configura las variables de entorno a través de archivos ts y luego combina la información de estas variables de entorno cuando el proyecto comienza a generar la configuración default.yml. Cuando ci / cd, k8s escribe automáticamente las variables de entorno configuradas en default.yml en el contenedor.
  • El entorno en línea proporciona directamente una página de interfaz de usuario para configurar las variables de entorno y luego llama a la API, y la API de back-end escribe las variables en el contenedor a través de k8s.
  • Cómo leer las variables de entorno configuradas a través de k8s y escribirlas en el contenedor y escuchar la descomposición la próxima vez

A continuación se muestra un código de muestra de Dockerfile en un escenario de producción (¡la compañía probablemente no me matará!) Aquí omitimos cómo k8s inyecta variables de entorno en el contenedor y solo considera cómo leer las variables de entorno del contenedor (suponiendo que el entorno Se han inyectado variables en el contenedor))

FROM --platform=${BUILDPLATFORM} hub-dev.rockontrol.com/rk-infrav2/docker.io/library/node:17-bullseye as builder

WORKDIR /src
COPY ./ ./

ARG APP
ARG ENV

ARG PROJECT_GROUP
ARG PROJECT_NAME
ARG PROJECT_VERSION

ARG YARN_NPM_REGISTRY_SERVER

RUN npm install -g --registry=${YARN_NPM_REGISTRY_SERVER} pnpm
RUN pnpm --registry=${YARN_NPM_REGISTRY_SERVER} install


RUN PROJECT_GROUP=${PROJECT_GROUP} PROJECT_VERSION=${PROJECT_VERSION} \
    npx devkit build --prod ${APP} ${ENV}

FROM hub-dev.rockontrol.com/rk-infrav2/ghcr.io/zboyco/webrunner:0.0.7

ARG PROJECT_NAME
COPY --from=builder /src/public/${PROJECT_NAME} /app

A continuación se muestra un fragmento de código que muestra cómo nginx combina variables de entorno y usa la configuración de nginx para escribirlas en la etiqueta mate de HTML.

#!/bin/sh

# This script is used to start the application

# 初始化一个字符串,用于存储拼接后的值
app_config="${APP_CONFIG}"
ext_config=""

# 遍历所有环境变量
for var in $(env | cut -d= -f1); do
    # 检查变量是否以 "APP_CONFIG__" 开头
    if [ "$(echo "$var" | grep '^APP_CONFIG__')" ]; then
        # 去除变量名前缀 "APP_CONFIG__"
        trimmed_var=$(echo "$var" | sed 's/^APP_CONFIG__//')
        # 使用 eval 来获取变量值并拼接到字符串中
        value=$(eval echo "\$$var")
        app_config="${app_config},${trimmed_var}=${value}"
    fi
done

# 去掉起始的逗号
export app_config=$(echo "$app_config" | sed 's/^,//')

# 解析app_config变量
# 以,分割 app_config
IFS=","
set -- $app_config
# 遍历数组
for config in "$@"; do
    # 以等号分剥数组
    IFS="="
    set -- $config
    # 将单个环境变量单独注入
    ext_config="${ext_config}        sub_filter '__$1__' '$2';\n"
    echo "$1: $2"
done

# Install envsubst
echo "Installing envsubst"
# 将扩展变量替换到 conf.template 中
sed "s@__EXTENT_CONFIG__@${ext_config}@g" /etc/nginx/conf.d/conf-base.template > /etc/nginx/conf.d/conf.template 

envsubst '${PROJECT_VERSION} ${ENV} ${app_config}' < /etc/nginx/conf.d/conf.template > /etc/nginx/conf.d/default.conf

# Start nginx
echo "Starting nginx"
nginx -g 'daemon off;'

Código de configuración de nginx, el marcador de posición de la etiqueta mate se reemplazará con la variable de entorno real, consulte sub_filter en el código

server {
    
    
    listen 80;
    listen  [::]:80;
    server_name  localhost;
    root /app;

    #开启gzip
    gzip on;  
    #低于1kb的资源不压缩 
    gzip_min_length 1k;
    #压缩级别1-9,越大压缩率越高,同时消耗cpu资源也越多,建议设置在5左右。 
    gzip_comp_level 6; 
    #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片.
    gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;

    location ~ ^/(static|__built__)/ {
    
    
        root /app;
        expires max;
        proxy_cache static_memory_cache;  # 使用内存缓存
        proxy_cache_valid 200 1d;
        proxy_cache_lock on;
    }

    location / {
    
    
        expires -1;
        try_files $uri /index.html;

        add_header X-Frame-Options sameorigin;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1;mode=block" always;

        sub_filter '__PROJECT_VERSION__' '$PROJECT_VERSION';
        sub_filter '__ENV__' '$ENV';
        sub_filter '__APP_CONFIG__' '$app_config';

        # 需要将以下字符串替换为注入的扩展环境变量
__EXTENT_CONFIG__

        sub_filter_once on;
    }
}

A continuación se muestra una sección sobre cómo el front-end lee las variables de entorno de las metaetiquetas html.

import appConfig from "../../config";

interface IConfig {
    
    
  appName: string;
  baseURL: string;
  version?: string;
  env?: string;
}

export function getConfig(): IConfig {
    
    
  const defaultAppConfig = {
    
    
    appName: "",
    version: "",
    env: "",
    baseURL: "",
  };
  console.log("metaEnv", import.meta.env);

  if (import.meta.env.DEV) {
    
    
    return appConfig;
  } else {
    
    
    const appConfigStr = getMeta("app_config");

    if (!appConfigStr) return defaultAppConfig;

    return parseEnvVar(appConfigStr);
  }
}

function getMeta(metaName: string) {
    
    
  const metas = document.getElementsByTagName("meta");

  for (let i = 0; i < metas.length; i++) {
    
    
    if (metas[i].getAttribute("name") === metaName) {
    
    
      return metas[i].getAttribute("content");
    }
  }

  return "";
}

function parseEnvVar(envVarURL: string) {
    
    
  const arrs = envVarURL.split(",");

  return arrs.reduce((pre, item) => {
    
    
    const keyValues = item.split("=");

    return {
    
    
      ...pre,
      [keyValues[0]]: keyValues[1],
    };
  }, {
    
    } as IConfig);
}

const BASE_URL = getConfig().baseURL;

const instance = axios.create({
    
    
  baseURL: BASE_URL,
  headers: {
    
    
    "Content-Type": "application/json",
  },
  timeout: 60000, // 超时时间60秒
});

Finalmente, se publicó el Dockerfile, ¡así que publiquemos el código fuente del archivo ci en un escenario real! ! !

stages:
  - ship
  - deploy

ship:
  stage: ship
  image: hub-dev.rockontrol.com/rk-infrav2/gitlab-runner-buildx:0.0.0-b0450fe
  # variables:
  #   MULTI_ARCH_BUILDER: 1
  before_script:
    - echo "${DOCKER_PASSWORD}" | docker login "${DOCKER_REGISTRY}" -u="${DOCKER_USERNAME}" --password-stdin
    - BUILDKIT_NAME=node-buildkit hx buildx ci-setup
  script:
    - export PLATFORM=linux/amd64,linux/arm64
    - |
      if [[ -f ./.platform ]]; then
        source ./.platform
      else
        echo "WARNING, there is no .platform in project, USE default PLATFORM=${PLATFORM} "
      fi
    - hx buildx --with-builder --push --platform=${PLATFORM}
  tags:
    - webapp

deploy:
  stage: deploy
  script:
    - hx config
    - hx deploy
  dependencies:
    - ship
  tags:
    - webapp

6. Implementación de aplicaciones front-end en Kubernetes

Kubernetes es una plataforma de orquestación de contenedores de código abierto que puede automatizar la implementación, el escalado y la gestión de aplicaciones en contenedores. Estos son los pasos para implementar una aplicación front-end en un clúster de Kubernetes:

6.1 Crear implementación

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend-app
  template:
    metadata:
      labels:
        app: frontend-app
    spec:
      containers:
        - name: frontend-app
          image: my-frontend-app:latest
          ports:
            - containerPort: 3000

6.2 Crear servicio

apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    app: frontend-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

6.3 Implementar en el clúster de Kubernetes

Utilice el comando kubectl para implementar la aplicación en el clúster de Kubernetes:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Ahora, su aplicación de front-end se ejecuta en el clúster de Kubernetes y se puede acceder a ella externamente a través del servicio tipo LoadBalancer.

7. Acerca de la arquitectura del proyecto front-end React

7.1 Tecnología central

7.2 Obtener automáticamente la función de solicitud de API basada en openapi

// src/core/openapi/index.ts

// 示例代码
generateService({
    
    
  // openapi地址
  schemaPath: `${
     
     appConfig.baseURL}/${
     
     urlPath}`,
  // 文件生成目录
  serversPath: "./src",
  // 自定义网络请求函数路径
  requestImportStatement: `/// <reference types="./typings.d.ts" />\nimport request from "@request"`,
  // 代码组织命名空间, 例如:Api
  namespace: "Api",
});

7.3 Interfaz de llamada (react-query), admite carga automática y enlace de solicitud de interfaz

// HelloGet是一个基于axios的promise请求
export async function HelloGet(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: Api.HelloGetParams,
  options?: {
    
     [key: string]: any },
) {
    
    
  return request<Api.HelloResp>('/gin-demo-server/api/v1/hello', {
    
    
    method: 'GET',
    params: {
    
    
      ...params,
    },
    ...(options || {
    
    }),
  });
}

// 自动调用接口获取数据
const {
    
     data, isLoading } = useQuery({
    
    
  queryKey: ["hello", name],
  queryFn: () => {
    
    
    return HelloGet({
    
     name: name });
  },
});

export async function HelloPost(body: Api.HelloPostParam, options?: {
    
     [key: string]: any }) {
    
    
  return request<Api.HelloResp>('/gin-demo-server/api/v1/hello', {
    
    
    method: 'POST',
    headers: {
    
    
      'Content-Type': 'application/json',
    },
    data: body,
    ...(options || {
    
    }),
  });
}

// 提交编辑数据
const {
    
     mutate, isLoading } = useMutation({
    
    
  mutationFn: HelloPost,
  onSuccess(data) {
    
    
    setName(data?.data || "");
  },
  onError() {
    
    
    // 清除queryKey为hello的接口数据缓存,自动重新获取接口数据
    queryClient.invalidateQueries({
    
     queryKey: ['hello'] });
  }
})

mutate({
    
     name: "lisi" });

8. CLI del código React de front-end

9. Conclusión

  • Se introdujo la configuración básica de gitlab-action en el campo npm del front-end.
  • Presenta la escritura de archivos Dockerfile de front-end, así como el plan de optimización de pnpm en Docker y cómo usar buildx para generar imágenes de múltiples arquitecturas de front-end.
  • Introduce el uso de variables de entorno front-end en escenarios de producción.
  • Presentamos el plan de arquitectura técnica del proyecto front-end React

Supongo que te gusta

Origin blog.csdn.net/luo1055120207/article/details/132742642
Recomendado
Clasificación