帮公司搭了个Nuxt3项目框架


theme: smartblue

最近公司立项了一个新项目,因为是to C 的,所以对SEO是有较高需求的,由于公司前端技术栈统一用的VUE,顺理成章的就选择了nuxt这个全栈框架。项目立项之后我就被安排了负责前端项目框架的搭建,从搭建过程的体验来看,技术栈切换到nuxt还是有门槛的,所以这里我就把经过我打磨好的nuxt完整项目框架分享出来,大家即拿即用,童叟无欺。顺嘴提一句,欢迎大家关注我的微信公众号fever code,获取最新技术分享。

项目结构

- api
- assets
-- images
-- lang
---- en_us.json
---- zh_cn.json
-- scss
---- constants.scss
---- index.scss
- components
- composables
-- store
-- pinia
-- locale.js
-- auth.js
-- toast.js
- configs
- constants
-- auth.js
- layouts
-- default.vue
-- login.vue
- middleware
-- default.global.js
- pages
- plugins
-- pinia.js
- public
- server
-- api
---- list.js
-- middleware
---- request.js
- utils
-- http.js
- .env.development
- .env.local
- .env.production
- .eslintrc.cjs
- .gitignore
- .prettierrc.json
- app.vue
- error.vue
- i18n.config.js
- nuxt.config.ts
- package.json

NUXT项目配置

下面贴一下nuxt项目配置的代码。因为UI设计师选用的样式风格是arco-design组件库的风格,所以项目中也集成的acro-design。项目采用的适配方案是px-to-vw,状态管理工具是nuxt自带的useStatepinia,简单的状态管理采用useState就够了,复杂的状态就决定使用pinia分模块化管理。项目的受众群体囊括了海内外的业内人士,所以在项目中也做了国际化的处理,环境变量使用的是VITE_开头,客户端可以使用import.env.meta访问,也可以使用useRuntimeConfig获得。

// https://nuxt.com/docs/api/configuration/nuxt-configexport default defineNuxtConfig({devtools: { enabled: false },app: {head: {titleTemplate: '%s - 京东商城',title: '京东商城',charset: 'utf-8',htmlAttrs: {lang: 'zh-CN'},meta: [{ name: 'keywords', content: '网上购物,网上商城,家电,手机,电脑,服装,居家,母婴,美妆,个护,食品,生鲜,京东' },{name: 'description',content:'京东JD.COM-专业的综合网上购物商城,为您提供正品低价的购物选择、优质便捷的服务体验。商品来自全球数十万品牌商家,囊括家电、手机、电脑、服装、居家、母婴、美妆、个护、食品、生鲜等丰富品类,满足各种购物需求。'}]}},// 注入全局样式css: ['~/assets/scss/index.scss'],modules: [// arco-design UI组件库'arco-design-nuxt-module',// 国际化插件'@nuxtjs/i18n',[// pinia状态管理库'@pinia/nuxt',{// 项目中自动导入pinia的defineStore方法autoImports: ['defineStore']}]],// arco-design UI组件库配置arco: {importPrefix: 'A',hookPrefix: 'Arco',locales: ['getLocale'],localePrefix: 'Arco'},// 国际化插件配置i18n: {strategy: 'no_prefix', // 添加路由前缀的方式locales: ['en', 'zh'], //配置语种defaultLocale: 'zh', // 默认语种vueI18n: 'i18n.config.js' // 通过vueI18n配置},// nuxt组件库配置components: [{path: '~/components',extensions: ['.vue'],pathPrefix: false}],imports: {dirs: [// 扫描composables目录中的所有(包括子文件夹)模块'composables/**']},// 发服务器配置devServer: {port: 3001},build: {// 在开发环境和生产环境对es包使用babel进行语法转换transpile: ['element-plus/es']},vite: {css: {preprocessorOptions: {scss: {// 全局引入scss常量,供全局使用additionalData: '@import "assets/scss/constant.scss";'}}}},postcss: {plugins: {'postcss-px-to-viewport': {viewportWidth: 1920 /** 设计稿的视口宽度 */,unitToConvert: 'px' /** 需要转换的单位,默认为"px" */,unitPrecision: 5 /** 单位转换后保留的精度 */,propList: ['*'] /** 能转化为vw的属性列表 */,viewportUnit: 'vw' /** 希望使用的视口单位 */,fontViewportUnit: 'vw' /** 字体使用的视口单位 */,selectorBlackList: [] /**  需要忽略的CSS选择器 */,minPixelValue: 1 /** 设置最小的转换数值 */,mediaQuery: false /** 媒体查询里的单位是否需要转换单位 */,replace: true /** 是否直接更换属性值,而不添加备用属性 */,exclude: undefined /** 忽略某些文件夹下的文件或特定文件 */,include: undefined /**  设置将只有匹配到的文件才会被转换 */,landscape: false /** 是否添加根据 landscapeWidth 生成的媒体查询条件 @media */,landscapeUnit: 'vw' /** 横屏时使用的单位 */,landscapeWidth: undefined /** 横屏时使用的视口宽度 */}}},runtimeConfig: {mode: process.env.VITE_MODE,base_url: process.env.VITE_BASE_URL,app: {mode: process.env.VITE_MODE,base_url: process.env.VITE_BASE_URL,}}
})

