快速構建Web應用,從零學習React後臺項目模版

来源:https://www.cnblogs.com/yunzhishu/archive/2022/04/01/16086882.html
-Advertisement-
Play Games

我們可以通過公共倉庫拉取鏡像使用,但是,有些時候公共倉庫拉取的鏡像並不符合我們的需求。儘管已經從繁瑣的部署工作中解放出來了,但是在實際開發時,我們可能希望鏡像包含整個項目的完整環境,在其他機器上拉取打包完整的鏡像,直接運行即可。 ​ Docker 支持自己構建鏡像,還支持將自己構建的鏡像上傳到公共倉 ...


想要快速構建實際應用,離不開一個好的應用模版,React作為大廠出品工具,有著穩定性和可維護性的保障,同時可以使用相關的全套全家桶(React + React-router + Axios + Mobx + Antd)進行連貫敏捷開發,本文將從如何在雲開發平臺創建項目應用模版,基於應用模版創建《後臺管理》項目,以及上傳並且通過雲平臺將項目上線部署應用,為項目開發提供更加便捷的操作環境。

一 、通過雲開發平臺快速創建初始化應用

1.創建相關應用模版請參考鏈接:https://developer.aliyun.com/article/878171?spm=a2c6h.12873581.0.dArticle878171.c61253e8nVBtAv

2.完成創建後就可以在github中查看到新增的react倉庫

二 、本地編寫《後臺管理》項目

1.將應用模版克隆到本地

• 首先假定你已經安裝了Git、node,沒有安裝請移步node官網進行安裝。克隆項目:

git clone + 項目地址

• 進入項目文件

cd create-react-app

• 切換到feature/1.0.0 分支上

git checkout feature/1.0.0

• 使用一下命令全局安裝 React :

npm install -g create-react-app

• 安裝依賴包

npm install

• 啟動服務

npm start

這裡打開瀏覽器3000埠,並出現預設頁面。

2.架構與效果預覽

• 《後臺管理》項目架構

• 效果預覽

3.初始化項目

• 初始化package.json

npm init

• 安裝webpack

npm add -D webpack webpack-cli webpack-merge

項目中使用的Webpack版本是^5.10.0,Webpack4.0 打包構建做了很多預設的優化配置,不少配置項無需配置或更改。
比如:針對開發模式的加快打包速度,合併chunk; 針對生產模式的代碼壓縮,減少打包體積等。

// 一部分預設配置  
optimization: {
		removeAvailableModules: true, // 刪除已解決的chunk (預設 true)
		removeEmptyChunks: true, // 刪除空的chunks (預設 true)
		mergeDuplicateChunks: true // 合併重覆的chunk (預設 true)
	}

 // 針對生產環境預設配置
	optimization: {
		sideEffects:true, //配合tree shaking
		splitChunks: {...}, //拆包
		namedModules: false, // namedChunks:false 不啟用chunk命名,預設自增id
		minimize: true, // 代碼壓縮
	}

根據開發環境/生產環境 區分webpack配置非常有必要,可以加快開發環境的打包速度,有時候遇到開發環境打包過慢,可以排查下是否配置有誤(比如開發環境開啟了代碼壓縮等)。
項目中配合webpack-merge根據開發環境/生產環境進行拆分配置:

Webpack4.0發佈已經很長時間了,相信基本上項目都已遷移至4.0,在這裡就不多贅述了。
• 配置Html模版
安裝:

npm add -D html-webpack-plugin

配置:

const srcDir = path.join(__dirname, "../src");
plugins: [
	new HtmlWebpackPlugin({
		template: `${srcDir}/index.html`
 })
]

• 配置本地服務及熱更新
安裝:

npm add -D webpack-dev-server clean-webpack-plugin

開發環境利用webpack-dev-server搭建本地 web server,並啟用模塊熱更新(HMR)。
為方便開發調試,轉發代理請求(本例中配合axios封裝 轉發介面到easy-mock線上平臺)
配置:

