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

JavaScript系列(90)--前端脚手架开发

前端脚手架开发 🛠️

前端脚手架是现代前端开发流程中的重要工具,它能够帮助开发者快速初始化项目结构、配置开发环境、设置构建流程,从而提高开发效率和标准化项目结构。本文将详细介绍前端脚手架的开发原理、实现方式以及最佳实践。

脚手架概述 🌟

💡 小知识:脚手架(Scaffold)源自建筑行业,指辅助建筑工人进行高空作业的临时平台。在软件开发中,脚手架指能够快速生成项目基础结构的工具,让开发者专注于业务逻辑而非繁琐的项目配置。

为什么需要脚手架

现代前端开发已经变得越来越复杂,一个典型的项目通常需要:

  • 模块化系统管理
  • 代码转译和编译
  • 开发服务器配置
  • 热更新支持
  • 测试框架集成
  • 代码格式化和检查
  • 构建和优化流程

手动设置这些配置既耗时又容易出错,而脚手架工具使得开发者可以通过简单的命令就能创建符合最佳实践的项目结构,极大地提高了开发效率。

脚手架的核心功能

一个完整的前端脚手架工具通常提供以下功能:

  1. 项目初始化 - 创建项目目录结构和基础文件
  2. 依赖管理 - 安装和配置项目依赖
  3. 开发环境 - 配置开发服务器、热重载等
  4. 构建流程 - 设置代码编译、打包和优化流程
  5. 项目拓展 - 提供插件机制或子生成器支持
  6. 开发规范 - 集成代码格式化、检查工具
  7. 文档生成 - 自动生成项目文档

脚手架原理与架构 📐

核心工作流程

1. 命令行解析 -> 确定用户意图
2. 项目配置 -> 收集用户输入或使用默认配置
3. 模板获取 -> 从本地或远程获取模板
4. 模板编译 -> 根据配置处理模板变量
5. 文件生成 -> 将编译后的模板写入目标目录
6. 依赖安装 -> 安装项目所需依赖包
7. 初始化操作 -> 执行项目初始化命令
8. 完成提示 -> 给出使用提示和下一步操作建议

脚手架架构设计

一个典型的脚手架工具包含以下主要组件:

  1. 命令行接口 (CLI)

    • 解析命令行参数
    • 展示用户交互界面
    • 调用相应的子命令
  2. 配置管理器

    • 收集用户配置
    • 管理默认配置
    • 配置校验与合并
  3. 模板引擎

    • 加载模板文件
    • 编译模板内容
    • 处理条件渲染逻辑
  4. 文件操作模块

    • 创建项目目录结构
    • 写入生成的文件
    • 复制静态资源
  5. 包管理器接口

    • 调用npm/yarn/pnpm等包管理器
    • 安装项目依赖
    • 处理安装错误

数据流图

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   用户输入   │───>│  配置收集   │───>│  模板处理   │
└─────────────┘    └─────────────┘    └─────────────┘│                   ││                   ▼
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ 项目初始化  │<───│  依赖安装   │<───│  文件生成   │
└─────────────┘    └─────────────┘    └─────────────┘

命令行工具实现

使用Node.js创建脚手架CLI的核心代码示例:

// cli.js
#!/usr/bin/env node
const program = require('commander');
const chalk = require('chalk');
const create = require('./commands/create');program.version('1.0.0').description('A modern frontend scaffold tool');program.command('create <project-name>').description('Create a new project').option('-t, --template <template>', 'Project template to use').option('--typescript', 'Use TypeScript').option('--skip-install', 'Skip installing dependencies').action((name, options) => {console.log(chalk.blue(`Creating project: ${name}`));create(name, options);});program.parse(process.argv);if (!process.argv.slice(2).length) {program.outputHelp();
}

交互式配置收集

使用inquirer.js实现用户交互体验:

