Skip to content
On this page

web 平台

前端框架与项目文件目录结构

选择合适的前端框架可以提高开发效率和用户体验。我们主要使用的前端框架是 vue 与 react

  1. vue项目,不管是是通过 webpack 还是 vite 搭建的项目,主要目录结构如下:

    项目名称
    |-- public 默认存储文件夹,默认存储一些静态文件,网站图标之类
    |-- src 主要文件夹
    |-- .env* 环境配置文件,一般有 .env.dev .env.test .env.pro 三个文件,分别对应开发环境、测试环境、生产环境,如果还有其他环境,再添加对应文件即可
    |-- package.json 安装依赖配置文件
    |-- index.html
    |-- .*ignore
    |-- *.config.js/ts

    接下来,我们主要对 src 文件夹 进行配置

    active
    src
    |-- api 请求接口注入
    |      |-- 请求业务模块.js
    |-- assets 本地资源,资源分类
    |      |-- svgs
    |      |-- imgs
    |      |-- videos
    |-- components 组件
    |      |-- 组件名称
    |            |-- index.vue
    |            |-- 其他文件(css/.js) 其他一些方法(非必有)
    |-- config 配置文件夹(一般用作全局使用)(非必有)
    |      |-- 文件名.js/json
    |-- directives 自定义指令 (非必要)
    |      |-- 指令名称
    |            |-- index.js
    |-- layout 界面主窗口布局文件夹
    |      |-- 各个布局文件夹 (推荐采用HTML5语义化标签命名)
    |            |-- index.vue
    |      |-- index.vue
    |      |-- 其他界面(如:看板)
    |-- router 路由
    |      |-- modules (根据项目是否进行业务分模块以及打包)(非必有)
    |      |-- index.js
    |-- store 状态管理
    |      |-- modules (根据项目是否进行业务分模块以及打包)(非必有)
    |            |-- app.js 应用的的一些设置
    |            |-- dict.js 数据字典
    |            |-- permission.js 权限
    |            |-- 其他
    |      |-- index.js
    |-- styles 样式文件
    |      |-- index.css/scss/less 负责导入其他样式
    |      |-- reset.css/scss/less 重置默认样式
    |      |-- root.css/scss/less root样式
    |      |-- theme.css/scss/less 主题样式
    |      |-- global.css/scss/less 全局样式
    |-- utils 工具类、第三方js/sdk
    |      |-- request.js 请求封装类
    |      |-- js_sdk.js 第三方js_sdk
    |      |-- validate.js 校验
    |      |-- filter.js 等等
    |-- views 业务内容
    |      |-- 业务组件名称
    |            |-- dialog 弹窗dialog组件文件夹
    |                  |-- 弹窗组件名称.vue
    |            |-- index.vue 主要业务组件
    |            |-- modules 子业务模块(非必有)
    |                  |-- 子业务名称(复杂业务建立文件夹,简单业务直接名称.vue)
    |            |-- components 业务模块公共组件
    |                  |-- 业务模块组件.vue,如search.vue
    |            |-- 业务名称(中文名称,便于查找).md  md文件备注开发该业务模块的一些注意事项
    |-- mixins vue2拥有,vue3项目禁止使用(非必有)
    |      |-- 混合器名称page、dialog等
    |            |-- index.js
    |-- App.vue 最外层vue示例容器
    |-- main.js vue注入以及依赖配置以及初始化
    src
    |-- api 请求接口注入
    |      |-- 请求业务模块.ts
    |-- assets 本地资源,资源分类
    |      |-- svgs
    |      |-- imgs
    |      |-- videos
    |-- components 组件
    |      |-- 组件名称
    |            |-- index.vue
    |            |-- 其他文件(css/.ts) 其他一些方法(非必有)
    |-- config 配置文件夹(一般用作全局使用)(非必有)
    |      |-- 文件名.ts/json
    |-- directives 自定义指令 (非必要)
    |      |-- 指令名称
    |            |-- index.ts
    |-- layout 界面主窗口布局文件夹
    |      |-- 各个布局文件夹 (推荐采用HTML5语义化标签命名)
    |            |-- index.vue
    |      |-- index.vue
    |      |-- 其他界面(如:看板)
    |-- router 路由
    |      |-- modules (根据项目是否进行业务分模块以及打包)(非必有)
    |      |-- index.ts
    |-- store 状态管理
    |      |-- modules (根据项目是否进行业务分模块以及打包)(非必有)
    |            |-- 业务.d.ts 存放业务状态管理数据的类型、接口声明等
    |            |-- app.ts 应用的的一些设置
    |            |-- dict.ts 数据字典
    |            |-- permission.ts 权限
    |            |-- 其他
    |      |-- index.ts
    |-- styles 样式文件
    |      |-- index.css/scss/less 负责导入其他样式
    |      |-- reset.css/scss/less 重置默认样式
    |      |-- root.css/scss/less root样式
    |      |-- theme.css/scss/less 主题样式
    |      |-- global.css/scss/less 全局样式
    |-- utils 工具类、第三方js/sdk
    |      |-- request.ts 请求封装类
    |      |-- js_sdk.js 第三方js_sdk // 注意如果第三方没有ts版本,记得引入@ts-ignore去除ts校验
    |      |-- validate.ts 校验
    |      |-- filter.ts 等等
    |-- views 业务内容
    |      |-- 业务组件名称
    |            |-- dialog 弹窗dialog组件文件夹
    |                  |-- 弹窗组件名称.vue
    |            |-- index.d.ts // 存放业务数据类型、接口声明等
    |            |-- index.vue 主要业务组件
    |            |-- modules 子业务模块(非必有)
    |                  |-- 子业务名称(复杂业务建立文件夹,简单业务直接名称.vue)
    |            |-- components 业务模块公共组件
    |                  |-- 业务模块组件.vue,如search.vue
    |            |-- 业务名称(中文名称,便于查找).md  md文件备注开发该业务模块的一些注意事项
    |-- App.vue 最外层vue示例容器
    |-- main.ts vue注入以及依赖配置以及初始化
    |-- types 全局类型申明文件
    |      |-- *.d.ts

    ts 项目中

    *.d.ts 文件当存储业务数据类型、接口数据等,该文件非必要创建,看实际业务而定

  2. react

    以后补充

