前端容器化实践( 四 )

下面贴一段前端如何从html meta标签中读取环境变量
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秒});最后的最后,都贴了Dockerfile了,那就一不做二不休,贴个真实场景下的ci文件源码吧!!!
stages:- ship- deployship:stage: shipimage: hub-dev.rockontrol.com/rk-infrav2/gitlab-runner-buildx:0.0.0-b0450fe# variables:#MULTI_ARCH_BUILDER: 1before_script:- echo "${DOCKER_PASSword}" | docker login "${DOCKER_REGISTRY}" -u="${DOCKER_USERNAME}" --password-stdin- BUILDKIT_NAME=node-buildkit hx buildx ci-setupscript:- export PLATFORM=linux/amd64,linux/arm64- |if [[ -f ./.platform ]]; thensource ./.platformelseecho "WARNING, there is no .platform in project, USE default PLATFORM=${PLATFORM} "fi- hx buildx --with-builder --push --platform=${PLATFORM}tags:- webappdeploy:stage: deployscript:- hx config- hx deploydependencies:- shiptags:- webapp6.前端应用的Kubernetes部署Kubernetes是一个开源的容器编排平台,可以实现自动化部署、扩展和管理容器化应用程序 。以下是将前端应用部署到Kubernetes集群的步骤:
6.1 创建DeploymentapiVersion: apps/v1kind: Deploymentmetadata:name: frontend-appspec:replicas: 3selector:matchLabels:app: frontend-apptemplate:metadata:labels:app: frontend-appspec:containers:- name: frontend-appimage: my-frontend-app:latestports:- containerPort: 30006.2 创建ServiceapiVersion: v1kind: Servicemetadata:name: frontend-servicespec:selector:app: frontend-appports:- protocol: TCPport: 80targetPort: 3000type: LoadBalancer6.3 部署到Kubernetes集群使用kubectl命令部署应用到Kubernetes集群:
kubectl apply -f deployment.yamlkubectl apply -f service.yaml现在,您的前端应用已经在Kubernetes集群中运行,并可以通过LoadBalancer类型的Service外部访问 。
7.关于前端React项目架构7.1 核心技术

  • 打包编译 - vite
  • 包管理 - pnpm
  • 编程语言 - typescript
  • 前端框架 - react
  • 路由 - react-router
  • UI组件库 - antd
  • cssinjs(不考虑性能开销) - emotion
  • 全局数据共享 - zustand
  • 自动生成api - openapi
  • 网络请求 - axios
  • 数据请求利器 - react-query
  • 通用hook(可不用) - ahooks
  • 错误边界 - react-error-boundary
  • 前端日志(暂未集成) - sentry-JAVAscript
  • hack - babel
  • 代码检查 - eslint
  • ts代码检查插件 - typescript-eslint
  • 代码美化 - prettier
  • git钩子 - husky
  • commit格式化 -commitlint
7.2 基于openapi自动获取api请求函数// src/core/openapi/index.ts// 示例代码generateService({// openapi地址schemaPath: `${appConfig.baseURL}/${urlPath}`,// 文件生成目录serversPath: "./src",// 自定义网络请求函数路径requestImportStatement: `/// <reference types="./typings.d.ts" />nimport request from "@request"`,// 代码组织命名空间, 例如:Apinamespace: "Api",});7.3 调用接口(react-query), 支持自动loading和接口请求联动// 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" });


推荐阅读