客户端请求HTTP模块封装

Nuxt作为一个全栈框架,是有客户端和服务端的概念的。在使用nuxt开发的过程中,很多人有一个误区,认为前端所有的请求都要发送到nuxt服务端,nuxt服务端请求后端接口后返回前端。其实不是这样的,只有需要SSR(服务端渲染)的内容才需要这样做,也就是需要渲染的数据的GET请求才需要这样做,对于增加、删除、修改这一类请求完全可以直接在客户端向后端发请求。这里贴一下我封装HTTP模块(请求库用的是nuxt自带的$fetch)。

/*** @description http模块*/
import { jumpToLogin } from '@/utils/utils'// 接口基地址
const BASE_URL = import.meta.env.VITE_BASE_URL// 环境
const MODE = import.meta.env.VITE_MODE// 生产环境
const MODE_PRODUCTION = 'production'// GET请求方法
const METHOD_GET = 'GET'// 成功状态
const SUCCESS_STATUS_TEXT = 'OK'// 响应类型
const RESPONSE_TYPE = ['blob', 'stream']// 请求拦截器
const requestInterceptor = (config) => {if (config.options.meta?.needAuth) {const { getToken, getUid } = useAuth()const token = getToken()const uid = getUid()const method = config.options.method?.toUpperCase()if (method === METHOD_GET) {const query = config.options.query || {}config.options.query = { ...query, token, uid }} else {const body = config.options.body || {}config.options.body = { ...body, token, uid }}}return config
} // 响应拦截器
const responseInterceptor = (response) => {const res = response.responseif (res.status === 200 &&res.statusText === SUCCESS_STATUS_TEXT &&res._data.data &&RESPONSE_TYPE.includes(res?.type)) {return response}if (MODE !== MODE_PRODUCTION) {console.log(res.url, {code: res._data.code,data: res._data.data,res: res._data,params: response.options,resHeaders: res.headers})}if (res._data.code === 0 || res._data.code === 200) {return response} else if (res._data.code === -50) {// token过期或失效const routeMeta = useRouteMeta()const { removeToken, removeUid } = useAuth()const userInfo = useUserInfo()removeToken()removeUid()// 清空用户信息userInfo.value = {}if (routeMeta.value.needAuth) {// 当前页面需要权限的话,登录失效即跳转登录页jumpToLogin()}return Promise.reject(res._data)}return Promise.reject(res._data)
}  // 错误拦截器
const errorInterceptor = (err) => {return Promise.reject(err.error)
}const httpInstance = $fetch.create({baseURL: BASE_URL,onRequest: requestInterceptor,onResponse: responseInterceptor,onRequestError: errorInterceptor
}) export default httpInstance

api接口管理模块

// /api/common.js/*** @description 项目中公共请求api*/import http from '@/utils/common' // 获取上传临时密钥
export function getCommonList() {return http('/api/common/getList', {method: 'get',meta: {// 标记该接口是否需要权限校验,需要则会在请求拦截器那里做请求拦截相关逻辑处理needAuth: true}})
}

NUXT服务端请求

nuxt服务端接口开发,请求流程:前端 --> nuxt服务端 --> java等服务端接口

// /server/api/list.jsimport { readRawBody, getQuery, getMethod } from 'h3'export default defineEventHandler(async (event) => {// const res = await useFetchData('/user-center/user/getUserInfo', {//     method,//     baseURL: event.context.baseUrl,//     headers: event.context.headers,//     params: getQuery(event),//     body// })const method = getMethod(event).toUpperCase()let bodyif (method !== 'GET') body = await readRawBody(event)const res = await $fetch('/user-center/user/getUserInfo', {method,baseURL: event.context.baseUrl,headers: event.context.headers,params: getQuery(event),body})return res || { userInfo: {} }
})

nuxt服务端中间件处理请求(所有通往nuxt服务端的请求,以及nuxt服务端响应前端过程都会在这里被拦截处理)

import { getHeaders } from 'h3'export default defineEventHandler((event) => {const reqHeaders = getHeaders(event)const ssrHeader = new Headers()const { app } = useRuntimeConfig()ssrHeader.set('cookie', reqHeaders.cookie)// 往nuxt请求注入请求基地址event.context.baseUrl = app.base_url// 往nuxt请求注入请求头event.context.headers = ssrHeader
})

前使用useFetch调用nuxt接口即可

<srcipt setup>
const { data: result } = await useFetch('/api/list')
</script>

路由守卫

nuxt中的路由守卫是在客户端middleware使用defineNuxtRouteMiddleware路由中间件功能实现的。nuxt中设计的客户端的middleware主要是用来拦截路由的,即客户端的路由切换会通过客户端的middleware。如果客户端向nuxt服务端发请求,则请求都会被服务端的middleware拦截处理。客户端的中间件文件名如果使用.global.js,则nuxt会识别为这是一个全局生效的中间件。由于我们这里实现的是全局路由守卫功能,所以文件名命名为default.global.js

// /middleware/default.global.js/*** @description 全局路由守卫*/
import { jumpToLogin } from '@/utils/utils'export default defineNuxtRouteMiddleware((to, from) => {const routeMeta = useRouteMeta()const { getToken, getUid } = useAuth()if (to.meta.needAuth && (!getToken() || !getUid())) {// 需要授权的页面验证是否登录jumpToLogin()return abortNavigation()}// 记录当前要访问页面的元信息(必须置于鉴权逻辑之后),供http模块鉴权之用routeMeta.value = to.meta || {}
})

状态管理

项目中的状态管理我同时使用了nuxt集成的轻量级的useState和vue官方推荐的pinia

使用useState封装的hook直接放到/composables/store文件夹下

// composables/store/base.js/*** @description 项目基础状态管理模块*/import { USER_INFO, ROUTE_META, LOCALE_TYPE } from '@/constants/state'// 用户信息管理
export const useUserInfo = () => useState(USER_INFO, () => {return {}
})// 路由元数据
export const useRouteMeta = () => useState(ROUTE_META, () => {return {}
})// 国际化 - 本地语言类型
export const useLocale = () => useState(LOCALE_TYPE, () => {return 'zh'
})

pinia模块直接放到/composables/pinia文件夹下管理维护。因为nuxt中pinia存在,刷新状态丢失的情况,所以在客户端的plugins中集成了pinia-plugin-persistedstate插件,实现状态数据持久化能力。

// plugins/pinia.js
// https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html/*** @description pinia数据持久化插件*/
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'export default defineNuxtPlugin((nuxtApp) => {nuxtApp.$pinia.use(piniaPluginPersistedstate)
})

国际化

项目中使用的国际化插件是vue-i18n,配置如下

// i18n.config.jsimport en from "assets/lang/en_us.json";
import zh from "assets/lang/zh_cn.json";export default defineI18nConfig(() => ({legacy: false,  // 是否兼容之前fallbackLocale: 'en',  // 区配不到的语言就用enmessages: {en,zh}
}))
// /assets/lang/en_us.json
{"home": "Home"}
// /assets/lang/zh_cn.json
{"home": "主页"}

为了使用方便,我特地在文件夹下封装了一个hook

/*** @description 提供国际化功能的hook*/export function useI18nHook() {const { locale, setLocale } = useI18n()const localeLang = useLocale()// 初始化本地语言类型localeLang.value = localeconst setLocaleLang = (type) => {setLocale(type)localeLang.value = type}return {locale: localeLang,setLocale: setLocaleLang}
}

.vue模版中使用直接如下

<template><div>{{ $t('home') }}
</template>

不仅页面代码需要国际化处理,UI组件库也需要国际化处理,acro-designUI库使用a-config-provider标签在App.vue文件中全局注入本地语言

<template><div><a-config-provider :locale="locale"><NuxtLayout><NuxtPage /></NuxtLayout></a-config-provider></div>
</template><script setup>
import enUS from '@arco-design/web-vue/es/locale/lang/en-us'
import zhCN from '@arco-design/web-vue/es/locale/lang/zh-cn'const locales = {zh: zhCN,en: enUS
}const { locale: langLocale } = useI18nHook()const locale = computed(() => {return locales[langLocale] || zhCN
})useHead({link: [{ rel: 'shortcut icon', href: '/favicon.ico' },{ rel: 'apple-touch-icon', href: '/favicon.ico' }]
})
</script>

其他配置

Layout

// /layout/default.vue<template><div class="layout-container"><Header /><main class="content"><slot /></main><Footer /></div>
</template><style scoped lang="scss">
.layout-container {min-height: 100vh;.content {min-height: calc(100vh - 447px);background: #f7f8fa;}
}
</style>

权限管理HOOK

// /composables/auth.js/*** @description 提供权限管理功能*/
import { TOKEN_KEY, UID_KEY } from '@/constants/auth'const MODE = import.meta.env.VITE_MODEconst DomainMap = {development: 'demo.com',production: 'demo.cn',
}export function useAuth() {const cookieToken = useCookie(TOKEN_KEY, { domain: DomainMap[MODE] }const cookieUID = useCookie(UID_KEY, { domain: DomainMap[MODE] })const getToken = () => {return cookieToken.value}const setToken = (token) => {cookieToken.value = token}const removeToken = () => {cookieToken.value = undefined}const getUid = () => {return cookieUID.value}const setUid = (uid) => {cookieUID.value = uid}const removeUid = () => {cookieUID.value = undefined}return {getToken,setToken,removeToken,getUid,setUid,removeUid,}
}

全局Toast HOOK

toast提示使用的是vue-toast-notification插件

// /composables/toast.js/*** @description 全局用toast提示方法*/
import { useToast as useToastNotification } from 'vue-toast-notification'export function useToast() {return useToastNotification()
}

Eslint配置

配置里继承的@nuxt/eslint-config的规则较为严格,不用也可以去掉

module.exports = {root: true,extends: ['@nuxt/eslint-config'],parserOptions: {ecmaVersion: 'latest'},rules: {'vue/multi-word-component-names': 0/**针对单个单词组件报错的规则关闭 */,'no-undef': 0, /**关闭变量未定义检查 */'no-debugger': 2 /**禁用 debugger  */,'no-dupe-args': 2 /**禁止 function 定义中出现重名参数 */,'no-dupe-keys': 2 /**禁止对象字面量中出现重复的 key */,'no-empty': 1 /**禁止出现空语句块 */,'no-ex-assign': 1 /**禁止对 catch 子句的参数重新赋值 */,'no-extra-boolean-cast': 1 /**禁止不必要的布尔转换 */,'no-extra-parens': 1 /**禁止不必要的括号 */,'no-extra-semi': 1 /**禁止不必要的分号 */,'no-func-assign': 1 /**禁止对 function 声明重新赋值 */,'no-irregular-whitespace': 1 /**禁止在字符串和注释之外不规则的空白 */,'no-unexpected-multiline': 1 /**禁止出现令人困惑的多行表达式 */,'no-unreachable': 1 /**禁止在return、throw、continue 和 break语句之后出现不可达代码 */,'use-isnan': 1 /**要求使用 isNaN() 检查 NaN */,'dot-location': 1 /**强制在点号之前和之后一致的换行 */,'eqeqeq': 2 /**要求使用 === 和 !== */,'no-alert': 1 /**禁用 alert、confirm 和 prompt */,'no-case-declarations': 1 /**不允许在 case 子句中使用词法声明 */,'no-else-return': 1 /**禁止 if 语句中有 return 之后有 else */,'no-empty-function': 1 /**禁止出现空函数 */,'no-eq-null': 1 /**禁止在没有类型检查操作符的情况下与 null 进行比较 */,'no-eval': 1 /**禁用 eval() */,'no-fallthrough': 1 /**禁止 case 语句落空 */,'no-lone-blocks': 1 /**禁用不必要的嵌套块 */,'no-redeclare': 1 /**禁止使用 var 多次声明同一变量 */,'no-self-assign': 1 /**禁止自我赋值 */,'no-self-compare': 1 /**禁止自身比较 */,'no-unmodified-loop-condition': 1 /**禁用一成不变的循环条件 */,'vars-on-top': 1 /**要求所有的 var 声明出现在它们所在的作用域顶部 */,'eol-last': 1 /**强制文件末尾至少保留一行空行强制文件末尾至少保留一行空行 */,}
}

Premitter配置

{"$schema": "https://json.schemastore.org/prettierrc","semi": false,"tabWidth": 2,"singleQuote": true,"printWidth": 100,"trailingComma": "none","useTabs": true
}

package.json

{"name": "app","private": true,"type": "module","scripts": {"build": "nuxt build --dotenv .env.production","build:dev": "nuxt build --dotenv .env.development","serve": "nuxt dev --dotenv .env.local","generate": "nuxt generate","preview": "nuxt preview --dotenv .env.production","postinstall": "nuxt prepare","lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore","format": "prettier"},"dependencies": {"@pinia/nuxt": "^0.5.1","arco-design-nuxt-module": "^0.1.0","blueimp-md5": "^2.19.0","clipboard": "^2.0.11","cos-js-sdk-v5": "^1.8.1","dayjs": "^1.11.11","nuxt": "^3.12.2","pinia": "^2.1.7","pinia-plugin-persistedstate": "^3.2.1","vue": "^3.4.29","vue-i18n": "^9.13.1","vue-router": "^4.3.3","vue-toast-notification": "^3.1.2"},"devDependencies": {"@nuxt/eslint-config": "^0.3.13","@nuxtjs/i18n": "^8.3.1","postcss-aspect-ratio-mini": "^1.1.0","postcss-px-to-viewport": "^1.1.1","prettier": "^3.3.2","sass": "^1.77.6","sass-loader": "^14.2.1"}
}

环境变量

环境变量定义了.local.env.production.env.development.env这里只单列一个

# 环境变量
VITE_MODE=development# 接口基地址
VITE_BASE_URL=https://demo.cn

写在最后

扫码关注作者微信公众号fever code,获取一手技术分享
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高校教师教学质量评估系统-计算机毕业设计源码03344

摘要 在高等教育中&#xff0c;教学质量是培养优秀人才的关键。为了提高教学质量&#xff0c;高校需要建立一套科学、有效的教师教学质量评估系统。本研究采用 SSM技术框架&#xff0c;旨在开发一款高校教师教学质量评估系统。 SSM框架作为一种成熟的Java开发框架&#xff0c;具…

网安小贴士(6)TCP/IP分层

一、前言 1983年&#xff0c;美国国防部决定将TCP/IP作为所有计算机网络的标准协议&#xff0c;这标志着TCP/IP正式成为互联网的基础协议。随着个人计算机的普及和网络技术的发展&#xff0c;TCP/IP模型被广泛应用于各种网络环境中&#xff0c;包括局域网&#xff08;LAN&#…

【图说中国】大江大河你知道哪些?

【图说中国】大江大河你知道哪些&#xff1f; 中国河流 中国是世界上河流最多国家之一&#xff0c;其中流域面积超过1000平方米河流就有1500多条。 主要有长江、黄河、黑龙江、珠江、淮河、海河、辽河、雅鲁藏布江、塔里木河、澜沧江、怒江、闽江、钱塘江、韩江、鸭绿江、图…

Pandas函数详解:案例解析(第25天)

系列文章目录 Pandas函数详解排序函数聚合函数缺失值处理日期函数 文章目录 系列文章目录前言1 索引和列名操作1.1 查看索引和列名1.2 修改索引和列名 2 常用计算函数2.1 排序函数2.2 聚合函数2.3 练习 3 缺失值处理3.1 缺失值概念3.2 加载包含缺失值数据3.3 查看缺失值3.4 缺失…

十五、【源码】给代理对象设置属性

源码地址&#xff1a;https://github.com/spring-projects/spring-framework 仓库地址&#xff1a;https://gitcode.net/qq_42665745/spring/-/tree/15-proxy-set-property 给代理对象设置属性 之前的代码是创建Bean进行判断&#xff0c;要不要进行代理&#xff0c;如果代理…

物联网应用Fast ingest

一、原文路径 Tuning the System Global Area 二、翻译 1、原理 Fast ingest 优化是针对高并发&#xff0c;单行数据的插入这种场景的。比如IOT应用采集&#xff08;很符合国网的用采数据场景&#xff09;。 Fast ingest 使用MEMOPTIMIZE_WRITE 提示来插入数据到 MEMOPTIM…

LVM负载均衡群集

一.群集基础概述 1.群集的类型 &#xff08;1&#xff09;负载均衡的群集&#xff1a;以提高应用系统的响应能力&#xff0c;尽可能处理更多的访问请求&#xff0c;减少延迟为目标&#xff0c;获得高并发的、高负载的整体性能。例如&#xff1a;“DNS轮询”&#xff0c;“应用…

.net 快速开发框架开源

DF.OpenAPI开源系统 前后端分离&#xff0c;开箱即用&#xff0c;java经典功能.net也具备 系统介绍 DF.OpenAPI是基于Admin.NET二开的&#xff0c;是一个开源的多租户后台管理系统。采用前后端分离技术&#xff08;前端使用vue.js&#xff0c;后端使用.net 3~.net6&#xff…

SyntaxError: invalid character in identifier 解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

鸿翼全链智能知识管理,打造大模型时代的企业知识管理新范式

在知识经济的浪潮中&#xff0c;知识已成为企业构筑竞争优势的基石。随着大模型转向应用落地&#xff0c;其强大的语义理解、推理、逻辑、记忆等能力&#xff0c;推动企业知识管理迈向一个“智能涌现”的新时代。 鸿翼大模型KM知识管理系统&#xff0c;植根于非结构化数据治理全…

Mac安装nvm,node

新的Mac安装nvm&#xff0c;最简单的是先安装nvm&#xff0c;再安装node&#xff0c;官网示例代码也是这么整的&#xff0c;如果已经安装了node&#xff0c;不要慌 多几步终端操作可以“没有如果”。分两种情况&#xff1a;1&#xff0c;还没安装node&#xff0c;直接装nvm&…

【C++】初步认识C++

1. 初识C1.1 C概念相关1.2 C发展史及其重要性1.2.1 发展史1.2.2 重要性 2. C关键字3. 命名空间4. 输入和输出 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;【C学习】 1. 初识C 1.1 C概念相关 C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。 【来源】…

ctfshow-web入门-命令执行(web118详解)Linux 内置变量与Bash切片

输入数字和小写字母&#xff0c;回显 evil input 查看源码&#xff0c;发现这里会将提交的参数 code 传给 system 函数 使用 burpsuite 抓包进行单个字符的模糊测试 fuzz&#xff1a; 发现过滤掉了数字和小写字母以及一些符号&#xff0c;下面框起来的部分是可用的 结合题目提…

【C++】开源:命令行解析库CLI11配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍命令行解析库CLI11配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#x…

ETCD概述--使用/特性/架构/原理

ETCD概述 ETCD是一个高度一致的分布式键值存储, 它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据(高可用, 强一致性)​全局的配置服务中心. 本文将介绍其特性、相关操作和常见的应用场景. 如果想了解更多, 请查阅我的技术博客: https://dingyuqi.com 特性 …

新章节:全设备通用调度算法-通讯重构

新章节&#xff1a;全设备通用调度算法-通讯重构 文章目录 新章节&#xff1a;全设备通用调度算法-通讯重构前言一、重构了TCP和UDP通讯二、优化了OPC和OPCUA三、升级了监控客户端四、升级了通讯的图形化其他升级 前言 现在真的很懒也很少写代码了&#xff0c;写代码和更新进度…

webSocket网页通信---使用js模拟多页面实时通信

webSocket是什么 WebSocket是一种先进的网络技术&#xff0c;它提供了一种在单个TCP连接上进行全双工通信的能力。传统的基于HTTP的通信是单向的&#xff0c;即客户端发起请求&#xff0c;服务器响应请求&#xff0c;然后连接关闭。但是&#xff0c;WebSocket允许服务器和客户端…

欧盟,又出了新规-通用充电器新规通用充電器的 RED 修正案如何办理?

欧盟&#xff0c;又出了新规-通用充电器新规通用充電器的 RED 修正案如何办理&#xff1f; 欧盟新规委员会发布《通用充电器指令》指南通用充電器的 RED 修正案办理流程&#xff1a; 2024年5月7日&#xff0c;欧盟委员会发布《通用充电器指令》指南&#xff0c;修订了《无线…

Linux之进程控制(下)

目录 进程替换的概念 进程替换的函数 execl​编辑 execlp execle execv execvp execve 上期&#xff0c;我们学习了进程创建&#xff0c;进程终止和进程等待&#xff0c;今天我们要学习的是进程控制中相对重要的板块------进程替换。 进程替换的概念 在进程创建时&…

【 香橙派 AIpro评测】大语言模型实战教程:香橙派 AIpro部署LLMS大模型实站(保姆级教学)

引言 OrangePi AIpro 这块板子作为业界首款基于昇腾深度研发的AI开发板&#xff0c;一经发布本博主就火速去关注了&#xff0c;其配备的 8/20TOPS澎湃算力是目前开发板市场中所具备的最大算力&#xff0c;可谓是让我非常眼馋啊&#xff01;这么好的板子那必须拿来用用&#xff…