当前位置: 首页 > news >正文

网站的外链接数自己可以做一个网站吗

网站的外链接数,自己可以做一个网站吗,河南建筑市场一体化平台,wordpress分类设计rsup是使用 rust 编写的一个前端 npm 依赖包管理工具#xff0c;可以获取到项目中依赖包的最新版本信息#xff0c;并通过 web 服务的形式提供查看、升级操作等一一系列操作。 在前一篇文章中#xff0c;记录初始的功能设计#xff0c;自己的想法实现过程。在自己的使用过…rsup是使用 rust 编写的一个前端 npm 依赖包管理工具可以获取到项目中依赖包的最新版本信息并通过 web 服务的形式提供查看、升级操作等一一系列操作。 在前一篇文章中记录初始的功能设计自己的想法实现过程。在自己的使用过程功能中也会发现一些存在的问题有一些问题值得记录的再次标记供大家参考。 rsup 工具安装 在上一篇文章中描写的安装rsup工具部分错误因为我本地是 macos 系统 rust 默认执行cargo build构建的是适合 macos 的可执行文件对于 windows、linux 是不能直接用还有一个问题就是rsup-web静态服务资源是不会被编译进工具包的我本地能用也仅仅是我本地有源代码它指向静态资源路径的就是我电脑的绝对地址。 可以采取将静态资源链接打包进二进制文件中。 使用include_bytes!rust 内置的宏将静态文件的内容嵌入到二进制文件使用第三方 crate比如embed-resource或者rust-embed 但是为了方便控制 web 静态资源比如可以单独更新。采取了静态文件和可执行文件分离的方式提供下载器同时下载rsup可执行文件和rsup-webweb 静态资源。针对不同的系统定义默认的下载路径然后通过配置文件读取 web 静态资源提供 web 服务。 rsup工具包包含了配置文件、可执行文件、web 服务文件等。根据不同的系统提供了三种安装工具包包括 linux、macos、windows。 macos installer ubuntu instanller windows instanller 提供了安装脚本文件sh一键下载解压、安装。无需手动配置环境变量。 curl -fsSL https://github.com/ngd-b/rsup/blob/main/install.sh | shwindows用户需要手动下载安装包解压后执行installer.exe即可并且需要手动配置环境变量。 installer子包下载资源 这是为了解决上述问题新增的一个安装器更友好的交互方式进行安装。也方便后面对下载方式进行更友好的优化。 执行安装器需要使用管理员权限。windows右键以管理员身份执行 exe类 linux 系统需要使用sudo执行。 提供了从 github 或者 gitee 下载资源两种方式。使用第三方库 cratedialoguer进行交互选择。 目前只提供了从github下载资源。 use clap::{Parser, ValueEnum}; use dialoguer::{theme::ColorfulTheme, Select};#[derive(Parser, Debug, Clone, ValueEnum)] pub enum Origin {Github,Gitee, }impl Origin {// ...pub fn as_str(self) - static str {match self {Origin::Github github,Origin::Gitee gitee,}}/// 将枚举pub fn choices() - Vecstatic str {vec![Origin::Github.as_str(), Origin::Gitee.as_str()]} }/// 提示用户选择下载源 /// return 下载源 pub fn prompt_origin() - Origin {let select Select::with_theme(ColorfulTheme::default()).with_prompt(Please select download source...).default(0).items(Origin::choices().as_slice()).interact().unwrap();match select {0 Origin::Github,1 Origin::Gitee,_ unreachable!(),} }使用reqwest 下载资源并将资源保存到默认路径。文件路径output的目录必须要提前创建而fs::File::create(output)创建了资源文件如果文件已经存在会直接覆盖。 use reqwest::Client; use tokio::fs;/// 下载文件 /// async fn download_file(client: Client, url: str, output: str) - Result(), Boxdyn Error {// 下载地址let res client.get(url).send().await?;if res.status().is_success() {// 下载成功// 保存文件到指定目录// 文件路径let mut file fs::File::create(output).await?;// 保存文件let bytes res.bytes().await?;file.write_all(bytes).await?;Ok(())} else {let error_message format!(Request failed with status code: {}, res.status());Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other,error_message,)))} }文件下载完成后需要解压。所有的资源文件都是.tar.gz格式的使用flate2解压文件并且需要使用tar进行解包提取到指定目录。 use flate2::read::GzDecoder; use tar::Archive;/// 解压文件 /// /// param url 下载地址 /// param target_dir 保存目录 async fn decompress_file(url: str, target_dir: str) - Result(), Boxdyn Error {let tar_gz File::open(url)?;let decomppress GzDecoder::new(tar_gz);let mut archive Archive::new(decomppress);// 处理解压目录不存在则创建目录if !Path::new(target_dir).exists() {fs::create_dir_all(target_dir).await?;}archive.unpack(target_dir)?;Ok(()) }所需要的资源下载解压完成后现在默认目录下类 linux 系统下是/opt/rsup有三个文件 rsup 可执行文件config.toml 配置文件web web 静态资源 可以直接去执行rsup可执行文件。但是当前目录下没有package.json文件我们可以指定参数--dir去访问指定目录下的package.json。为了方便命令的使用安装时经将命令添加到环境变量中。 针对不同的操作系统环境变量的配置文件不一样。windows系统需要用户自行配置macos系统下是.zshrc;其他类系统默认为.bashrc use std::io::Write; use std::{error::Error, fs::OpenOptions};/// 提示用户是否添加命令到环境变量 /// 默认添加 pub fn prompt_add_to_env(path: str) - Result(), Boxdyn Error {// ... 省略部分代码let home_dir std::env::var(HOME)?;// 确定系统使用的shelllet shell_file_name match os {macos .zshrc,_ .bashrc,};// 环境变量配置目录let shell_config_path format!({}/{}, home_dir, shell_file_name);// 写入配置let mut file OpenOptions::new().append(true).open(shell_config_path)?;writeln!(file, \n# Add rsup to PATH\nexport PATH\{}:$PATH\, path)?; }写入配置文件后需要重新加载配置文件。执行source ~/.zshrc或者.bashrc这样就可以全局使用rsup命令了。 config子包管理配置文件 配置文件的读取和写入使用config子包提供配置文件读写操作。installer安装时会默认生成配置文件在rsup执行时会读取配置文件。为了方便配置文件管理新增config子包。 使用了 crate toml 对配置文件config.toml进行读写序列化和反序列化。 use std::{error::Error,fs::{self, File},io::{self, Write},path::Path, };impl Config {/// 读取配置文件///pub async fn read_config() - Result(), Boxdyn Error {// 读取配置文件let config_dir Config::get_url();let config_file_dir format!({}/config.toml, config_dir);// ... 省略部分代码let config_content fs::read_to_string(config_file_dir)?;let config: Config toml::from_str(config_content)?;Ok(())}/// 写入配置文件pub async fn write_config() - ResultConfig, Boxdyn Error {let config_dir Config::get_url();// ... 省略部分代码// 配置文件let config_url format!({}/config.toml, config_dir);let mut file File::create(config_url.clone())?;let mut config Config::default();// 配置文件路径config.dir config_dir.clone();// 静态文件目录config.web.static_dir format!({}/web, config_dir);let config_content toml::to_string(config)?;file.write_all(config_content.as_bytes())?;Ok(config)} }在主入口main中执行读取配置文件然后可以在各个子包中读取。为了方便使用在config中提供了静态全局变量CONFIG使用了第三方 crateonce_cell实现。 use once_cell::sync::OnceCell;// 全局共享配置 pub static CONFIG: OnceCellConfig OnceCell::new();impl Config {pub async fn read_config() - Result(), Boxdyn Error {// ... 省略部分代码// 保存配置数据共享CONFIG.set(config).unwrap();}/// 父级包获取配置pub fn get_config() - static Config {CONFIG.get().unwrap()} }这样就可以在其他子包中直接使用config::Config::get_config()获取配置数据了。 配置文件中包含的配置项有 name rsup version 0.3.0 dir /opt/rsup[web] port 8888 static_dir /opt/rsup/web[pkg] npm_registry https://registry.npmmirror.com配置文件中的dir字段是安装目录默认安装在/opt/rsup;web.port字段是 web 服务的端口号默认8888pkg.npm_registry字段是 npm 依赖源地址默认为国内镜像。通常只建议修改pkg.npm_registry设置源地址方便请求依赖包。 command子包提供命令行交互 提供了新的子包command用于解析命令行参数。统一管理命令行参数方便使用。并且提供了一些方法使用。 在使用rsup命令时可以指定目录使用前端 npm 依赖管理web服务也可以通过输入自命令进行交互式操作。 子命令包含了两部分Config 配置命令Update更新命令。新创建了command子包在主包解析参数时进行逻辑判断如果输入命令则执行对应的子命令未输入子命令则默认执行 web 服务 #[tokio::main] async fn main() {let args Cli::parse();match args.command {Some(Commands::Config { .. }) | Some(Commands::Update { .. }) {run().await;}_ {let package Package::new();// 默认启动pkg解析服务let package_clone package.clone();task::spawn(async move {pkg::run(args.pkg_args, package_clone).await;});web::run(package.clone()).await;}} }执行run()方法调用了子包command中的方法并解析命令行参数根据参数执行对应的操作。 pub async fn run() {let cli Commands::parse();let _ match cli {Commands::Config { config } match config {ConfigOptions::List ConfigOptions::list_config().await,ConfigOptions::Set { key, value } ConfigOptions::set_config_value(key, value).await,ConfigOptions::Get { key } ConfigOptions::get_config_value(key).await,ConfigOptions::Delete todo!(),},Commands::Update { update } {// 获取最新的包地址let (rsup_url, rsup_web_url) utils::get_pkg_url(None);// 获取命令安装目录let config external_config::Config::get_config().await;match update {UpdateOptions::Rsup UpdateOptions::rsup_update(rsup_url, config.dir).await,UpdateOptions::Web {UpdateOptions::rsup_web_update(rsup_web_url, config.dir).await}}}}; }Config 配置命令 Config配置命令用来管理配置文件提供交互式操作。我们之前在installer安装时默认生成配置文件。通过config命令可以查看、修改、删除配置项。 config list 可以展示出配置文件config.toml,在我们安装好rsup命令后执行rsup config list可以看到配置文件内容。 config set key value 可以修改配置文件中的值例如rsup config set web.port 9999 修改web服务端口号。 对于配置文件的访问、修改主要是使用了子包config中的方法。为了方便修改对于子包config的实现进行了调整文章上面提到的实现为第一版实现可以做对比差异。 初始实现的需要在core主入口中调用一次读取配置文件然后在其他子包中通过config::Config::get_config()获取。这种方式在config子包中不方便直接修改配置文件需要重新读取。 使用tokio::sync::RwLock 实现读写锁它是线程安全的。使用once_cell::sync::Lazy 实现懒加载在首次使用时才去读取配置文件。 pub static CONFIG: LazyRwLockConfig Lazy::new(|| {// 这里调用初始化let config Config::read_config().unwrap();RwLock::new(config) });在使用set设置配置项时需要管理员权限配置更新后会同步更新config.toml配置文件 Update更新命令 rsup工具包含自身和web服务两部分提供了更新命令可以更新rsup工具和web服务。 通过rsup update rsup更新工具通过rsup update web更新web服务。 utils子包提供公共方法 为了方便子包之间的共用方法的服用提供了utils子包提供了一些公共方法。 遇到的问题 记录一下遇到的问题方便后续查阅。 在使用本地config 模块与配置文件config发生命名冲突 通过extern 明确导入外部模块 // 引入外部crate extern crate config as external_config;发布包到crates-io时名称重复本地引用修改名称 本地开发时使用的名称utils,为了发布到crates-io时需要修改名称rsup_utils避免名称重复。然后本地引用时使用package字段指定名称这样不需要去调整代码里的引用。 [package] utils { version 0.1.0, path ../utils, package rsup_utils }下载文件时展示进度条 之前的文件下载时控制台会陷入长时间的阻塞状态没有任何反应为了提供更好的交互体验使用indicatif展示进度条。 要采用进度条在下载文件时就要使用流式读取文件以便更新进度条。 增加两个新的lib库,futures-util提供对于stream的扩展函数。 cargo add indicatif cargo add futures-util修改请求reqwest增加特性支持stream [dependencies] reqwest { version 0.12.9, features [stream] }修改之前的下载函数download_file,不再使用write_all一次性写入文件通过分批次读取写入并同步更新进度条。 /// 下载文件 /// async fn download_file(client: Client, url: str, output: str) - Result(), Boxdyn Error {// 下载地址let res client.get(url).send().await?;if res.status().is_success() {// 获取文件大小let content_size res.content_length().ok_or(无法获取文件大小)?;// 下载成功// 保存文件到指定目录// 文件路径let mut file fs::File::create(output).await?;// 创建进度条let pb ProgressBar::new(content_size);pb.set_style(ProgressStyle::default_bar().template({msg} [{elapsed_precise}] {bar:80} {percent}%)?.progress_chars(##-),);// 创建流式响应体let mut downloaded 0;let mut stream res.bytes_stream();while let Some(item) stream.next().await {let chunk item?;file.write_all(chunk).await?;let len chunk.len() as u64;downloaded len;pb.set_position(downloaded);}pb.finish_with_message(下载完成);// 保存文件// let bytes res.bytes().await?;// file.write_all(bytes).await?;Ok(())} else {let error_message format!(Request failed with status code: {}, res.status());Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other,error_message,)))} }解决web服务自动后刷新页面加载不到的问题 这是典型的SPA的问题由于我们使用的是history路由模式路由由前端控制。我们刷新页面比如http://localhost:8888/home时会请求http://localhost:8888/home但是web服务没有这个路由所以会返回404导致刷新页面加载不到。 为了处理这个问题需要增加通配符路由处理跳转route(/{tail:.*}, web::get().to(index)){tail:.*}是一个路径参数它可以匹配任何路径。 let server HttpServer::new(move || {//...App::new().app_data(web::Data::new(ms.clone())).route(/, web::get().to(index)).wrap(cors).service(web::scope(/api).configure(api::api_config)).service(Files::new(/static, format!({}/static/, static_file_path)).prefer_utf8(true),).route(/ws, web::get().to(socket_index))// SPA fallback route.route(/{tail:.*}, web::get().to(index)) })windos系统下不同的命令执行名称 在windows系统下我们执行npm -v时实际内部执行的是npm.cmd -v而在mac系统下执行npm -v时实际内部执行的是npm -v所以需要根据系统类型使用不同的命令。 // 判断系统如果是windows则使用npm.cmd let npm_cmd if cfg!(windows) { npm.cmd } else { npm };如果安装时是.exe的话就不需要添加后缀了直接使用即可。比如node web服务API参数映射处理 在处理API请求参数时通过枚举定义了参数类型然后通过解析匹配到指定的数据结构。 async fn update_pkg(req: web::JsonReqParams,data: web::DataMs, ) - Resultimpl Responder, Error {match *req {ReqParams::UpdatePkg(params) {}err {// ...} }如果定义的数据结构字段存在重叠某个结构完全包含另一个结构的字段在匹配时就需要将完全包含的结构放在前面否则可能会匹配到错误的结构。 #[derive(Deserialize, Serialize, Debug)] #[serde(untagged)] pub enum ReqParams {UpdatePkg(UpdateParams),// 删除// 目前接受一个nameRemovePkg(RemoveParams), }UpdateParams 和RemoveParams存在字段重叠UpdateParams包含了RemoveParams的所有字段要想匹配到UpdateParams需要将RemoveParams放在前面。 最后 部署了rsup文档服务网站rsup|Npm Helper 往期rsup文章 模式匹配、trait 特征行为、必包、宏多线程任务执行并发线程间的数据共享包、模块引用路径开发一个命令行工具rust 命令行工具rsup管理前端npm依赖
http://www.hkea.cn/news/14433700/

