微前端 - qiankun


qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。

本文主要记录下如何接入 qiankun 微前端。主应用使用 vue2,子应用使用 vue3、react。

一、主应用
主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可。

1、创建项目

// @vue/cli 5.0.4
npm install @vue/cli -g
 
vue create main-vue
主应用选择 vue2.x 版本。 具体创建步骤,便不在此一一叙述。

项目创建之后,配置路由,页面布局等。整体效果如下图。

 

2、安装 qiankun

npm i qiankun -S


3、 注册微应用并启动

新建微应用子列表文件 micros/app.js

// src/micros/app.js
// 子应用列表
const apps = [
  {
    name: 'vue2-app', // 子应用app name 推荐与子应用的package的name一致
    entry: '//localhost:8081/', // 子应用的入口地址,就是你子应用运行起来的地址
    container: '#micro-container', // 挂载子应用内容的dom节点 `# + dom id`【见上面app.vue】
    activeRule: '/vue2App' // 子应用的路由前缀
  },
  {
    name: 'vue3-app',
    entry: '//localhost:8082/',
    container: '#micro-container',
    activeRule: '/vue3App'
  },
  {
    name: 'react-app',
    entry: '//localhost:8083/',
    container: '#micro-container',
    activeRule: '/react'
  }
]
 
export default apps

注册微应用

// src/micros/index.js
import { addGlobalUncaughtErrorHandler, registerMicroApps, start} from 'qiankun'
// 微应用的信息
import apps from './app'
 
/**
 * 注册微应用
 * 第一个参数 - 微应用的注册信息
 * 第二个参数 - 全局生命周期钩子
 */
registerMicroApps(apps, {
  // qiankun 生命周期钩子 - 微应用加载前
  beforeLoad: (app) => {
    // 加载微应用前,加载进度条
    console.log('before load=====', app.name)
    return Promise.resolve()
  },
  // qiankun 生命周期钩子 - 微应用挂载后
  afterMount: (app) => {
    // 加载微应用前,进度条加载完成
    console.log('after mount=====', app.name)
    return Promise.resolve()
  }
}
)
 
/**
 * 添加全局的未捕获异常处理器
 */
addGlobalUncaughtErrorHandler((event) => {
  console.error(event)
  const { message: msg } = event
  if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
    console.error('微应用加载失败,请检查应用是否可运行')
  }
})
 
// 导出 qiankun 的启动函数
export default start

配置主应用路由

// src/router/index.js
 
import Vue from 'vue'
import VueRouter from 'vue-router'
 
Vue.use(VueRouter)
 
const routes = [
  {
    path: '/',
    name: 'home',
    component: () => import('@/components/Home.vue'),
    children: [{
      path: '/',
      name: 'hello',
      component: () => import('@/views/HomeView.vue')
    },{
      path: '/vue2App',
      name: 'vue2App'
    }, {
      path: '/vue3App',
      name: 'vue3App'
    }, {
      path: '/vue3App/list',
      name: 'vueAppList'
    }, {
      path: '/react',
      name: 'react'
    }]
  }
]
 
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
 
export default router

页面设置子应用的挂载节点

<template>
  <div class="wrapper">
    <MyHeader></MyHeader>
    <el-container class="content">
      <el-aside width="200px">
        <MySider></MySider>
      </el-aside>
      <el-main>
        <router-view></router-view>
        <!-- 挂载子应用节点 -->
        <div id="micro-container"></div>
      </el-main>
    </el-container>
  </div>
</template>
 
<script>
  import MyHeader from './Header.vue'
  import MySider from './Sider.vue'
 
  export default {
    name: 'MyHome',
    components: {
      MyHeader,
      MySider
    },
    data() {
      return {
 
      }
    }
  }
</script>
 
<style lang="less">
  .content {
    height: calc(100% - 50px);
  }
</style>

在 main.js 中引入并启动 qiankun

// src/main.js
 
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import '../src/assets/style/reset.less'
import './plugins/element.js'
 
import start from '@/micros'
// 启动
start()
 
Vue.config.productionTip = false
 
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

二、微应用
微应用分为有 webpack 构建和无 webpack 构建项目,有 webpack 的微应用(主要是指 Vue、React、Angular)需要做的事情有:

