本周整体内容介绍和学习方法 标题
脚手架需求分析和架构设计,核心流程开发
收获
主要内容
加餐
Node项目如何支持ES Module
2-1 大厂是如何做项目的
2-2 前端研发过程中的痛点和需求分析
2-3 加餐:大厂的git操作规范是怎样的?
2-4 高端操作:脚手架架构设计+绘制架构图 / 2-5 架构设计图绘图技巧分享
3-1 脚手架模块拆分策略
3-2 core模块技术方案
准备阶段:
4-1 脚手架框架代码拆包+import-local应用
{
"packages": [
"core/*",
"commands/*",
"models/*",
"utils/*"
],
"version": "1.0.4"
}
……
"bin": {
"cloudscope-cli": "bin/index.js"
},
……
"dependencies": {
"@cloudscope-cli/utils": "file:../../utils/utils",
"import-local": "^3.0.2",
"npmlog": "^4.1.2"
},
#! /usr/bin/env node
const importLocal = require('import-local')
if(importLocal(__filename)){
require('npmlog').info('cli','正在使用 cloudscope-cli 本地版本')
}else{
require('../lib')(process.argv.slice(2))
}
git代码提交扩展
我将此代码通过分支的形式,对每一次的代码提交,都在一个特殊的分支进行代码提交。 本节提交到该分支: lesson01 下面是分支提交小记录。
4-2 检查版本号功能开发(require加载资源类型讲解+npmlog封装)
从本节开始本地新建分支 lesson02,最后将此分支代码推送至远程仓库cloudscope-cli。
4-3 最低Node版本检查功能开发
检查Node版本号的原因以及解决办法:
4-4 root账号启动检查和自动降级功能开发
检查账号权限原因以及解决方法:
4-5 用户主目录检查功能开发
4-6 入参检查和debug模式开发
这里就进行如参检查,是要判断是否进入调试模式,如果带有 --debug参数,我们要进行log的level设置。
4-7 环境变量检查功能开发
4-8 通用npm API模块封装 | 4-9 npm全局更新功能开发
准备阶段的最后一个功能:检查我们的这个脚手架是否为最新版本
步骤:
npm提供了这样一个API: https://registry.npmjs.org/cloudscope-cli/core ,可以获得该包的所有版本号,要从这里拿到所有版本号,我们需要使用第三方库 axios,同时我们也需要添加一个用来url拼接的库:url-join,可以帮助我们进行多参数的拼接,以及我们进行版本对比的第三方库 semver。
将以上代码提交支仓库远程cloudscope-cli的分支 lesson02,并合并至main分支。 **
5-1 快速实现一个commander脚手架 | 5-2 commander脚手架全局配置
之前在学习命令注册的时候,使用的是yrags,本节使用另一个库 commander去实现命令注册 本节代码提交至:liugezhou-yargs-demo 其中 bin/yargs.js是之前学习yargs的demo代码。 bin/commander.js是本节关于commander的代码。 我们在这个库的基础上,学习commander的简单用法.
#!/usr/bin/env node
const commander = require('commander')
const pkg = require("../package.json")
// 获取commander的单例
// const {program} = commander
// 手动实例化一个Command示例
const program = new commander.Command()
program
.name(Object.keys(pkg.bin)[0])
.usage('<command> [options]')
.version(pkg.version)
.option('-d, --debug', '是否开启调试模式', false)
.option('-e, --envName <envName>' , '环境变量')
.parse(process.argv);
const options = program.opts()
console.log(options.debug)
program.outputHelp() //打印出帮助信息
课程所讲内容:commander命令注册有两种方式:
现在默认安装commander时,已更新到7.0.0,sam老师写法还是6.X,可参考 commader for git 配置。本节内容就是对官方文档更新用法之后的学习笔记:
完整的node.js命令行解决方法
为简化声明,Commander提供了一个全局对象
const { program } = require('commander')
program.version('0.0.1')
若程序较为复杂,用户需要以多种方式来使用Commander,如单元测试等,可采用创建本地Commander对象的方法
const {Command } = require('commander')
const program = new Command();
program.version('0.0.1')
program
//Commander 使用.option() 方法来定义选项,同时可以附加选项的简介
.option('-d,--debug','booelan')
//选项可以设置一个默认值。
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
//必填选项
.requiredOption('-n, --name <type>', 'name must have cheese');
//通过program.parse(arguments)方法处理参数
program.parse(process.argv)
const ret = program.opts()
const debug = ret.debug
program.
//参数支持必须<>,可选[]
command('clone <source> [destination]')
//在参数名后加上...来声明可变参数,且只有最后一个参数支持这种用法
program
.command('rmdir <dirs...>')
.action(function (dirs) {
dirs.forEach((dir) => {
console.log('rmdir %s', dir);
});
});
5-4 commander注册命令的两种高级用法 |5-5 再讲3条commander的高级用法
program
.command('install [name]','install package',{
executableFile:'vue',
isDefault:true,
hidden:true //command的隐藏
})
.alias('i')
program.on('optins:debug',function(){
if(program.debug){
process.env.LOG_LEVEL = 'verbose'
}
}
program.on('command:*',function(obj){
console.log(obj)
console.log('未知的命令:' + obj[0])
const avaliableCommands = program.commands.map( cmd => cmd.name())
console.log('可用命令:'+ avaliableCommands.join(','))
})
6-1 通过webpack完成ES Module资源构建 模块化
实现
//webpack-config.js
const path = require('path')
module.exports = {
entry: './bin/core.js',
output:{
path:path.join(__dirname,'/dist'),
filename:'core.js'
},
mode:'development'
}
// index.js
#! /usr/bin/env node
require('./core')
// core.js
import utils from './utils'
utils()
// utils
module.exports = function(){
console.log('kskaksk')
}
6-2 通过webpack target属性支持Node内置库
// npm i -S path-exists
// bin/utils.js
import pathExists from 'path-exists'
export function exists(p){
return pathExists.sync(p)
}
// bin/core.js
import path from 'path'
import {exists} from './utils'
console.log(path.resolve('.'))
console.log(exists(path.resolve('.')))
// webpack.config.js
...
target:"node"
(async function(){
await new Promise(resolve => setTimeout( resolve,1000));
console.log('ok')
})()
6-3 webpack loader配置babel-loader支持低版本node
配置一个最简单babel-loader,需要安装的库 npm i -D babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime @babel/runtime-corejs3
const path = require('path')
module.exports = {
entry:'./bin/core.js',
output:{
path: path.join(__dirname,'/dist'),
filename:'core.js'
},
mode:'development', //开发模式
// target: 'web'//默认
target:'node', // 识别内置库
module:{
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets:['@babel/preset-env'],
plugins: [
[
'@babel/plugin-transform-runtime',
{
corejs:3,
regenerator:true,
useESModules:true,
helpers: true
}
]
]
}
}
}
]
}
}
6-4 通过Node原生支持ES Module
将node版本升级到14.x,代码中将引用的文件,改写后缀名为 .mjs即可。