// questions.js
const inquirer = require('inquirer');async function promptForProjectInfo() {return inquirer.prompt([{type: 'input',name: 'projectName',message: 'Project name:',default: 'my-app'},{type: 'list',name: 'framework',message: 'Select a framework:',choices: ['React', 'Vue', 'Angular', 'None'],default: 'React'},{type: 'checkbox',name: 'features',message: 'Select additional features:',choices: [{ name: 'TypeScript', value: 'typescript' },{ name: 'ESLint', value: 'eslint' },{ name: 'Jest', value: 'jest' },{ name: 'Prettier', value: 'prettier' }]},{type: 'list',name: 'packageManager',message: 'Select a package manager:',choices: ['npm', 'yarn', 'pnpm'],default: 'npm'}]);
}module.exports = { promptForProjectInfo };

模板管理与渲染 📄

模板组织结构

一个标准的脚手架模板结构:

template-react/                # React模板
├── template/                  # 模板文件
│   ├── public/                # 静态资源
│   │   ├── components/        # 组件目录
│   │   ├── App.js             # 应用入口
│   │   └── index.js           # 主入口
│   ├── package.json           # 项目配置
│   └── README.md              # 项目说明
└── config.js                  # 模板配置

模板配置示例

// config.js
module.exports = {name: 'react-template',description: 'React project template with modern configuration',version: '1.0.0',prompts: [{type: 'confirm',name: 'useRouter',message: 'Add React Router?',default: false},{type: 'list',name: 'stateManagement',message: 'Choose state management solution:',choices: ['None', 'Redux', 'MobX', 'Context API'],default: 'None'}],filters: {'src/redux/**/*': 'stateManagement === "Redux"','src/mobx/**/*': 'stateManagement === "MobX"','src/router/**/*': 'useRouter'},complete: (data, { chalk }) => {console.log(chalk.green('Project created successfully!'));console.log('To get started:');console.log(`cd ${data.projectName}`);console.log(`${data.packageManager} start`);}
};

模板引擎实现

使用EJS作为模板引擎处理文件:

// template-engine.js
const ejs = require('ejs');
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');async function renderTemplates(src, dest, data) {const templates = glob.sync('**/*', {cwd: src,nodir: true,dot: true});for (const file of templates) {const sourcePath = path.join(src, file);const content = fs.readFileSync(sourcePath, 'utf-8');// 处理EJS模板let result;let targetFile = file;if (file.endsWith('.ejs')) {result = ejs.render(content, data);// 移除.ejs扩展名targetFile = file.slice(0, -4);} else {result = content;}const targetPath = path.join(dest, targetFile);// 确保目标目录存在await fs.ensureDir(path.dirname(targetPath));// 写入处理后的内容await fs.writeFile(targetPath, result);}
}module.exports = { renderTemplates };

条件文件处理

根据用户配置决定是否包含特定文件:

// generate-project.js
const { evaluate } = require('./utils');function shouldIncludeFile(file, filters, data) {if (!filters) return true;// 检查文件是否有条件过滤规则for (const pattern in filters) {if (minimatch(file, pattern)) {// 计算条件表达式return evaluate(filters[pattern], data);}}return true;
}async function generateProject(template, dest, data, filters) {const files = glob.sync('**/*', {cwd: template,nodir: true,dot: true});for (const file of files) {// 检查文件是否应该包含if (!shouldIncludeFile(file, filters, data)) {continue;}// 处理并写入文件// ...处理模板和复制文件逻辑}
}

动态模板变量处理

package.json模板示例:

{"name": "<%= projectName %>","version": "0.1.0","private": true,"scripts": {"start": "react-scripts start","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"},"dependencies": {"react": "^18.2.0","react-dom": "^18.2.0","react-scripts": "5.0.1"<% if (useRouter) { %>,"react-router-dom": "^6.10.0"<% } %><% if (stateManagement === 'Redux') { %>,"redux": "^4.2.1","react-redux": "^8.0.5"<% } %><% if (stateManagement === 'MobX') { %>,"mobx": "^6.9.0","mobx-react-lite": "^3.4.3"<% } %>},"eslintConfig": {"extends": ["react-app","react-app/jest"]},"browserslist": {"production": [">0.2%","not dead","not op_mini all"],"development": ["last 1 chrome version","last 1 firefox version","last 1 safari version"]}<% if (typescript) { %>,"devDependencies": {"typescript": "^4.9.5","@types/react": "^18.0.28","@types/react-dom": "^18.0.11"<% if (useRouter) { %>,"@types/react-router-dom": "^5.3.3"<% } %>}<% } %>
}