mode: "development", // 開發模式
devServer: { // 本地服務配置
	port: 9000,
	hot: true,
	open: false,
	historyApiFallback: true,
	compress: true,
	proxy: { // 代理
		"/testapi": {
			target:
			"https://www.easy-mock.com/mock/5dff0acd5b188e66c6e07329/react-template",
			 changeOrigin: true,
			 secure: false,
			 pathRewrite: { "^/testapi": "" }
		}
	}
},
plugins: [
	new webpack.NamedModulesPlugin(),
	new webpack.HotModuleReplacementPlugin()
],

• 配置Babel
安裝:

npm add -D babel-loader @babel/core @babel/plugin-transform-runtime 
 @babel/preset-env @babel/preset-react  babel-plugin-import
 @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators

Webpack中Babel配置,是比較重要的一環。關係著ES6語法、React jsx、Mobx等語法經過打包後能否正常運行。
其中:
@babel/preset-react轉換React jsx語法;
@babel/plugin-proposal-class-properties 轉換 Class語法;
@babel/plugin-proposal-decorators 轉換 Mobx 等更高級的語法;
babel-plugin-import 配合實現React組件的按需載入;
這裡需要註意Babel7.0 相較於Babel6.0的區別。
配置:

module: {
	rules: [
		{
			test: /\.(js|jsx)$/,
			include: [srcDir],
			use: ["babel-loader?cacheDirectory=true"]
		},
	]
}
• .babelrc 文件配置
{
	"presets": [
		"@babel/preset-env",
		"@babel/preset-react"
	],
	"plugins": [
		"@babel/transform-runtime",
		[
			"@babel/plugin-proposal-decorators",
			{
				"legacy": true
			}
		],
		["@babel/plugin-proposal-class-properties", { "loose": true }],
		[
			"import",
			{
				"libraryName": "antd",
				"libraryDirectory": "es",
				"style": "css" // `style: true` 會載入 less 文件
			}
		]
	]
}

• 處理Less樣式和圖片等資源
安裝:

npm add -D less less-loader style-loader css-loader url-loader 
mini-css-extract-plugin postcss-loader autoprefixer

其中:
less-loader、style-loader、css-loader處理載入less、css文件;
postcss-loader、autoprefixer處理css樣式瀏覽器首碼相容;
url-loader處理圖片、字體文件等資源;
mini-css-extract-plugin 分離css成單獨的文件;
配置:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...
module: {
	rules: [
		{
			test: /\.less$/,
			use: [
				devMode ? "style-loader" : MiniCssExtractPlugin.loader,
				"css-loader",
				"postcss-loader",
				"less-loader"
			]
		},
		{
			test: /\.css$/,
			use: [
				devMode ? "style-loader" : MiniCssExtractPlugin.loader,
				"css-loader",
				"postcss-loader"
			]
		},
		{
			test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
			use: ["url-loader"],
			include: [srcDir]
		},
		{
			test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
			use: ["url-loader"],
			include: [srcDir]
		},
		{
			test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
			use: ["url-loader"],
			include: [srcDir]
		}
	]
},
plugins: [
	new MiniCssExtractPlugin({
		filename: "[name].[contenthash:8].css",
		chunkFilename: "chunk/[id].[contenthash:8].css"
	}),
	],

配置postcss .postcssrc.js 文件

// .postcssrc.js
module.exports = {
	plugins: {
		autoprefixer: {}
	}
};
// package.json中配置相容瀏覽器
"browserslist": [
	"> 1%",
	"last 2 versions",
	"not ie <= 10"
]

• 利用happypack多線程打包
安裝:

npm add -D happypack

配置:

const os = require("os");
const HappyPack = require("happypack");
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module: {
	rules: [
		{
			test: /\.(js|jsx)$/,
			include: [srcDir],
			exclude: /(node_modules|bower_components)/,
			use: ["happypack/loader?id=happybabel"]
		},
	]
},
plugins: [
	//開啟 happypack 的線程池
	new HappyPack({
		id: "happybabel",
		loaders: ["babel-loader?cacheDirectory=true"],
		threadPool: happyThreadPool,
		cache: true,
		verbose: true
	}),
]