相关文章:

  • 网站开发网站北京微网站建设公司
  • 网站的tdk指的是什么wordpress固定主题
  • 电子商务网站建设与管理的背景网站建立数据库连接时出错
  • 辽宁朝阳网站建设公司wordpress自己写页面
  • 52麻将官方网站做代理深圳哪个网站好推广一点
  • 江苏定制网站建设费用网站信息发布和内容建设自查报告
  • 自考免费自学网站网站代码需要注意什么问题吗
  • 做网站用html还是python好网站的流程图
  • 网站建设详细描述产品的是什么意思淄博做网站的公司排名
  • 浙江网站建设dyfwzx临沂企业网站建站模板
  • 建一个网站需要哪些知识做网站按页面收费
  • 广告网站模板下载 迅雷下载安装想代理个网站建设平台
  • wordpress加备案号徐州百度搜索优化
  • 网站建设费用兴田德润团队semseo
  • wordpress 整站移植首页定制
  • 电子商务网站设计成功的要素wordpress内容折叠
  • 企业建设网站价格电商网站可以用dw做
  • 外贸购物网站建站不用下载就可以登录微信
  • 浙江建设厅网站怎么进不去wordpress登陆地址修改
  • 做瞹瞹小视频网站河南建筑材料信息网
  • wordpress建立多站点wordpress主题付费
  • 德州极速网站建设百家号有没有什么网站可以直接在网上做试题并且可以给你判出来
  • 网站建设手机端pc端分开semiconductor是什么意思
  • 模拟网站平台怎么做建材类网站建设需要的资料
  • 餐饮网站建设的目的网站建设内容与实现功能
  • 汕头建网站教育网站开发需求说明书
  • 上海网站搜索引擎优化开车网址来一个
  • h5做的分销网站可以自己设计装修的免费软件
  • 做外链音乐网站建筑设计公司资质
  • 有没有免费做网站的网站qq在线代码