脚手架工具实现 ⚙️

创建项目命令实现

核心实现代码:

// commands/create.js
const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const { promptForProjectInfo } = require('../utils/questions');
const { renderTemplates } = require('../utils/template-engine');
const { installDependencies } = require('../utils/package-manager');
const { getTemplate } = require('../utils/template-loader');async function create(projectName, options) {try {// 1. 项目目标路径const targetDir = path.resolve(process.cwd(), projectName);// 2. 检查目录是否已存在if (fs.existsSync(targetDir)) {const { overwrite } = await inquirer.prompt([{type: 'confirm',name: 'overwrite',message: `Directory ${projectName} already exists. Overwrite?`,default: false}]);if (!overwrite) {console.log(chalk.red('Operation cancelled'));return;}await fs.remove(targetDir);}// 3. 收集用户配置const userAnswers = await promptForProjectInfo();const config = {...userAnswers,projectName,...options};// 4. 加载模板const template = await getTemplate(config.framework.toLowerCase());// 5. 渲染模板await fs.ensureDir(targetDir);await renderTemplates(path.join(template.path, 'template'),targetDir,config);// 6. 安装依赖if (!options.skipInstall) {console.log();console.log(chalk.cyan('Installing dependencies...'));await installDependencies(targetDir, config.packageManager);}// 7. 完成信息console.log();console.log(chalk.green('✨ Project creation complete!'));console.log();console.log('To get started:');console.log(`  cd ${projectName}`);if (options.skipInstall) {console.log(`  ${config.packageManager} install`);}console.log(`  ${config.packageManager} start`);// 8. 运行模板自定义的完成函数if (template.config.complete) {template.config.complete(config, { chalk });}} catch (error) {console.error(chalk.red('Error creating project:'), error);process.exit(1);}
}module.exports = create;

依赖安装实现

// utils/package-manager.js
const execa = require('execa');
const ora = require('ora');async function installDependencies(targetDir, packageManager = 'npm') {const spinner = ora('Installing dependencies...').start();try {const command = packageManager;const args = ['install'];// 根据不同的包管理器调整参数if (packageManager === 'yarn') {// yarn默认安装,不需要特别参数} else if (packageManager === 'pnpm') {// pnpm可能需要额外参数}await execa(command, args, {cwd: targetDir,stdio: 'pipe' // 隐藏标准输出});spinner.succeed('Dependencies installed successfully');return true;} catch (error) {spinner.fail('Failed to install dependencies');console.error(`\n${error.message}`);return false;}
}module.exports = { installDependencies };

模板获取实现

// utils/template-loader.js
const path = require('path');
const fs = require('fs-extra');
const os = require('os');
const { downloadFromGitHub } = require('./downloader');// 模板缓存目录
const TEMPLATE_CACHE_DIR = path.join(os.homedir(), '.my-scaffold', 'templates');/*** 获取项目模板* @param {string} templateName 模板名称* @returns {Promise<Object>} 模板信息*/
async function getTemplate(templateName) {// 确保缓存目录存在await fs.ensureDir(TEMPLATE_CACHE_DIR);const templateMap = {'react': 'my-org/react-template','vue': 'my-org/vue-template','angular': 'my-org/angular-template'};// 获取模板完整名称const repoName = templateMap[templateName];if (!repoName) {throw new Error(`Template ${templateName} not found`);}// 检查本地缓存const templateDir = path.join(TEMPLATE_CACHE_DIR, templateName);const isTemplateExist = await fs.pathExists(templateDir);if (!isTemplateExist) {// 下载模板await downloadFromGitHub(repoName, templateDir);}// 加载模板配置const configPath = path.join(templateDir, 'config.js');const config = require(configPath);return {path: templateDir,config};
}module.exports = { getTemplate };

脚手架开发实例 🚀

创建自己的脚手架生成器

// 创建脚手架项目的引导程序
#!/usr/bin/env node
const inquirer = require('inquirer');
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const { execSync } = require('child_process');async function init() {console.log(chalk.blue('欢迎使用脚手架生成器!'));console.log('这个工具将帮助你创建你自己的前端脚手架工具.');console.log();const answers = await inquirer.prompt([{type: 'input',name: 'name',message: '脚手架名称:',default: 'my-scaffold'},{type: 'input',name: 'description',message: '简短描述:',default: 'A modern frontend scaffold tool'},{type: 'list',name: 'templateEngine',message: '选择模板引擎:',choices: ['EJS', 'Handlebars', 'Nunjucks'],default: 'EJS'},{type: 'confirm',name: 'includeExamples',message: '包含示例模板?',default: true}]);const targetDir = path.resolve(process.cwd(), answers.name);// 检查目录是否存在if (fs.existsSync(targetDir)) {const { overwrite } = await inquirer.prompt([{type: 'confirm',name: 'overwrite',message: `目录 ${answers.name} 已存在. 覆盖?`,default: false}]);if (!overwrite) {console.log(chalk.red('操作已取消'));return;}await fs.remove(targetDir);}// 创建项目结构await createProjectStructure(targetDir, answers);console.log();console.log(chalk.green('✨ 脚手架项目创建成功!'));console.log();console.log('接下来:');console.log(`  cd ${answers.name}`);console.log('  npm install');console.log('  npm link');console.log();console.log(`然后你可以运行 "${answers.name} create my-app" 来测试你的脚手架`);
}// 省略createProjectStructure函数实现...init().catch(err => {console.error(err);process.exit(1);
});