• 生產環境 拆分模塊
根據實際項目情況拆分模塊,配合非同步載入,防止單個文件過大。

optimization: {
		runtimeChunk: {
			name: "manifest"
		},
		splitChunks: {
			chunks: "all", //預設只作用於非同步模塊,為`all`時對所有模塊生效,`initial`對同步模塊有效
			cacheGroups: {
				dll: {
					test: /[\\/]node_modules[\\/](react|react-dom|react-dom-router|babel-polyfill|mobx|mobx-react|mobx-react-dom|antd|@ant-design)/,
					minChunks: 1,
					priority: 2,
					name: "dll"
				},
				codeMirror: {
					test: /[\\/]node_modules[\\/](react-codemirror|codemirror)/,
					minChunks: 1,
					priority: 2,
					name: "codemirror"
				},
				vendors: {
					test: /[\\/]node_modules[\\/]/,
					minChunks: 1,
					priority: 1,
					name: "vendors"
				}
			}
		}
	}

• 其他配置
引入 ESLint 與 Prettier 配合,規範化團隊項目代碼開發,統一代碼風格。

npm add -D prettier babel-eslint eslint eslint-loader eslint-config-airbnb 
eslint-config-prettier eslint-plugin-babel eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react

具體配置詳見 /build目錄https://github.com/now1then/react-web-pro/tree/master/build
• npm scripts
package.json 文件

{
	...
	"scripts": {
		"start": "webpack-dev-server --color --inline --progress --config build/webpack.dev.js", //
		"build": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js",
		"build:report": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js",
		"build:watch": "NODE_ENV=production webpack --progress --config ./build/webpack.prod.js"
	},
	...
}

命令行運行:
// 命令行執行
// 運行開發環境;

npm start

// 生產環境打包壓縮;

npm build

// 圖形化分析打包文件大小;

npm build:report

// 方便排查生產環境打包後文件的錯誤信息(文件source map);

npm build:watch

其中 build:report 、build:watch 能夠實現功能,是在build/webpack.prod.js 中有如下代碼:
// 方便排查生產環境打包後文件的錯誤信息(文件source map)

if (process.env.npm_lifecycle_event == "build:watch") {
	config = merge(config, {
		devtool: "cheap-source-map"
	});
}
// 圖形化分析打包文件大小
if (process.env.npm_lifecycle_event === "build:report") {
	const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
		.BundleAnalyzerPlugin;
	config.plugins.push(new BundleAnalyzerPlugin());
}

• 項目代碼架構

npm add react react-dom react-router-dom mobx mobx-react mobx-react-router 
axios antd moment

4.函數化Hooks

當前React版本已更新到16.12,Hooks 完全應該成為 React 使用的主流。本項目中將完全擁抱Hook,一般不再用 class 來實現組件。
以下為部分實現代碼(可暫忽略mobx的使用):

import React, { useState, useEffect, useContext } from 'react';
import { observer } from 'mobx-react';
import { Button } from 'antd';
import Store from './store';
import './style.less';
const HomePage = () => {
	// useContext 訂閱mobx數據
	const pageStore = useContext(Store);
	// useState state狀態
	const [num, setNum] = useState(0);
	// useEffect副作用
	useEffect(() => {
		pageStore.qryTableDate();
	}, []);
	return (
		<div className="page-home page-content">
			<h2>{pageStore.pageTitle}</h2>
			<div>
				<span>num值:{num}</span>
				<Button type="primary" size="small" style={{ marginLeft: 10 }}
					onClick={() => setNum(num + 1)}
				>+1</Button>
			</div>
		</div>
	);
};
export default observer(HomePage);

5.Router路由配置

項目是單頁應用,路由配置一般分為約定式動態路由和集中配置式路由。
在 React 的世界里,直接採用成熟的react-router工具管理頁面路由。我們現在說到react-router,基本上都是在說 react-router 的第4版之後的版本,當前的最新版本已經更新到5.1.x了。
當前react-router支持動態路由,完全用React組件來實現路由,在渲染過程中動態設置路由規則,匹配命中規則載入對應頁面組件。
本項目採用集中配置式路由(方便路由鑒權、從服務端介面獲取菜單路由配置等),同時兼顧方便地設置側邊菜單欄。 當然為簡單起見,項目中讀取本地靜態菜單配置,也暫未引入路由鑒權。

