1.脚手架初认识
2.自定义sonar插件-脚手架
3.UMI3源码解析系列之构建原理
脚手架初认识
脚手架是脚手架系构建开发工具的核心组件,它们简化复杂过程,统源加速项目开发。码脚例如,手架Vue-cli、代码npm 和 commitizen 等工具都是脚手架系taskctl 源码脚手架的具体体现,分别用于搭建 Vuejs 项目、统源依赖管理与规范化的码脚 Git commit。这些工具帮助开发者专注于业务逻辑,手架提高效率。代码
本文将带你深入理解前端脚手架,脚手架系适合想自己构建脚手架但不知从何开始的统源开发者。你将学习如何搭建一个脚手架工程、码脚实现开发与调试过程,手架以及处理命令参数。代码m8源码通过实践,你会掌握如何构建一个完整的脚手架应用。
本文的完整代码已上传至 GitHub,你可直接查看源代码。
实现一个脚手架工程,首先需要创建入口文件(/bin/index.js),并使用 /src 目录存放业务逻辑代码。为了支持使用 ES6 语法,需要安装 Babel 转译工具。尝试不使用 Babel 直接使用 ES6 语法,你会发现无法识别 `export` 语法,这是因为 Node.js 默认遵循 CommonJS 规范。在使用 ES6 语法后,还需将 ESM 编译为 CommonJS 格式,59公里源码以便 Node.js 可执行。
接着,修改 /src/index.js 文件以处理命令参数。通过 yargs 提供的命令参数解析,你可以通过 `yargs.argv.name` 获取到相关参数值。此外,将功能分散到不同的子命令中,避免将所有功能集中在一个命令中。使用 `yargs.command` 方法设置子命令,实现功能模块化。
以文件拷贝功能为例,通过 `yargs.command` 添加拷贝子命令,并在 /src/copy/index.js 中实现逻辑。使用 `process.argv` 获取命令参数,免维护影视源码根据参数执行拷贝操作。如果输入不存在的命令参数,系统将提示错误信息。
为了提升用户体验,引入 `inquirer` 库来创建交互式命令,允许用户输入各种信息,如模板文件名称、模板类型等。通过 `inquirer.prompt` 接收用户输入,根据输入执行相应的操作。将询问式交互集成到脚手架中,使操作更加灵活。
在处理路径问题时,若项目名称已存在,源码需上门自取需要询问用户是否覆盖当前文件夹,而不是直接终止进程。通过 `inquirer` 的 `isOverride` 方法实现交互式决策,为用户提供选择。
本文内容已详尽覆盖前端脚手架的构建过程与优化方法。通过实践,你将掌握构建高效、用户友好的脚手架技术。记得将完整代码保存至 GitHub,持续研究与实践,提升你的前端开发能力。
更多前端学习资源与实践案例,请访问我的 GitHub 仓库。期待你的关注与分享!
自定义sonar插件-脚手架
企业需求多样化,标准的sonar规则集及阿里的P3C规则集难以满足所有场景。故此,自定义sonar插件成为企业优化代码质量的必要手段。鉴于当前自定义插件开发缺乏统一框架,实现过程复杂,本文章提供了一个易于遵循的骨架项目(请访问文末提供的GitHub源码),旨在简化开发者自定义sonar插件的流程。
针对sonar 7.9版本,我们构建了自定义sonarPMD插件的骨架项目,其余版本只需调整相关项目版本即可。此框架主要基于以下两个项目进行源码修改以实现兼容性。
项目适用版本为sonar 7.9。
该项目包含以下三个模块:
1. **integration-test**:负责集成测试,确保自定义功能的正确性。
2. **sonar-pmd-custom-rules**:此模块用于编写及验证自定义规则,编写完毕后,将规则安装至本地仓库。
3. **sonar-pmd-plugin**:负责集成 **sonar-pmd-custom-rules** 模块,生成sonar插件。
若无需自定义规则集,开发者可直接从 **2. 开发一个自定义规则** 部分开始操作。整个流程包括:
1. **自定义规则集**:根据需求创建新规则。
2. **开发一个自定义规则**:遵循项目文档编写规则。
3. **测试你的规则**:通过集成测试验证规则效果。
4. **在sonar中导入你的规则**:将自定义规则集成至sonar环境。
完整项目源码已提供,期待您的探索与贡献,共同提升代码质量。
UMI3源码解析系列之构建原理
基于前面umi插件机制的原理可以了解到,umi是一个插件化的企业级前端框架,它配备了完善的插件体系,这也使得umi具有很好的可扩展性。umi的全部功能都是由插件完成的,构建功能同样是以插件的形式完成的。下面将从以下两个方面来了解umi的构建原理。UMI命令注册想了解umi命令的注册流程,咱们就从umi生成的项目入手。
从umi初始化的项目package.json文件看,umi执行dev命令,实际执行的是start:dev,而start:dev最终执行的是umidev。
"scripts":{ "dev":"npmrunstart:dev","start:dev":"cross-envREACT_APP_ENV=devMOCK=noneUMI_ENV=devumidev"}根据这里的umi命令,我们找到node_modules里的umi文件夹,看下umi文件夹下的package.json文件:
"name":"umi","bin":{ "umi":"bin/umi.js"}可以看到,这里就是定义umi命令的地方,而umi命令执行的脚本就在bin/umi.js里。接下来咱们看看bin/umi.js都做了什么。
#!/usr/bin/envnoderequire('v8-compile-cache');constresolveCwd=require('@umijs/deps/compiled/resolve-cwd');const{ name,bin}=require('../package.json');constlocalCLI=resolveCwd.silent(`${ name}/${ bin['umi']}`);if(!process.env.USE_GLOBAL_UMI&&localCLI&&localCLI!==__filename){ constdebug=require('@umijs/utils').createDebug('umi:cli');debug('Usinglocalinstallofumi');require(localCLI);}else{ require('../lib/cli');}判断当前是否执行的是本地脚手架,若是,则引入本地脚手架文件,否则引入lib/cli。在这里,我们未开启本地脚手架指令,所以是引用的lib/cli。
//获取进程的版本号constv=process.version;//通过yParser工具对命令行参数进行处理,此处是将version和help进行了简写constargs=yParser(process.argv.slice(2),{ alias:{ version:['v'],help:['h'],},boolean:['version'],});//若参数中有version值,并且args._[0]为空,此时将version字段赋值给args._[0]if(args.version&&!args._[0]){ args._[0]='version';constlocal=existsSync(join(__dirname,'../.local'))?chalk.cyan('@local'):'';console.log(`umi@${ require('../package.json').version}${ local}`);//若参数中无version值,并且args._[0]为空,此时将help字段复制给args._[0]}elseif(!args._[0]){ args._[0]='help';}处理完version和help后,紧接着会执行一段自执行代码:
(async()=>{ try{ //读取args._中第一个参数值switch(args._[0]){ case'dev'://若当前运行环境是dev,则调用Node.js的核心模块child_process的fork方法衍生一个新的Node.js进程。scriptPath表示要在子进程中运行的模块,这里引用的是forkedDev.ts文件。constchild=fork({ scriptPath:require.resolve('./forkedDev'),});//ref:///api/process/signal_events.html///post/