流行脚手架工具解析 🔍

Create React App

特点与功能

  • 零配置开箱即用
  • 集成开发服务器、编译器、测试工具
  • 支持TypeScript和PWA
  • 提供开发和生产环境优化

使用方式

# 创建新应用
npx create-react-app my-app# 使用TypeScript
npx create-react-app my-app --template typescript# 自定义模板
npx create-react-app my-app --template cra-template-custom

架构特点

  • 基于react-scripts实现构建和开发功能
  • 利用模板注入项目结构
  • 隐藏复杂配置,提供简单API

Vue CLI

特点与功能

  • 交互式项目创建
  • 插件化架构
  • 图形用户界面
  • 配置灵活可扩展
  • 支持预设配置

使用方式

# 安装
npm install -g @vue/cli# 创建项目
vue create my-project# 使用图形界面
vue ui# 使用预设
vue create --preset username/repo my-project

架构特点

  • 基于插件系统和webpack配置
  • 允许通过插件扩展功能
  • 提供完整的GUI界面支持

Yeoman

特点与功能

  • 丰富的生成器生态
  • 高度可定制
  • 框架无关
  • 支持子生成器

使用方式

# 安装
npm install -g yo# 安装生成器
npm install -g generator-webapp# 运行生成器
yo webapp# 运行子生成器
yo webapp:component

架构特点

  • 基于生成器系统
  • 每个生成器是一个独立的npm包
  • 高度可扩展的架构

主流脚手架比较

特性Create React AppVue CLIYeoman
配置灵活性低 (隐藏配置)高 (可插件化配置)高 (完全自定义)
易用性高 (零配置)中 (交互式配置)低 (需要选择生成器)
可扩展性低 (需要eject)高 (插件系统)高 (完全可定制)
生态规模单一目标 (React)中等 (Vue生态)大 (框架无关)
维护方式Facebook团队Vue.js核心团队社区维护

自定义脚手架开发实战 💻

Yeoman生成器开发

基本结构

generator-myapp/
├── generators/                # 生成器目录
│   ├── app/                   # 默认生成器
│   │   ├── index.js           # 生成器主文件
│   │   └── templates/         # 模板文件
│   └── component/             # 子生成器
│       ├── index.js           # 组件生成器
│       └── templates/         # 组件模板
├── package.json               # 包配置
└── README.md                  # 说明文档

生成器实现示例