6.靜態路由配置 src/routes/config.js :

import React, { lazy } from "react";
import BasicLayout from "@/layouts/BasicLayout";
import BlankLayout from "@/layouts/BlankLayout";
const config = [
	{
		path: "/",
		component: BlankLayout, // 空白頁佈局
		childRoutes: [ // 子菜單路由
			{ 
				path: "/login", // 路由路徑
				name: "登錄頁", // 菜單名稱 (不設置,則不展示在菜單欄中)
				icon: "setting", // 菜單圖標
				component: lazy(() => import("@/pages/Login")) // 懶載入 路由組件
			},
			// login等沒有菜單導航欄等基本佈局的頁面, 要放在基本佈局BasicLayout之前。
			{
				path: "/",
				component: BasicLayout, // 基本佈局框架
				childRoutes: [
					{
						path: "/welcome",
						name: "歡迎頁",
						icon: "smile",
						component: lazy(() => import("@/pages/Welcome"))
					},
					{... /* 其他 */}, 
					{ path: "/", exact: true, redirect: "/welcome" },
					{ path: "*", exact: true, redirect: "/exception/404" }
				]
			}
		]
	}
];
export default config;

上面是靜態路由的一部分配置,
註意:中會用包裹,會匹配命中的第一個。"/login"等沒有菜單導航欄等基本佈局的頁面, 要放在基本佈局BasicLayout之前。
利用和React.lazy()實現頁面組件懶載入。

7.路由組建渲染 src/routes/AppRouter.js :

import React, { lazy, Suspense } from "react";
import LoadingPage from "@/components/LoadingPage";
import {
	HashRouter as Router,
	Route,
	Switch,
	Redirect
} from "react-router-dom";
import config from "./config";
const renderRoutes = routes => {
	if (!Array.isArray(routes)) {
		return null;
	}
	return (
		<Switch>
			{routes.map((route, index) => {
				if (route.redirect) {
					return (
						<Redirect
							key={route.path || index}
							exact={route.exact}
							strict={route.strict}
							from={route.path}
							to={route.redirect}
						/>
					);
				}
				return (
					<Route
						key={route.path || index}
						path={route.path}
						exact={route.exact}
						strict={route.strict}
						render={() => {
							const renderChildRoutes = renderRoutes(route.childRoutes);
							if (route.component) {
								return (
									<Suspense fallback={<LoadingPage />}>
										<route.component route={route}>
											{renderChildRoutes}
										</route.component>
									</Suspense>
								);
							}
							return renderChildRoutes;
						}}
					/>
				);
			})}
		</Switch>
	);
};
const AppRouter = () => {
	return <Router>{renderRoutes(config)}</Router>;
};
export default AppRouter;

8.路由 hooks 語法

react-router-dom 也已經支持 hooks語法,獲取路由信息或路由跳轉,可以使用新的hooks 函數:
useHistory:獲取歷史路由,回退、跳轉等操作;
• useLocation:查看當前路由信息;
useParams:讀取路由附帶的params參數信息;
useRouteMatch:匹配當前路由;
只要包裹在中的子組件都可以通過這幾個鉤子函數獲取路由信息。
代碼演示:

import { useHistory } from "react-router-dom";
function HomeButton() {
	const history = useHistory();
	function onClick() {
		history.push("/home");
	}
	return (
		<button type="button" onClick={onClick}>
			跳轉Home頁
		</button>
	);
}

9.結合mobx管理數據狀態