页面布局和组件

设计良好的页面布局和可复用的组件能够提升用户界面的一致性和可维护性。 在前端开发项目中类型 web 平台主要由两类主导市场,一个和是面向 C 端用户的 web 前台,另一个则是面向 B 端的后台管理系统

  • web 前台

    • 面向用户的网站或应用程序的用户界面,它用于展示和提供功能给用户,并与用户进行交互。Web 前台通常由网页、移动应用等组成,用户可以通过浏览器或移动设备访问和使用
    • 主要负责与用户的互动和展现信息,包括用户注册、登录、浏览商品、提交订单等操作;而 Web 后台管理平台主要面向管理员,用于管理网站或应用程序的内容、用户权限、数据统计、产品管理、订单管理等,以保证前台系统正常运行和管理工作的便利性
    • 作为面向 C 端用户,界面构建和布局是根据 设计稿1:1 还原的,以至于能提升更好的用户体验感,主要用的设计平台就是 蓝湖平台(https://lanhuapp.com)
  • web 后台管理平台

    • 也称为后台管理系统、管理后台,是用于管理、维护和配置 Web 前台系统的后台界面。它通常只有授权的管理员或运营人员可以访问和使用。Web 后台管理平台提供了对前台系统内容、用户、数据等的管理和控制能力
    • 进行网站配置、添加、编辑和删除内容,管理用户账号和权限,监控网站访问情况,处理订单和支付等任务。同时,后台管理平台还提供一些数据分析功能,帮助管理员了解用户行为、销售情况等,从而进行进一步的优化和决策
    • 一般作为后台管理系统的开发我们会使用到第三方组件库,常用的有:
      1. elementUI
      2. iview
      3. Ant Design

路由和导航

路由和导航在前端开发中扮演着重要的角色,用于管理不同页面之间的切换和导航操作。它们可以提供更流畅的用户体验,并支持基于 URL 的页面分享和书签功能。

  • 路由(Routing)是指确定应用程序界面显示哪个页面的过程。在单页应用(Single-Page Application,SPA)中,整个应用只有一个 HTML 页面,通过动态加载和替换内容来展示不同的视图。一般来说,路由会根据用户的操作或 URL 的变化来决定当前显示的页面,并且会记录历史浏览记录,以便用户可以回退到之前访问过的页面。

  • 导航(Navigation)则是指用户在应用中切换页面或执行其他导航操作的行为。导航可以通过点击链接、按钮或菜单项等方式触发,也可以通过编程方式进行控制。当用户进行导航时,路由系统会根据导航目标来加载相应的页面,并更新浏览器的 URL 以反映当前状态。

常见的前端框架都提供了路由和导航功能的支持。它们通常提供了路由组件、路由配置和导航组件等工具,开发人员可以使用这些工具来定义路由规则、设置页面间的关联关系,并处理导航事件。一些常用的功能包括路由参数传递、嵌套路由、重定向、权限控制等。

通过良好的路由和导航设计,可以实现页面之间的无缝切换,提高用户体验和应用的可维护性。同时,基于 URL 的导航也使得用户可以轻松地分享特定页面或状态给其他人,增强了应用的可分享性和可链接性。

数据交互和后端通信

在 Web 应用程序中,前端通常需要与后端服务器进行数据交互,包括获取数据、提交表单、发送请求等操作。

  • 数据交互可以通过各种协议和技术来实现,其中最常见的是使用 HTTP(Hypertext Transfer Protocol)协议。前端通过发送 HTTP 请求到后端服务器,后端服务器则根据请求处理逻辑进行相应的处理,并将结果返回给前端。这种请求-响应模式能够满足大部分应用程序的数据交互需求。

  • 在前端开发中,可以使用不同的技术来发起 HTTP 请求和处理响应。常用的方式包括使用浏览器提供的原生 XMLHttpRequest 对象、Fetch API、Axios、jQuery AJAX 等库或框架。这些工具提供了简化的 API 和功能,使得前端开发人员能够更方便地进行数据交互操作。

  • 在数据交互过程中,常见的请求方式包括 GET、POST、PUT、DELETE 等,它们分别表示获取数据、提交数据、更新数据和删除数据等操作。请求和响应中可以携带各种数据格式,例如 JSON、XML、表单数据等,根据具体需求选择合适的数据格式进行传输。

  • 为了保证数据的安全性和完整性,可以在数据交互过程中采用一些安全机制,例如使用 HTTPS 协议进行加密传输、对请求进行身份验证和授权、对数据进行输入验证和过滤等。

通常我们会统一封装成一个请求类,并提供请求的四种(GET、POST、PUT、DELETE)方法,具体请查看工具类篇章

状态管理

状态管理是指在前端应用程序中有效地管理和共享数据的一种模式或方法。随着应用程序的复杂性增加,各个组件之间的数据传递和共享变得更加困难,这时就需要使用状态管理来简化和优化数据流。

传统上,前端应用程序的状态通常保存在组件内部的本地状态(Local State)中,并通过 props 属性进行父子组件之间的数据传递。但当应用程序规模增大,组件层级深度增加时,这种方式可能会导致数据流混乱、难以追踪和调试。

状态管理工具(如 Redux、Vuex 等)的出现解决了这个问题。这些工具提供了一个集中式的状态存储容器,称为状态库(State Store),用于存储、管理和共享应用程序的各种数据。组件可以从状态库中获取数据,并通过触发动作(Actions)来更新数据,而无需直接操作状态库。

状态库通常包含以下几个核心概念

  • 状态(State):表示应用程序的数据状态。它是只读的,组件通过订阅状态来获取数据。

  • 动作(Actions):表示对数据进行修改或更新的操作。组件通过派发(Dispatch)动作来触发数据的变更。

  • 变更(Mutations):表示对状态进行实际修改的方法。动作通过调用变更来更新状态。

  • 订阅(Subscriptions):表示组件订阅状态的变化,在状态更新时触发相关逻辑。

使用状态管理有以下好处

  • 集中化的数据管理:状态库提供了一个集中的地方来管理应用程序的数据,使得数据流清晰可见,易于调试和追踪。

  • 组件解耦:通过将数据抽离到状态库中,组件之间的数据传递和共享变得简单明了,减少了组件间的直接依赖和耦合。

  • 可预测的状态变更:在状态管理中,对状态的变更必须通过执行动作来进行,使得状态的变更变得可控、可预测。这样可以更好地维护和调试代码。

表单验证和输入处理

在一般的组件库(如 element 等),对应的组件已经有了基本的表单验证配置以及方法,当然表单验证和输入处理初始的目的主要是用于确保用户输入的数据符合预期的格式和要求。

以下是有关表单验证和输入处理的一些建议:

  1. 客户端验证:在前端通过使用 JavaScript 进行客户端验证,可以在用户提交表单之前对输入进行验证。例如,检查字段是否为空、长度是否满足要求、输入是否为有效的邮箱地址或手机号码等。这种验证可以提供即时反馈给用户,并减少向后端提交无效数据的次数。

  2. 服务器端验证:尽管进行了客户端验证,但仍然需要在服务器端进行验证。客户端验证只是一种辅助手段,可以防止无效的输入提交到服务器,但不能完全信任客户端的验证结果。服务器端验证能够更可靠地验证数据合法性,防止恶意用户绕过客户端验证。

  3. 输入过滤和清理:在处理用户输入之前,对输入数据进行过滤和清理是很重要的。这可以通过移除不必要的空格、转义特殊字符来实现,以防止潜在的安全漏洞(如跨站脚本攻击)和数据不一致。

  4. 错误提示和反馈:在进行表单验证时,向用户提供清晰的错误提示和反馈是必要的。当用户输入无效数据时,及时通知用户错误的字段和具体问题,并给出解决方案或建议。

  5. 使用验证库或框架:为了简化表单验证和输入处理的工作,可以使用各种验证库或框架。这些库提供了可重用的验证规则、表单字段的自动验证和错误处理等功能,如 jQuery Validation、Yup、Formik 等。

  6. 安全性考虑:在进行表单验证和输入处理时,要注意处理敏感数据的安全性。确保密码等敏感信息在传输和存储过程中得到适当的加密和保护,以防止未经授权的访问。

响应式设计

响应式设计是一种网页设计方法,旨在使网站或应用程序能够适应不同屏幕尺寸和设备类型,以提供更好的用户体验。以下是关于响应式设计的一些要点:

  1. 弹性布局:响应式设计使用弹性布局来自动调整页面元素的大小和位置。相比于固定布局,弹性布局可以根据屏幕尺寸自动伸缩,使内容适应不同的显示区域。

  2. 媒体查询:媒体查询是用于根据设备特性(如屏幕宽度、高度、分辨率等)来应用不同样式规则的 CSS 技术。通过使用媒体查询,可以针对不同的屏幕尺寸和设备类型应用不同的样式,从而适配不同的显示环境。

  3. 流动内容:响应式设计考虑到不同屏幕尺寸上的可视区域大小有限,因此需要优化内容排布和呈现方式。流动内容指的是将重要内容放置在前面,避免水平滚动,并在小屏幕上进行适当的折行和缩减,以确保用户可以轻松阅读和浏览页面。

  4. 图像优化:在响应式设计中,图像是一个重要的考虑因素。针对不同的屏幕尺寸,可以使用适当的图像压缩技术(如 WebP、JPEG XR 等)以减少加载时间和带宽消耗。此外,还可以使用 CSS 属性来确保图像大小适应容器,并避免图像溢出或失真。

  5. 触摸友好性:由于响应式设计涉及移动设备和触摸屏幕,因此需要确保界面元素的大小、间距和交互方式适合手指触控操作。增大可点击区域、使用合适的按钮和手势操作等都是提升触摸友好性的方法。

  6. 设备测试:在实施响应式设计之前,进行设备测试非常重要。通过在不同的设备和浏览器上测试网站或应用程序,可以发现并修复可能存在的布局问题、样式错误或功能故障。

性能优化

对于大型的 web 管理平台,性能优化是至关重要的。优化加载时间、减少资源请求、代码分割和懒加载等技术可以提升用户体验和降低服务器负载。

具体如何优化,以后单独开一期内容讲解

测试和调试

测试和调试是软件开发过程中非常重要的环节,用于确保软件的质量和稳定性。下面是关于测试和调试的一些要点:

测试(Testing):

  1. 单元测试:单元测试是对软件中最小可测试单元进行验证的过程。通过编写测试用例,对函数、方法或模块进行测试,并检查其行为是否符合预期。

  2. 集成测试:集成测试是将多个单元测试整合在一起,对不同模块之间的接口和交互进行测试。它旨在发现组件之间的错误和缺陷,并确保它们在协作时正常工作。

  3. 系统测试:系统测试是对整个软件系统进行测试的过程,以验证它是否满足规格和需求。它涵盖了功能、性能、安全性等方面的测试,可以用来评估系统在真实环境中的表现。

  4. 验收测试:验收测试是由最终用户或客户进行的测试,旨在确认软件是否满足预期的业务需求和目标。

调试(Debugging):

  1. 日志记录:在开发和测试过程中添加日志记录代码,以便在出现问题时追踪代码执行路径、变量状态和错误消息。这有助于快速定位和解决问题。

  2. 断点调试:使用开发工具提供的调试功能,在代码中设置断点,并逐步执行程序以观察变量值、调用栈和代码路径。这有助于分析问题并找到错误所在。

  3. 重现问题:尽可能准确地复制出现问题的步骤,并通过特定输入值或特定环境条件来重新创建问题。这样可以更容易地诊断和修复错误。

  4. 排查错误:通过分析代码、检查错误信息、查看日志和使用调试工具等方法,逐渐缩小问题范围,找到引发错误的具体原因,并进行修复。

总结起来,测试和调试是软件开发过程中必不可少的环节。通过各种层次的测试(包括单元测试、集成测试、系统测试和验收测试),可以发现和解决软件中的问题和缺陷。而调试则是针对已经发现的问题进行分析和修复的过程,通过日志记录、断点调试、问题重现和错误排查等方式,定位和解决代码中的错误。

环境配置

对于 web 项目我们的主要环境配置主要针对 vue 和 react 环境,项目构建主要是在 vue 框架里,vue 构建工具主要是 webpack 和 vite ,react 我们将在后续补充

  • vue

    如果是采用 webpack 构建 vue 项目,我们统一使用 vue-cli 脚手架来搭建,不单独集成 vue 和 webpack。vue-cli 集成了 webpack

    1. 第一步:在项目根目录下添加环境配置文件,我们必须添加的 3 个环境文件分别为.env.dev、.env.test、.env.prod。文件内容主要如下:

      vue-cli(webpack) 搭建:

      # 环境名称
      VUE_ENV_NAME='开发环境'
      # 端口
      VUE_PORT=8090
      # 代理
      VUE_BASE_PROXY=/api
      # 请求地址
      VUE_BASE_API=https://test-b2bshop-common.yiwcloud.com

      vite 搭建:

      # 环境名称
      VITE_ENV_NAME='开发环境'
      # 端口
      VITE_PORT=8090
      # 代理
      VITE_BASE_PROXY=/api
      # 请求地址
      VITE_BASE_API=https://test-b2bshop-common.yiwcloud.com
    2. 第二部:在对应的 vue.config.js/vite.config.js 里配置开发环境。具体代码如下:

      vue-cli(webpack) 搭建:

      js
      module.exports = {
       ...
       devServer: {
         host:'0.0.0.0',
         port: process.env.VUE_PORT,
         proxy: {
          [process.env.VUE_BASE_PROXY]: {
            target: process.env.VUE_BASE_API,
            changeOrigin: true,
            pathRewrite:{
              [`^${process.env.VUE_BASE_PROXY}`]:''
            }
          },
        }
       }
       ...
      }

      vite 搭建:

      vite 项目我们统一采用 ts 开发

      ts
      import { loadEnv } from 'vite'
      import type { UserConfig, ConfigEnv } from 'vite'
      
      export default ({ mode }: ConfigEnv): UserConfig => {
        const env = loadEnv(mode, process.cwd()) as any
        return {
          ...
          server: {
              port: env.VITE_PORT,
              host: '0.0.0.0',
              proxy: {
                [env.VITE_BASE_PROXY]: {
                  target: env.VITE_BASE_API,
                  changeOrigin: true,
                  rewrite: (path) =>
                    path.replace(new RegExp(`^${env.VITE_BASE_PROXY}`), ''),
                },
              },
            }
          ...
        }
      }
    3. 第三步:在 package.json 里的 scripts 配置对应的运行脚本命令。代码如下:

      vue-cli(webpack)搭建

      json
      "scripts": {
        "dev": "vue-cli-service serve --mode dev",
        "test": "vue-cli-service serve --mode test",
        "prod":"vue-cli-service serve --mode prod",
        "build:test": "vue-cli-service build --mode test",
        "build:prod": "vue-cli-service build --mode prod",
      },

      vite 构建

      vite 项目我们统一采用 ts 开发,默认加载 vue-tsc 依赖

      json
      "scripts": {
        "dev": "vue-tsc && vite --mode dev",
        "test": "vue-tsc && vite --mode test",
        "prod": "vue-tsc && vite --mode prod",
        "build:test": "vue-tsc && vite build --mode test",
        "build:prod": "vue-tsc && vite build --mode prod",
      },
  • react

    后续补充

部署、发布与上线

  • 部署

    目前服务器上是通过 docker 部署的,gitLab 的 CI/CD 自动打包部署,流程如下:

    1. 添加镜像文件,在项目根目录添加 Dockerfile 文件,内容如下
    sh
    # 设置基础镜像
    FROM swr.cn-southwest-2.myhuaweicloud.com/yhy-public/nginx:latest
    
    # 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
    COPY dist/  /usr/share/nginx/html/
    
    EXPOSE 80
    1. 添加部署文件,在项目根目录添加 deploy 文件夹,文件加下添加 3 个文件,deployment-dev.yaml、deployment-preview、deployment-release.yaml

      • deployment-dev.yaml
      yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: SERVICE_NAME
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: SERVICE_NAME
        template:
          metadata:
            labels:
              app: SERVICE_NAME
          spec:
            containers:
              - name: SERVICE_NAME
                image: swr.cn-southwest-2.myhuaweicloud.com/yhy-home/SERVICE_NAME:IMAGE_TAG
                imagePullPolicy: Always
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 256Mi
                volumeMounts:
                  - name: SERVICE_NAME-config-volume
                    mountPath: /etc/nginx/conf.d
            volumes:
              - name: SERVICE_NAME-config-volume
                configMap:
                  name: SERVICE_NAME-config
            imagePullSecrets:
              - name: harbor-secret
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: SERVICE_NAME-svc
        namespace: NAMESPACE
      spec:
        ports:
          - name: http
            port: 80
            protocol: TCP
            targetPort: 80
        selector:
          app: SERVICE_NAME
      
      ---
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: SERVICE_NAME-config
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME-cm
      data:
        default.conf: |
          server {
              listen       80;
              server_name  localhost;
      
              #charset koi8-r;
              access_log  /var/log/nginx/host.access.log  main;
              error_log  /var/log/nginx/error.log  error;
      
              #nginx优化----------------------
              #隐藏版本号
              server_tokens on;
              #开启高效文件传输模式
              sendfile on;
      
              #减少网络报文段数量
              #tcp_nopush on;
              #提高I/O性能
              tcp_nodelay on;
      
              #开启gzip压缩
              gzip on;
      
              gzip_min_length 1k;
      
              gzip_comp_level 9;
      
              gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
      
              gzip_vary on;
      
              client_max_body_size 5m;
      
              gzip_disable "MSIE [1-6]\.";
      
              location / {
                  root   /usr/share/nginx/html;
                  index  index.html index.htm;
                  add_header Cache-Control "no-cache, no-store";
                  try_files $uri $uri/ /index.html;
              }
              location /api/ {
                # 将该服务下的所有请求实体的大小限制为5m
                client_max_body_size 5m;
                proxy_pass  https://test-b2bshop-common.yiwcloud.com/;
              }
      
              error_page   500 502 503 504  /50x.html;
              location = /50x.html {
                  root   /usr/share/nginx/html;
              }
          }
      • deployment-preview.yaml
      yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: SERVICE_NAME
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: SERVICE_NAME
        template:
          metadata:
            labels:
              app: SERVICE_NAME
          spec:
            containers:
              - name: SERVICE_NAME
                image: swr.cn-southwest-2.myhuaweicloud.com/yhy-home/SERVICE_NAME:IMAGE_TAG
                imagePullPolicy: Always
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 256Mi
                volumeMounts:
                  - name: SERVICE_NAME-config-volume
                    mountPath: /etc/nginx/conf.d
            volumes:
              - name: SERVICE_NAME-config-volume
                configMap:
                  name: SERVICE_NAME-config
            imagePullSecrets:
              - name: harbor-secret
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: SERVICE_NAME-svc
        namespace: NAMESPACE
      spec:
        ports:
          - name: http
            port: 80
            protocol: TCP
            targetPort: 80
        selector:
          app: SERVICE_NAME
      
      ---
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: SERVICE_NAME-config
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME-cm
      data:
        default.conf: |
          server {
              listen       80;
              server_name  localhost;
      
              #charset koi8-r;
              access_log  /var/log/nginx/host.access.log  main;
              error_log  /var/log/nginx/error.log  error;
      
              #nginx优化----------------------
              #隐藏版本号
              server_tokens on;
              #开启高效文件传输模式
              sendfile on;
      
              #减少网络报文段数量
              #tcp_nopush on;
              #提高I/O性能
              tcp_nodelay on;
      
              #开启gzip压缩
              gzip on;
      
              gzip_min_length 1k;
      
              gzip_comp_level 9;
      
              gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
      
              gzip_vary on;
      
              client_max_body_size 5m;
      
              gzip_disable "MSIE [1-6]\.";
      
              location / {
                  root   /usr/share/nginx/html;
                  index  index.html index.htm;
                  add_header Cache-Control "no-cache, no-store";
              }
              location /api/ {
                # 将该服务下的所有请求实体的大小限制为5m
                client_max_body_size 5m;
                proxy_pass  https://test-b2bshop-common.yiwcloud.com/;
              }
              error_page   500 502 503 504  /50x.html;
              location = /50x.html {
                  root   /usr/share/nginx/html;
              }
          }
      • deployment-release.yaml
      yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: SERVICE_NAME
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: SERVICE_NAME
        template:
          metadata:
            labels:
              app: SERVICE_NAME
          spec:
            containers:
              - name: SERVICE_NAME
                image: swr.cn-southwest-2.myhuaweicloud.com/yhy-home/SERVICE_NAME:IMAGE_TAG
                imagePullPolicy: Always
                resources:
                  limits:
                    cpu: 250m
                    memory: 512Mi
                  requests:
                    cpu: 250m
                    memory: 256Mi
                volumeMounts:
                  - name: SERVICE_NAME-config-volume
                    mountPath: /etc/nginx/conf.d
            volumes:
              - name: SERVICE_NAME-config-volume
                configMap:
                  name: SERVICE_NAME-config
            imagePullSecrets:
              - name: harbor-secret
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: SERVICE_NAME-svc
        namespace: NAMESPACE
      spec:
        ports:
          - name: http
            port: 80
            protocol: TCP
            targetPort: 80
        selector:
          app: SERVICE_NAME
      
      ---
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: SERVICE_NAME-config
        namespace: NAMESPACE
        labels:
          app: SERVICE_NAME-cm
      data:
        default.conf: |
          server {
              listen       80;
              server_name  localhost;
      
              #charset koi8-r;
              access_log  /var/log/nginx/host.access.log  main;
              error_log  /var/log/nginx/error.log  error;
      
              #nginx优化----------------------
              #隐藏版本号
              server_tokens on;
              #开启高效文件传输模式
              sendfile on;
      
              #减少网络报文段数量
              #tcp_nopush on;
              #提高I/O性能
              tcp_nodelay on;
      
              #开启gzip压缩
              gzip on;
      
              gzip_min_length 1k;
      
              gzip_comp_level 9;
      
              gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
      
              gzip_vary on;
      
              client_max_body_size 5m;
      
              gzip_disable "MSIE [1-6]\.";
      
              location / {
                  root   /usr/share/nginx/html;
                  index  index.html index.htm;
                  add_header Cache-Control "no-cache, no-store";
              }
              location /api/ {
                # 将该服务下的所有请求实体的大小限制为5m
                client_max_body_size 5m;
                proxy_pass  https://test-b2bshop-common.yiwcloud.com/;
              }
      
              error_page   500 502 503 504  /50x.html;
              location = /50x.html {
                  root   /usr/share/nginx/html;
              }
          }
          apple-app-site-association: |
            {
                "applinks": {
                    "apps": [],
                    "details": [
                        {
                            "appID": "6W2HS65338.com.tusm.yhcIotpm",
                            "paths": ["/app/*"]
                        }
                    ]
                }
            }
    2. 添加 CI/CD 脚本文件,在项目根目录添加.gitlab-ci.yml 文件,主要内容如下

    yml
    variables:
      ENV: test
      DOCKER_TLS_CERTDIR: ''
      KUBECONFIG: /etc/deploy/config
      NAMESPACE: 'b2bshop-web'
      REPLICAS: 1
      SSH_PASS: ''
    
      cache:
        key: b2bshop-web
        paths: - node_modules
    
      stages:
    
      - build
      - docker_build
      - deploy
    
      install_job:
      image: node:18.14.2
      stage: build
      only: - develop - main - tags
      tags: - yhy-runner
      script: - npm install - |
        if [["$CI_COMMIT_BRANCH" = "develop"]]; then
          npm run build:test
        else
          npm run build:prod
        fi
    
        - ls -altrh # 输出该目录下比较详细的列表
    
      artifacts:
      paths: - dist/
    
      docker_build_job:
      stage: docker_build
      image: docker:stable
      services: - docker:dind
      dependencies: - install_job
      only: - develop - main - tags
      tags: - yhy-runner
      script: - |
          if [[-z "$CI_COMMIT_TAG"]]; then
          export CI_APP_TAG=$CI_COMMIT_SHORT_SHA
                else
                  export CI_APP_TAG=$CI_COMMIT_TAG
          fi - docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD swr.cn-southwest-2.myhuaweicloud.com # 登录镜像仓库
          - docker build -t swr.cn-southwest-2.myhuaweicloud.com/yhy-home/$CI_PROJECT_NAME:$CI_APP_TAG .
          - docker push swr.cn-southwest-2.myhuaweicloud.com/yhy-home/$CI_PROJECT_NAME:$CI_APP_TAG
    
      deploy_job_test:
      image: swr.cn-southwest-2.myhuaweicloud.com/yhy-public/kubectl:v1.16.7
      dependencies: - docker_build_job
      stage: deploy
      tags: - yhy-runner
      only: - develop
      script: - |
          if [[-z "$CI_COMMIT_TAG"]]; then
          export CI_APP_TAG=$CI_COMMIT_SHORT_SHA
                else
                  export CI_APP_TAG=$CI_COMMIT_TAG
          fi - mkdir -p /etc/deploy - echo $kubecfg | base64 -d > $KUBECONFIG
              - sed -i "s/IMAGE_TAG/$CI_APP_TAG/g" deploy/deployment-dev.yaml - sed -i "s/SERVICE_NAME/$CI_PROJECT_NAME/g" deploy/deployment-dev.yaml
              - sed -i "s/NAMESPACE/$NAMESPACE/g" deploy/deployment-dev.yaml - cat deploy/deployment-dev.yaml - kubectl apply -f deploy/deployment-dev.yaml
    
      deploy_job_preview:
      image: swr.cn-southwest-2.myhuaweicloud.com/yhy-public/kubectl:v1.16.7
      dependencies: - docker_build_job
      stage: deploy
      tags: - yhy-runner
      only: - main
      script: - |
          if [[-z "$CI_COMMIT_TAG"]]; then
          export CI_APP_TAG=$CI_COMMIT_SHORT_SHA
                else
                  export CI_APP_TAG=$CI_COMMIT_TAG
          fi - mkdir -p /etc/deploy - echo $kubecfg | base64 -d > $KUBECONFIG
              - NAMESPACE="preview-"$NAMESPACE - sed -i "s/IMAGE_TAG/$CI_APP_TAG/g" deploy/deployment-preview.yaml
              - sed -i "s/SERVICE_NAME/$CI_PROJECT_NAME/g" deploy/deployment-preview.yaml - sed -i "s/NAMESPACE/$NAMESPACE/g" deploy/deployment-preview.yaml - cat deploy/deployment-preview.yaml - kubectl apply -f deploy/deployment-preview.yaml
    
      deploy_job_prod:
      image: swr.cn-southwest-2.myhuaweicloud.com/yhy-public/kubectl:v1.16.7
      dependencies: - docker_build_job
      stage: deploy
      tags: - yhy-runner
      only: - tags
      script: - |
          if [[-z "$CI_COMMIT_TAG"]]; then
          export CI_APP_TAG=$CI_COMMIT_SHORT_SHA
                else
                  export CI_APP_TAG=$CI_COMMIT_TAG
          fi - REPLICAS=2 - sed -i "s/IMAGE_TAG/$CI_APP_TAG/g" deploy/deployment-release.yaml
              - sed -i "s/SERVICE_NAME/$CI_PROJECT_NAME/g" deploy/deployment-release.yaml - sed -i "s/NAMESPACE/$NAMESPACE/g" deploy/deployment-release.yaml
              - cat deploy/deployment-release.yaml
              - mkdir -p $CI_PROJECT_NAME/$CI_APP_TAG - cp -r deploy/\* $CI_PROJECT_NAME/$CI_APP_TAG - sshpass -p $SSH_PASS ssh -o StrictHostKeyChecking=no  root@jumpserver.yiwcloud.com -tt exit
              - sshpass -p $SSH_PASS scp -r $CI_PROJECT_NAME root@jumpserver.yiwcloud.com:/root/deployment/$NAMESPACE/

    作为前端开发人员主要关注的是下面这一块内容:

    yml
    install_job:
      image: node:18.14.2 // node 环境版本
      stage: build
      only: - develop - main - tags
      tags: - yhy-runner
      script: - npm install - |
          if [["$CI_COMMIT_BRANCH" = "develop"]]; then // 判断分支条件执行相应的 js 脚本命令
          npm run build:test
          else
          npm run build:prod
          fi
    
          - ls -altrh # 输出该目录下比较详细的列表
    
      artifacts:
      paths: - dist/

    当前这只是一个文件,具体还是按照实际需求更改

  • 发布

    添加了上面部署文件后,代码通过 git push 就直接通过 gitlab 的运维脚本 CI/CD 进行自动化打包了,这时候我们可以点击 CI/CD 菜单查看部署发布进度

  • 上线

    发布完成后,前往网页验证本次更新内容,确保产品的新功能的上线以及验证