// generators/app/index.js
const Generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');module.exports = class extends Generator {// 构造函数constructor(args, opts) {super(args, opts);// 添加选项this.option('typescript', {type: Boolean,default: false,description: 'Use TypeScript'});}// 初始化initializing() {this.log(yosay(`Welcome to the ${chalk.red('My App')} generator!`));}// 获取用户输入async prompting() {this.answers = await this.prompt([{type: 'input',name: 'name',message: 'Your project name',default: this.appname // 默认为当前文件夹名},{type: 'list',name: 'cssPreprocessor',message: 'Which CSS preprocessor would you like to use?',choices: ['None', 'Sass', 'Less', 'Stylus'],default: 'Sass'},{type: 'checkbox',name: 'features',message: 'Select additional features:',choices: [{name: 'ESLint',value: 'eslint',checked: true},{name: 'Jest',value: 'jest',checked: true},{name: 'Prettier',value: 'prettier',checked: true}]}]);}// 配置项目configuring() {// 创建.yo-rc.json配置文件this.config.set('cssPreprocessor', this.answers.cssPreprocessor);this.config.set('features', this.answers.features);this.config.set('typescript', this.options.typescript);this.config.save();// 如果使用ESLint,创建配置文件if (this.answers.features.includes('eslint')) {this.fs.copy(this.templatePath('.eslintrc.js'),this.destinationPath('.eslintrc.js'));}}// 写入文件writing() {// 复制静态文件this.fs.copy(this.templatePath('public/**/*'),this.destinationPath('public/'));// 处理package.jsonthis.fs.copyTpl(this.templatePath('package.json'),this.destinationPath('package.json'),{name: this.answers.name,typescript: this.options.typescript,eslint: this.answers.features.includes('eslint'),jest: this.answers.features.includes('jest'),prettier: this.answers.features.includes('prettier'),cssPreprocessor: this.answers.cssPreprocessor.toLowerCase()});// 处理READMEthis.fs.copyTpl(this.templatePath('README.md'),this.destinationPath('README.md'),{ name: this.answers.name });// 源代码目录const srcDir = 'src';// 选择正确的扩展名const ext = this.options.typescript ? 'tsx' : 'jsx';const styleExt = this.getStyleExtension();// 复制并处理主要源文件this.fs.copyTpl(this.templatePath(`src/App.${ext}`),this.destinationPath(`${srcDir}/App.${ext}`),{ name: this.answers.name,styleExt});// 复制样式文件this.fs.copy(this.templatePath(`src/App.${styleExt}`),this.destinationPath(`${srcDir}/App.${styleExt}`));}// 安装依赖install() {this.installDependencies();}// 结束end() {this.log(chalk.green('Done! Happy coding!'));}// 辅助方法getStyleExtension() {const cssMap = {'Sass': 'scss','Less': 'less','Stylus': 'styl','None': 'css'};return cssMap[this.answers.cssPreprocessor];}
};

脚手架最佳实践 ⭐

设计原则

  1. 简单性优先 - 脚手架应该易于使用,不应要求开发者了解太多底层细节
  2. 渐进式定制 - 提供合理默认值,但允许高级用户进行定制
  3. 一致的用户体验 - 命令行界面和交互应保持一致
  4. 适当的提示 - 提供清晰的错误提示和操作指南
  5. 可扩展架构 - 设计可扩展的模块化结构
  6. 良好文档 - 提供完整的使用说明和API文档

开发建议

  1. 模板版本控制 - 为模板设置版本管理,确保兼容性
  2. 提供多模板支持 - 支持多种项目类型和框架
  3. 设计人性化CLI - 提供帮助信息、彩色输出、进度指示器等增强体验
  4. 用户配置持久化 - 保存用户首选项以简化重复操作
  5. 模块化代码 - 分离关注点,使代码易于维护
  6. 缓存优化 - 缓存模板和依赖以提高性能
  7. 错误处理策略 - 优雅处理错误并提供恢复选项

测试策略

  1. 单元测试核心功能
  2. 集成测试确保组件协同工作
  3. 端到端测试验证完整工作流
  4. 快照测试确保生成文件的一致性
  5. 用户测试获取实际反馈

发布和维护

  1. 语义化版本控制
  2. 自动化发布流程
  3. 变更日志维护
  4. 兼容性策略
  5. 社区反馈收集机制

结语 📝

前端脚手架开发是前端工程化的重要一环,一个优秀的脚手架工具可以大幅提高团队效率,确保项目结构的一致性,并帮助新成员快速上手。通过本文,我们学习了:

  1. 脚手架的基本原理和架构设计
  2. 模板管理和渲染的核心实现
  3. 命令行工具和用户交互的实现方法
  4. 主流脚手架工具的特点和比较
  5. 自定义脚手架的开发实践和最佳实践