項目中是否使用狀態管理工具或使用何種管理工具,依據實際項目情況而定。
本項目使用自己比較熟悉的Mobx,Mobx是一個功能強大,上手非常容易的狀態管理工具。
為了使用簡潔及管理方便,在組織上,分為全局公共數據狀態和頁面數據狀態。
公用數據狀態存放在/src/stores目錄下;頁面幾數據存放於對應頁面目錄下。
在實現上,利用mobx + useContext Hook特性 實現函數式組件的狀態管理。
具體在於利用React的createdContext構建包含Mobx 的context上下文;函數式組件中使用useContext Hook 訂閱Mobx數據變化。
• 頁面級store.js 代碼:

import { createContext } from "react";
import { observable, action, computed } from "mobx";
import request from "@/services/newRequest";
class HomeStore {
	@observable tableData = [];
	@observable pageTitle = "Home主頁";
	@observable loading = false;
	@action.bound setData(data = {}) {
		Object.entries(data).forEach(item => {
			this[item[0]] = item[1];
		});
	}
	// 列表數據
	@action.bound
	async qryTableDate(page = 1, size = 10) {
		this.loading = true;
		const res = await request({
			url: "/list",
			method: "post",
			data: { page, size }
		});
		if (res.success) {
			const resData = res.data || {};
			console.log(resData);
		}
		this.loading = false;
	}
}
export default createContext(new HomeStore());

• 頁面組件代碼 :

import React, { useContext } from "react";
import { observer } from "mobx-react";
import Store from "./store";
import "./style.less";
const HomePage = () => {
	const pageStore = useContext(Store);
	return (
		<div className="page-home page-content">
			home頁面
			<h2>{pageStore.pageTitle}</h2>
		</div>
	);
};

export default observer(HomePage);
以上為部分演示代碼,具體業務實現可以查看項目代碼。

10.Axios Http 請求封裝

Axios請求封裝,具體代碼見 /src/services/newRequest.js

11.UI組件及頁面佈局

UI組件使用優秀的Ant Design 組件庫,註意使用 babel-plugin-import 配置實現組件的按需載入。
本項目的內部頁面佈局採用 Antd 上經典的佈局方式:

頁面佈局需要合理拆分模塊,左側菜單導航欄根據靜態菜單渲染。實際完整代碼詳見項目,以下為BasicLayout組件:

import React from "react";
import { Layout } from "antd";
import SiderMenu from "../SiderMenu";
import MainHeader from "../MainHeader";
import MainFooter from "../MainFooter";
import "./style.less";
const BasicLayout = ({ route, children }) => {
	return (
		<Layout className="main-layout">
			{/* 左側菜單導航 */}
			<SiderMenu routes={route.childRoutes} /> 
			<Layout className="main-layout-right">
				{/* 頂部展示佈局 */}
				<MainHeader></MainHeader>
				<Layout.Content className="main-layout-content">
					{/* 實際頁面佈局 */}
					{children}
					{/* <MainFooter></MainFooter> */}
				</Layout.Content>
			</Layout>
		</Layout>
	);
};
export default BasicLayout;

對於登錄頁等頁面無需套在上面的基本佈局之類,需要單獨處理(菜單配置在BasicLayout配置之前)。

三 、雲端一鍵部署上線應用

1.上傳代碼

git add . 
git commit -m '添加你的註釋'
git push

2.在日常環境部署

一鍵進行應用部署。在應用詳情頁面點擊日常環境的「部署」按鈕進行一鍵部署,部署狀態變成綠色已部署以後可以點擊訪問部署網站查看效果。

3.配置自定義功能變數名稱線上上環境上線

• 配置線上環境自定義功能變數名稱。在功能開發驗證完成後要線上上環境進行部署,線上上環境的「部署配置」-「自定義功能變數名稱」中填寫自己的功能變數名稱。例如我們添加一個二級功能變數名稱 company.workbench.fun 來綁定我們部署的前端應用。然後複製自定義功能變數名稱下方的API網關地址對添加的二級功能變數名稱進行CNAME配置。

• 配置CNAME地址。複製好 API網關功能變數名稱地址後,來到你自己的功能變數名稱管理平臺(此示例中的功能變數名稱管理是阿裡雲的功能變數名稱管理控制台,請去自己的功能變數名稱控制台操作)。添加記錄的「記錄類型」選擇「CNAME」,在「主機記錄」中輸入你要創建的二級功能變數名稱,這裡我們輸入「company」,在「記錄值」中粘貼我們之前複製的 API網關功能變數名稱地址,「TTL」保留預設值或者設置一個你認為合適的值即可。