新增 public-path.js 文件,用于修改运行时的 publicPath。
微应用建议使用 history 模式的路由,需要设置路由 base,值和它的 activeRule 是一样的。
在入口文件最顶部引入 public-path.js,修改并导出三个生命周期函数。
修改 webpack 打包,允许开发环境跨域和 umd 打包。
无 webpack 构建的微应用直接将 lifecycles 挂载到 window 上即可。

微应用无需安装 qiankun。

三、vue2-app 微应用
 1、创建项目

// vue-cli 2.9.6
npm install vue-cli -g
 
npm install webpack-cli -g
 
npm init webpack vue-app
2、在 src 目录新增 public-path.js

// src/public-path.js
if(window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
 

修改路由文件,建议使用history 模式的路由,并设置路由 base,值和它的 activeRule 是一样的。

// src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
 
Vue.use(Router)
 
export default new Router({
  mode: 'history',
  base: window.__POWERED_BY_QIANKUN__ ? "/vue2App" : "/",
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。并导出三个生命周期函数。

// src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import "./public-path";
 
Vue.config.productionTip = false
 
// 定义一个Vue实例
let instance = null
// 渲染方法
function render(props = {}) {
  const { container } = props
  instance = new Vue({
    router,
    render: (h) => h(App)
  }).$mount(container ? container.querySelector('#app'): '#app')
}
// 独立运行时
if(!window.__POWERED_BY_QIANKUN__) {
  render()
}
//暴露主应用生命周期钩子
/**
 * bootstrap : 在微应用初始化的时候调用一次,之后的生命周期里不再调用
 */
export async function bootstrap() {
  console.log('vue2-app bootstraped');
}
/**
 * mount : 在应用每次进入时调用
 */
export async function mount(props) {
  console.log('vue2-app mount', props);
  render(props);
}
/**
 * unmount :应用每次 切出/卸载 均会调用
 */
export async function unmount() {
  console.log("vue2-app unmount")
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
}

修改 webpack 打包,允许开发环境跨域和 umd 打包。

// build/webpack.base.conf.js
'use strict'
const config = require('../config')
const APP_NAME = require('../package.json').name
 
module.exports = {
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath,
    // 微应用的包名,这里与主应用中注册的微应用名称一致
    library: APP_NAME,
    // 将你的 library 暴露为所有的模块定义下都可运行的方式
    libraryTarget: "umd",
    // 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
    jsonpFunction: `webpackJsonp_${APP_NAME}`,
  },
  ...
}

// build/webpack.dev.conf.js
const devWebpackConfig = merge(baseWebpackConfig, {
   ...
   devServer: {
     ...
     // 关闭主机检查,使微应用可以被 fetch
     disableHostCheck: true,
     // 配置跨域请求头,解决开发环境的跨域问题
     headers: {
       "Access-Control-Allow-Origin": "*",
     }
   }
})
运行效果如下:

 

四、vue3-app 微应用
1、创建项目

// @vue/cli 5.0.4
npm install @vue/cli -g
 
vue create vue3-app


 2、在 src 目录新增 public-path.ts

 

// src/public-path.ts
if ((window as any).__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}


修改路由文件。

// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
 
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "home",
    component: () => import("@/components/Home.vue"),
    children: [
      {
        path: "/",
        name: "index",
        component: () => import("../views/HomeView.vue"),
      },
      {
        path: "/list",
        name: "list",
        component: () => import("../views/AboutView.vue"),
      },
    ],
  },
];
 
const router = createRouter({
  history: createWebHistory(
    window.__POWERED_BY_QIANKUN__ ? "/vue3App" : process.env.BASE_URL
  ),
  routes,
});
 
export default router;

 入口文件 main.ts 修改