💡 学习建议:

  1. 从使用现有脚手架工具开始,理解其工作原理
  2. 尝试开发小型脚手架,解决特定团队需求
  3. 学习命令行工具开发和模板引擎的使用
  4. 了解不同脚手架的优缺点,借鉴其设计思想
  5. 持续改进和优化,根据用户反馈调整

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

JavaScript系列(90)--前端脚手架开发

前端脚手架开发 &#x1f6e0;️ 前端脚手架是现代前端开发流程中的重要工具&#xff0c;它能够帮助开发者快速初始化项目结构、配置开发环境、设置构建流程&#xff0c;从而提高开发效率和标准化项目结构。本文将详细介绍前端脚手架的开发原理、实现方式以及最佳实践。 脚手…...

工程实践中常见的几种设计模式解析及 C++ 实现

工程实践中常见的几种设计模式解析及 C 实现 在软件工程中&#xff0c;设计模式是一种通用的解决方案&#xff0c;用于解决常见问题和优化代码结构。它们通过提供一种规范化的编程思想&#xff0c;帮助开发者写出更高效、可维护和可扩展的代码。本文将介绍几种在工程实践中常见…...

基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统

2024旅游推荐系统爬虫可视化&#xff08;协同过滤算法&#xff09; 基于Pythondjangomysql旅游数据爬虫采集可视化分析推荐系统 有文档说明 部署文档 视频讲解 ✅️基于用户的协同过滤推荐算法 卖价就是标价~ 项目技术栈 Python语言、Django框架、MySQL数据库、requests网络爬虫…...

Oracle 12c Docker安装问题排查 sga_target 1536M is too small

一、问题描述 在虚拟机环境&#xff08;4核16GB内存&#xff09;上部署 truevoly/oracle-12c 容器镜像时&#xff0c;一切运行正常。然而&#xff0c;当在一台 128 核 CPU 和 512GB 内存的物理服务器上运行时&#xff0c;容器启动时出现了 ORA-00821 等错误&#xff0c;提示 S…...

es-head(es库-谷歌浏览器插件)

1.下载es-head插件压缩包&#xff0c;并解压缩 2.谷歌浏览器添加插件 3.使用...

C++大整数类的设计与实现

1. 简介 我们知道现代的计算机大多数都是64位的&#xff0c;因此能处理最大整数为 2 64 − 1 2^{64}-1 264−1。那如果是超过了这个数怎么办呢&#xff0c;那就需要我们自己手动模拟数的加减乘除了。 2. 思路 我们可以用一个数组来存储大数&#xff0c;数组中的每一个位置表…...

Linux网络基础(协议 TCP/IP 网络传输基本流程 IP VS Mac Socket编程UDP)

文章目录 一.前言二.协议协议分层分层的好处 OSI七层模型TCP/IP五层(或四层)模型为什么要有TCP/IP协议TCP/IP协议与操作系统的关系(宏观上是如何实现的)什么是协议 三.网络传输基本流程局域网(以太网为例)通信原理MAC地址令牌环网 封装与解包分用 四.IP地址IP VS Mac地址 五.So…...

Web开发:ORM框架之使用Freesql的导航属性

一、什么时候用导航属性 看数据库表的对应关系&#xff0c;一对多的时候用比较好&#xff0c;不用多写一个联表实体&#xff0c;而且查询高效 二、为实体配置导航属性 1.给关系是一的父表实体加上&#xff1a; [FreeSql.DataAnnotations.Navigate(nameof(子表.子表关联字段))]…...

NLP07-朴素贝叶斯问句分类之数据集加载(1/3)

一、概述 数据集加载&#xff08;Dataset Loading&#xff09;是机器学习、自然语言处理&#xff08;NLP&#xff09;等领域中的一个重要步骤&#xff0c;指的是将外部数据&#xff08;如文件、数据库、网络接口等&#xff09;加载到程序中&#xff0c;以便进行后续处理、分析…...

Rk3568驱动开发_点亮led灯(手动挡)_5