• 線上上環境部署上線。回到雲開發平臺的應用詳情頁面,按照部署的操作,點擊線上環境的「部署按鈕」,部署完成以後就在你自定義的功能變數名稱進行了上線。CNAME 生效之後,我們輸入 company.workbench.fun(示例網址) 可以打開部署的頁面。至此,如何部署一個應用到線上環境,如何綁定自己的功能變數名稱來訪問一個線上的應用就完成了,趕緊部署自己的應用到線上環境,用自己的功能變數名稱玩起來吧 ;)

一鍵創建React應用模版鏈接 :https://workbench.aliyun.com/application/front/create?fromConfig=12&fromRepo=sol_github_12

參考文獻:https://juejin.cn/post/6844904035099623437


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 如何才能寫好Python代碼?很多小伙伴都會問這樣的問題,今天這篇就來告訴大家怎樣寫好Python代碼。 程式設計的好與壞,早在我們青蔥歲月時就接觸過了,只是那是並不知道這竟如此重要。能夠立即改善程式設計、寫出“好”代碼的知識有以下幾點: •面向對象五個基本原則; •常見的三種架構; •繪圖; •起 ...
  • 大家好,我是棧長。 最近技術棧真是醉了,Log4j2 的核彈級漏洞剛告一段落,這個月初 Spring Cloud Gateway 又突發高危漏洞,現在連最要命的 Spring 框架也淪陷了。。。 棧長今天看到了一些安全機構發佈的相關漏洞通告,Spring 官方博客也發佈了漏洞聲明: 漏洞描述: 用戶 ...
  • 前言: 請各大網友尊重本人原創知識分享,謹記本人博客:南國以南i 上篇我們介紹到 保姆教程系列二、Nacos實現註冊中心 配置中心原理 一、 服務配置中心介紹 首先我們來看一下,微服務架構下關於配置文件的一些問題: 配置文件相對分散。在一個微服務架構下,配置文件會隨著微服務的增多變的越來越多,而且分 ...
  • Python之所以能夠成為流行的數據分析語言,有一部分原因在於其簡潔易用的字元串處理能力。 Python的字元串對象封裝了很多開箱即用的內置方法,處理單個字元串時十分方便;對於Excel、csv等表格文件中整列的批量字元串操作,pandas庫也提供了簡潔高效的處理函數,幾乎與內置字元串函數一一對應。 ...
  • 昨天凌晨發了篇關於Spring大漏洞的推文,白天就有不少小伙伴問文章怎麼刪了。 主要是因為收到朋友提醒說可能發這個會違規(原因可參考:阿裡雲因發現Log4j2核彈級漏洞但未及時上報,被工信部處罰),所以就刪除了。 經過一天的時間,似乎這個事情變得有點看不懂了。所以下麵聊聊這個網傳的Spring大漏洞 ...
  • 在學習net core中接觸到了swagger、學習並記錄 純API項目中 引入swagger可以生成可視化的API介面頁面 引入包 nuget包: Swashbuckle.AspNetCore(最新穩定版) 配置 1.配置Startup類ConfigureServices方法的相關配置 1 pub ...
  • 故事背景 在linux開發中我們經常會用到dbus來進行進程間通信,但是如何理解dbus服務端和客戶端呢?很多小伙伴可能都會遇到類似的問題,而且都是含含糊糊的,接下來我們直接上硬菜。 探索之路 首先要明白dbus是什麼,有什麼作用? 如何把自己的程式做成dbus服務? 如何調用dbus介面? 經驗心 ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 ​LNMP是Linux + Nginx + MySQL + PHP 四個系統的首字母縮寫,相對於 LAMP(Linux + Apache + MySQL + PHP )來說的。曾經在虛擬主機建站界風靡一時,隨著新的編程語言和容器技術、微服務等發展 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...