// src/main.ts
import Vue, { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import "./public-path.ts";
 
// 定义一个Vue实例
let instance: Vue.App<Element>;
// 需要定义该接口,否则`/src/router/index.ts`无法使用`Window.__POWERED_BY_QIANKUN__`
declare global {
  interface Window {
    __POWERED_BY_QIANKUN__?: string;
  }
}
interface IRenderProps {
  container: Element | string;
}
 
// 渲染方法
function render(props: IRenderProps) {
  const { container } = props;
  instance = createApp(App);
  instance
    .use(store)
    .use(router)
    .mount(
      container instanceof Element
        ? (container.querySelector("#app") as Element)
        : (container as string)
    );
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render({ container: "#app" });
}
 
//暴露主应用生命周期钩子
/**
 * bootstrap : 在微应用初始化的时候调用一次,之后的生命周期里不再调用
 */
export async function bootstrap() {
  console.log("vue3-app bootstraped");
}
 
/**
 * mount : 在应用每次进入时调用
 */
export async function mount(props: any) {
  console.log("mount vue3-app", props);
  render(props);
}
 
/**
 * unmount :应用每次 切出/卸载 均会调用
 */
export async function unmount() {
  console.log("unmount vue3-app app");
  instance.unmount();
}

 修改 webpack 打包,允许开发环境跨域和 umd 打包。

注意:webpack5 中 jsonpFunction 修改为 chunkLoadingGlobal

// vue.config.js
const path = require("path");
 
const APP_NAME = require("./package.json").name;
 
function resolve(dir) {
  return path.join(__dirname, dir);
}
 
module.exports = {
  outputDir: "dist",
  assetsDir: "static",
  filenameHashing: true,
  devServer: {
    host: "localhost",
    hot: true,
    port: 8082,
    client: {
      overlay: {
        errors: true,
        warnings: false,
      },
    },
    // 配置跨域请求头,解决开发环境的跨域问题
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
  },
  // 自定义webpack配置
  configureWebpack: {
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
    output: {
      // 把子应用打包成 umd 库格式
      // // 微应用的包名,这里与主应用中注册的微应用名称一致
      library: APP_NAME,
      // 将你的 library 暴露为所有的模块定义下都可运行的方式
      libraryTarget: "umd",
      // 按需加载相关,设置为 webpackJsonp_微应用名称 即可
      chunkLoadingGlobal: `webpackJsonp_${APP_NAME}`,
    },
  },
};

运行效果如下:

 

五、react-app 微应用
1、创建项目,以 create-react-app 生成的 react 17 项目为例,搭配 react-router-dom 6.x。

npx create-react-app react-app --template typescript
 
npm i react-router-dom


在根目录下添加 .env 文件,设置项目监听的端口

// react-app/.env
PORT=8083
BROWSER=none
2⃣️、新建 public-path.ts

// src/public-path.ts
if ((window as any).__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}


如上面代码报错,可以通过补充定义进行修复。以下代码最好放到全局引入的 TypeScript 定义文件中。

interface Window {
  __POWERED_BY_QIANKUN__?: string
  __INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string
}
 
declare let __webpack_public_path__: string | undefined


设置 history 模式路由的 base

// src/App.tsx
import React from 'react';
import { Routes, Route, BrowserRouter} from 'react-router-dom'
import './App.css';
import Home from './components/home';
 
function App() {
  return (
    <div>
      {/* 设置路由命名空间 */}
      <BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react' : '/'}>
        <Routes>
          <Route path="/" element={<Home />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}
 
export default App;

修改入口文件 index.tsx

// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './types.d.ts'
import "./public-path";
 
/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log('react-app bootstraped');
}
/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props: any) {
  console.log('react-app mount');
  ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props: any) {
  console.log('react-app unmount');
  ReactDOM.unmountComponentAtNode(props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props: any) {
  console.log('react-app update props', props);
}
 
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
 
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

修改 webpack 配置,安装插件 react-app-rewired

npm install react-app-rewired -D
修改 package.json

// react-app/package.json
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-app-rewired eject"
}


在 react-app-rewired 配置完成后,新建 config-overrides.js 文件来配置 webpack。

// react-app/config-overrides.js
const path = require("path");
const APP_NAME = require("./package.json").name;
 
module.exports = {
  webpack: (config) => {
    // 微应用的包名,这里与主应用中注册的微应用名称一致
    config.output.library = APP_NAME;
    // 将你的 library 暴露为所有的模块定义下都可运行的方式
    config.output.libraryTarget = "umd";
    // 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可
    config.output.chunkLoadingGlobal = `webpackJsonp_${APP_NAME}`;
    config.output.globalObject = 'window';
    config.output.publicPath = `//localhost:${process.env.PORT}/`;
 
    config.resolve.alias = {
      ...config.resolve.alias,
      "@": path.resolve(__dirname, "src"),
    };
    return config;
  },
 
  devServer: function (configFunction) {
    return function (proxy, allowedHost) {
      const config = configFunction(proxy, allowedHost);
      // 关闭主机检查,使微应用可以被 fetch
      // config.disableHostCheck = true;
      config.allowedHosts = "all";
      // 配置跨域请求头,解决开发环境的跨域问题
      config.headers = {
        "Access-Control-Allow-Origin": "*",
      };
      // 配置 history 模式
      config.historyApiFallback = true;
 
      return config;
    };
  },
};

3、运行效果如下

 


原文链接:https://blog.csdn.net/lhz_333/article/details/123767105

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nest(2):Nest 应用目录结构和脚手架命令介绍

Nest 应用目录结构和脚手架命令介绍 在正式使用 NestJS 进行开发之前&#xff0c;先来了解下 Nest 应用的目录结构&#xff0c;和一些常用的脚本命令。 工程目录 下面是使用 nest/cli 创建的 Nest 项目的目录结构。 上篇文章中介绍了 src 目录以及目录下各个文件的作用。下面…

时序预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机时间序列预测

时序预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机时间序列预测 目录 时序预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SA-ELM模拟退火算法优化极限学习机时间序列预测 程序设计 完整…

【已解决】Please install Node.js and npm before continuing installation.

给juopyter lab安装插件时报这个错 原因是&#xff0c;conda本身有nodejs&#xff0c;但是版本很低&#xff0c;只有0.几 所以需要卸载掉原来的nodejs&#xff0c;重新安装10版本以上的nodejs # 卸载命令 pip uninstall nodejs # 安装命令 conda install nodejs14.7.0 -c cond…

SOPC之NIOS Ⅱ实现电机转速PID控制

通过FPGA开发板上的NIOS Ⅱ搭建电机控制的硬件平台&#xff0c;包括电机正反转、编码器的读取&#xff0c;再通过软件部分实现PID算法对电机速度进行控制&#xff0c;使其能够渐近设定的编码器目标值。 一、PID算法 PID算法&#xff08;Proportional-Integral-Derivative Algo…

Java代码审计13之URLDNS链

文章目录 1、简介urldns链2、hashmap与url类的分析2.1、Hashmap类readObject方法的跟进2.2、URL类hashcode方法的跟进2.3、InetAddress类的getByName方法 3、整个链路的分析3.1、整理上述的思路3.2、一些疑问的测试3.3、hashmap的put方法分析3.4、反射3.5、整个代码 4、补充说明…

深度学习基本理论上篇:(MLP/激活函数/softmax/损失函数/梯度/梯度下降/学习率/反向传播)、深度学习面试

1、MLP、FCN、DNN三者的关系&#xff1f; 多层感知器MLP&#xff0c;全连接网络&#xff0c;DNN三者的关系&#xff1f;三者是不是同一个概念&#xff1f; FCN&#xff1a;Fully Connected Neural Network&#xff0c;全连接神经网络&#xff0c;也称为密集连接神经网络&#…

小白到运维工程师自学之路 第七十八集 (安装Jenkins)

一、环境概述 随着软件开发需求及复杂度的不断提高&#xff0c;团队开发成员之间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题。Jenkins自动化部署可以解决集成、测试、部署等重复性的工作&#xff0c;工具集成的效率明显高于人工操作&#xf…

【私有GPT】CHATGLM-6B部署教程

【私有GPT】CHATGLM-6B部署教程 CHATGLM-6B是什么&#xff1f; ChatGLM-6B是清华大学知识工程和数据挖掘小组&#xff08;Knowledge Engineering Group (KEG) & Data Mining at Tsinghua University&#xff09;发布的一个开源的对话机器人。根据官方介绍&#xff0c;这是…

【AWS】创建IAM用户;无法登录IAM用户怎么办?错误提示:您的身份验证信息错误,请重试(已解决)

目录 0.背景问题分析 1.解决步骤 0.背景问题分析 windows 11 &#xff0c;64位 我的问题情景&#xff1a; 首先我创建了aws的账户&#xff0c;并且可以用ROOT用户登录&#xff0c;但是在登录时选择IAM用户&#xff0c;输入ROOT的名字和密码&#xff0c;就会提示【您的身份验证…

SQL 盲注

问题描述&#xff1a; 解决方案&#xff1a; 通过建立过滤器方法 添加拦截器&#xff1a; web.xml 文件配置拦截器 <filter><filter-name>sqlFilter</filter-name><filter-class>com.fh.filter.SqlFilter</filter-class></filter> pack…

【Python机器学习】实验15 将Lenet5应用于Cifar10数据集(PyTorch实现)

文章目录 CIFAR10数据集介绍1. 数据的下载2.修改模型与前面的参数设置保持一致3. 新建模型4. 从数据集中分批量读取数据5. 定义损失函数6. 定义优化器7. 开始训练8.测试模型 9. 手写体图片的可视化10. 多幅图片的可视化 思考题11. 读取测试集的图片预测值&#xff08;神经网络的…

GPT-3.5——从 人工智障 到 大人工智障

有人说&#xff0c;GPT是从人工智障到人工智能的蜕变&#xff0c;但是。。。 我认为&#xff0c;GPT是从 人工智障 到 大人工智障 的退化。。。 从 人工智障 到 大人工智障 GPT-3.5学术介绍No.1---- 西红柿炒钢丝球基本信息详细制作方法材料步骤 幕后花絮 No.2---- 顶尖数学家…

vue3学习笔记

1.创建项目 2. 3.setup 4. 5. 6. 7.生命周期函数 8. 9. 10. 11. 12.pinia

TCP拥塞控制详解 | 6. 主动队列管理

网络传输问题本质上是对网络资源的共享和复用问题&#xff0c;因此拥塞控制是网络工程领域的核心问题之一&#xff0c;并且随着互联网和数据中心流量的爆炸式增长&#xff0c;相关算法和机制出现了很多创新&#xff0c;本系列是免费电子书《TCP Congestion Control: A Systems …

QT的工程文件认识

目录 1、QT介绍 2、QT的特点 3、QT模块 3.1基本模块 3.2扩展模块 4、QT工程创建 1.选择应用的窗体格式 2.设置工程的名称与路径 3.设置类名 4.选择编译器 5、QT 工程解析 xxx.pro 工程配置 xxx.h 头文件 main.cpp 主函数 xxx.cpp 文件 6、纯手工创建一个QT 工程…

从Web 2.0到Web 3.0,互联网有哪些变革?

文章目录 Web 2.0时代&#xff1a;用户参与和社交互动Web 3.0时代&#xff1a;语义化和智能化影响和展望 &#x1f389;欢迎来到Java学习路线专栏~从Web 2.0到Web 3.0&#xff0c;互联网有哪些变革&#xff1f; ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#x…

springboot多模块打包方式

明确子父模块结构 父目录是带modules 大致结构如下&#xff1a; <modules><module>ruoyi-admin</module><module>ruoyi-framework</module><module>ruoyi-system</module><module>ruoyi-quartz</module><module>…

解决出海痛点:亚马逊云科技助力智能涂鸦,实现设备互联互通

今年6月&#xff0c;《财富》&#xff08;中文版&#xff09;发布“2023年值得关注的中国出海主力”盘点&#xff0c;在七个赛道中聚焦不断开拓新领域、影响力与日俱增的出海企业。涂鸦智能顺利入选&#xff0c;作为一家全球化公司&#xff0c;相比于产品直接到海外销售的传统出…

android cocoscreator 检测模拟器还是真机

转载至 一行代码帮你检测Android模拟器 具体原理看原博主文章&#xff0c;这里只讲cocoscreator3.6的安卓工程怎么使用 1.新建一个com.lahm.library包&#xff0c;和com.cocos.game同目录&#xff0c;如图示 那四个文件的代码如下&#xff1a; EmulatorCheckUtil类&#…

PostgreSQL中的密码验证方法

假设您想在客户端/服务器协议中实现密码身份验证方法。 您将如何做到这一点以及可能出现的问题是什么&#xff1f; 以下是 PostgreSQL 中如何完成此操作的故事。 password 一开始&#xff0c;PostgreSQL 只有 pg_hba.conf 中现在称为“password”的方法。 这是你能想象到的最…