1.MMU简介 完成虚拟空间到物理空间的映射 内存保护设立存储器的访问权限&#xff0c;设置虚拟存储空间的缓冲特性 stm32点灯可以直接操作寄存器&#xff0c;但是linux点灯不能直接访问寄存器&#xff0c;linux会使能mmu linux中操作的都是虚拟地址&#xff0c;要想访问物理地…...

LangChain构建行业知识库实践:从架构设计到生产部署全指南

文章目录 引言:行业知识库的进化挑战一、系统架构设计1.1 核心组件拓扑1.2 模块化设计原则二、关键技术实现2.1 文档预处理流水线2.2 混合检索增强三、领域适配优化3.1 医学知识图谱融合3.2 检索结果重排序算法四、生产环境部署4.1 性能优化方案4.2 安全防护体系五、评估与调优…...

Vscode编辑器:解读文件结构、插件的导入导出、常用快捷键配置技巧及其常见问题的解决方案

一、文件与文件夹结构 1.文件结构 文件名作用.babelrc配置 Babel 编译选项&#xff0c;指定代码转译规则。.editorconfig定义项目代码格式规范&#xff0c;如缩进风格和空格数量等。.eslintignore列出 ESLint 忽略的文件或文件夹。.eslintrc.js配置 ESLint 的规则和插件。.gi…...

androidstudio 运行项目加载很慢,优化方法

一、Android Studio 运行项目加载缓慢可能由多种原因引起&#xff0c;以下是一些优化建议&#xff1a; 1. 升级硬件配置 内存&#xff1a;建议至少 8GB&#xff0c;16GB 或以上更佳。 SSD&#xff1a;使用 SSD 替代 HDD 以加快读写速度。 CPU&#xff1a;多核处理器有助于提…...

Vue性能翻倍秘籍

导读&#xff1a;某电商大促因工程化缺失导致页面崩溃&#xff01;本文通过双11级别流量压测&#xff0c;揭秘Vue项目性能优化的6大核心策略&#xff0c;涵盖构建提速、首屏优化、SSR实战等全链路方案。 工程化缺失引发的灾难现场 血泪案例&#xff1a; 某电商大促活动因工程化…...

线性回归 (Linear Regression)案例分析1

广告费用与产品销量 工欲善其事必先利其器数据分析1. 检查缺失值、异常值3. 散点图查看特征、响应相关性3. 热力图查看特征、响应相关性 特征工程1、导入必要工具包2、读取数据3、数据标准化4、保存特征工程的结果到文件&#xff0c;供机器学习模型使用 模型选择读取数据数据准…...

uni-app集成sqlite

Sqlite SQLite 是一种轻量级的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于各种应用程序中&#xff0c;特别是那些需要嵌入式数据库解决方案的场景。它不需要单独的服务器进程或系统配置&#xff0c;所有数据都存储在一个单一的普通磁盘文件中&am…...

策略模式环境类的实现方式对比

文章目录 1、策略模式2、聚合策略类实现方式一3、聚合策略类实现方式二4、对比5、补充&#xff1a;ApplicationContextAware接口 1、策略模式 近期工作中&#xff0c;需要处理4.x和5.x两个版本的数据&#xff0c;所以自然想到的是策略模式&#xff0c;写一个抽象类&#xff0c…...

Node.js 登录鉴权

目录 Session express-session 配置 express-session 函数 ts 要配置声明文件 express-session.d.ts express-session 使用 express-session 带角色 Token 什么是 JWT token jsonwebtoken 使用 jsonwebtoken 带角色 Session express 使用 express-session 管理会话&…...

【c++】【线程池】固定式线程池(FixedThreadPool)

【c】【线程池】固定式线程池&#xff08;FixedThreadPool&#xff09; 1属性 1.1 Task可调用对象 使用 function 包装器和using类型重命名 设置一个Task的可调用对象(可理解为函数指针) 这个Task也就是我们的任务 using Task std::function<void(void)>;定义了一个…...

高可用、高性能、负载均衡集群的区别

维度高可用集群高性能集群负载均衡集群核心目标服务持续可用&#xff0c;减少停机加速计算任务&#xff0c;提升处理能力请求分发算法、健康检查关键技术冗余、心跳检测、鼓掌转移并行计算、高速网络、分布式存储请求分发算法、健康检查典型应用数据库主从切换、关键业务系统科…...

Docker 与 Serverless(无服务器架构)

Serverless&#xff08;无服务器架构&#xff09; 是一种新的云计算架构&#xff0c;它通过让开发者专注于业务逻辑而无需管理服务器基础设施&#xff0c;来简化应用的开发和部署。Serverless 模型通常由云服务提供商管理基础设施的所有方面&#xff0c;而开发者只需提供代码和…...

mac 下 java 调用 gurobi 不能加载 jar

在 mac 电脑中的 java 始终不能加载 gurobi 的 jar 包&#xff0c;java 的开发软件 eclipse&#xff0c;idea 总是显示找不到 gurobi 的 jar 包&#xff0c;但是 jar 包明明就在那里。 摸索了三个小时&#xff0c;最后发现原因竟然是&#xff1a; jar 包太新&#xff0c;替换…...

halcon三维点云数据处理(二十七)remove_bin_for_3d_object_localization

目录 一、remove_bin_for_3d_object_localization代码第一部分二、remove_bin_for_3d_object_localization代码第二部分三、效果图一、remove_bin_for_3d_object_localization代码第一部分 1、读图构建3D模型。 2、一次二值化选取区域。 3、一次和背景差值选取区域。 4、在二维…...

Python 编程题 第二节:组合数字、乘法口诀表、水仙花数、反向输出四位数、判断三角形

组合数字 1-4不重复组成三位数&#xff0c;利用集合的去重 lst[] for i in range(1,5):for j in range(1,5):for m in range(1,5):s{i,j,m}if len(s)3:lst.append(i*100j*10m) print(lst) 乘法口诀表 修改换行符 for i in range(1,10):for j in range(1,i1):print(f"…...

【HTML— 快速入门】HTML 基础

准备工作 vscode下载 百度网盘 Subline Text 下载 Sublime Text下载 百度网盘 vscode 下载 Sublime Text 是一款轻量好用的文本编辑器&#xff0c;我们在写前端代码时&#xff0c;使用 Sublime Text 打开比使用记事本打开&#xff0c;得到的代码体验更好&#xff0c;比 vscode…...

【MATLAB中的图像数据结构】

MATLAB中的图像数据结构 目录 MATLAB中的图像数据结构目标 &#xff1a;知识点 &#xff1a;1. 图像的存储方式 &#xff1a;2. 图像的颜色空间 &#xff1a;3. 图像的像素操作 &#xff1a; 示例代码 &#xff1a;1. 读取和显示图像 &#xff1a;2. 查看图像信息 &#xff1a;…...

在线抽奖系统——项目介绍

目录 项目介绍 页面预览 需求分析 管理员登录注册 人员模块 奖品模块 活动模块 抽奖模块 系统设计 系统架构 项目环境 数据库设计 安全设计 完整代码&#xff1a;项目完整代码/在线抽奖系统/lottery-system Echo/project - 码云 - 开源中国 项目介绍 利用 MySQ…...

day7作业

编写一个如下场景&#xff1a; 有一个英雄Hero类&#xff0c;私有成员&#xff0c;攻击&#xff08;Atx&#xff09;&#xff0c;防御&#xff08;Defense&#xff09;&#xff0c;速度&#xff08;Speed)&#xff0c;生命值&#xff08;Blood)&#xff0c;以及所有的set get 方…...

JavaScript 系列之:Ajax、Promise、Axios

前言 同步&#xff1a;会阻塞。同步代码按照编写的顺序逐行依次执行&#xff0c;只有当前的任务完成后&#xff0c;才会执行下一个任务。 异步&#xff1a;异步代码不会阻塞后续代码的执行。当遇到异步操作时&#xff0c;JavaScript 会将该操作放入任务队列中&#xff0c;继续…...

AI人工智能机器学习之神经网络

1、概要 本篇学习AI人工智能机器学习之神经网络&#xff0c;以MLPClassifier和MLPRegressor为例&#xff0c;从代码层面讲述最常用的神经网络模型MLP。 2、神经网络 - 简介 在 Scikit-learn 中&#xff0c;神经网络是通过 sklearn.neural_network 模块提供的。最常用的神经网…...