前端架构师-week3-脚手架执行准备过程实现

目录​​​​​​​​​​​​​​ 

脚手架框架代码拆包 + import-local应用  

检查版本号功能开发(require加载资源类型讲解 + npmlog封装)

最低Node版本检查功能开发

root 账号启动检查和自动降级功能开发

用户主目录检查功能开发

入参检查和 debug 模式开发

环境变量检查功能开发

通用 npm API 模块封装

npm 全局更新功能开发


脚手架框架代码拆包 + import-local应用  

core > cli > bin > index.js中

#! /usr/bin/env node

const importLocal = require('import-local');

if (importLocal(__filename)) {
  require('npmlog').info('cli', '正在使用 imooc-cli 本地版本');
} else {
  require('../lib')(process.argv.slice(2));
}

检查版本号功能开发(require加载资源类型讲解 + npmlog封装)

require加载资源类型讲解:

        支持三种类型:.js / .json / .node

        .js -> module.exports / exports

        .json -> JSON.parse()

        .node -> 是一个c++的插件,通过 process.dlopen 打开

        any -> 通过 js 引擎解析

可以定义一个专门的 log 类,在 utils 中定义一个 log package:

lerna create @imooc-cli-dev/log

调整 .log 目录位置,修改 log/lib/log.js 名字为 index.js(package.json中对应修改)。

lerna add npmlog utils/log/

在 core/cli 模块中调用 log package,在 core/cli/package.json 中注册:

"dependencies": {
    "@imooc-cli-dev/log": "file:../../utils/log",
    "@imooc-cli-dev/init": "file:../../commands/init",
    "import-local": "^3.0.2",
    "npmlog": "^4.1.2"
  },
cd core/cli/
npm link
// log/lib/index.js 中

'use strict';

const log = require('npmlog');

log.level = process.env.LOG_LEVEL ? process.env.LOG_LEVEL : 'info'; // 判断debug模式

log.heading = 'imooc'; // 修改前缀
log.addLevel('success', 2000, { fg: 'green', bold: true }); // 添加自定义命令

module.exports = log;

最低Node版本检查功能开发

        使用的 node api,在低版本的时候是不支持的。要设置一个最低的版本号。

semver库作用:

        用来做各种各样版本号比对的。

//用法

const semver = require('semver')

semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean('  =v1.2.3   ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
semver.minVersion('>=1.0.0') // '1.0.0'
semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'

colors库作用:

        Get colors in your node.js console 

var colors = require('colors/safe');
 
console.log(colors.green('hello')); // outputs green text
console.log(colors.red.underline('i like cake and pies')) // outputs red underlined text
console.log(colors.inverse('inverse the color')); // inverses the color
console.log(colors.rainbow('OMG Rainbows!')); // rainbow
console.log(colors.trap('Run the trap')); // Drops the bass

引入和实现代码:

lerna add semver core/cli/
lerna add colors core/cli/
function checkNodeVersion() {
    const currentVersion = process.version;
    const lowestVersion = constant.LOWEST_NODE_VERSION;
    if (!semver.gte(currentVersion, lowestVersion)) {
        throw new Error(colors.red(`imooc-cli 需要安装 v${lowestVersion} 以上版本的 Node.js`))
    }
}

root 账号启动检查和自动降级功能开发

        需要对操作系统比较了解,才能理解。脚手架需要频繁读写文件,root 账号会导致权限频繁报错,需要进行降级处理。

判断 root 环境:

process.getuid && process.getuid() == 0

process.setuid()

process.setgid() //分组id

process.env //环境变量

process //node进程信息

root-check 库作用:

        Try to downgrade the permissions of a process with root privileges and block access if it fails

//用法

import rootCheck from 'root-check';

rootCheck();

引入和实现代码:

lerna add root-check core/cli/

        在 core/cli/ 命令行中 npm link

function checkRoot() {
  const rootCheck = require('root-check');
  rootCheck();
}

用户主目录检查功能开发

user-home库作用:

        跨操作系统获取系统主目录。已弃用。

        Deprecated. Just use import {homedir} from 'os';

//用法

const userHome = require('user-home');

console.log(userHome);
//=> '/Users/sindresorhus'

path-exists库作用:

        判断文件是否存在。 

        原理:fs.accessSync(path);

//用法

// foo.js
import {pathExists} from 'path-exists';

console.log(await pathExists('foo.js'));
//=> true

引入和实现代码:

lerna add user-home core/cli/

lerna add path-exists core/cli/

        在 core/cli/ 命令行中 npm link

function checkUserHome() {
  if (!userHome || !pathExists(userHome)) {
    throw new Error(colors.red('当前登录用户主目录不存在!'));
  }
}

入参检查和 debug 模式开发

入参检查目的:看一下是否进入调试模式。

minimist库作用:

        parse argument options

//用法

var argv = require('minimist')(process.argv.slice(2));
console.log(argv);


$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }


$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{
	_: ['foo', 'bar', 'baz'],
	x: 3,
	y: 4,
	n: 5,
	a: true,
	b: true,
	c: true,
	beep: 'boop'
}

引入和实现代码: 

        core/cli/ 命令行中执行 npm install -S minimist 

function checkInputArgs() {
    const minimist = require('minimist')
    args = minimist(process.argv.slice(2))
    checkArgs()
}

function checkArgs() {
    if (args.debug) {
        process.env.LOG_LEVEL = 'verbose'
    } else {
        process.env.LOG_LEVEL = 'info'
    }
    log.level = process.env.LOG_LEVEL
}

环境变量检查功能开发

重要意义:可以在操作系统当中配置一些环境变量,将用户名密码等敏感信息保存在用户本地。而不用集成到代码当中,我们需要时就可以实时进行读取。同时我们还可以修改默认的配置信息。

        通过环境变量在全局进行获取,操作系统打开以后,不管哪个软件之中都可以获取的到。共享一份。

dotenv库作用:

        Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.

//用法

//Create a .env file in the root of your project:

S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"

//As early as possible in your application, import and configure dotenv:

require('dotenv').config()
console.log(process.env) // remove this after you've confirmed it is working

引入和实现代码:

         core/cli/ 命令行中执行 npm install -S dotenv

const userHome = require('user-home');

function checkEnv() {
  const dotenv = require('dotenv');
  const dotenvPath = path.resolve(userHome, '.env');
  if (pathExists(dotenvPath)) {
    dotenv.config({
      path: dotenvPath,
    });
  }
  createDefaultConfig();
}

function createDefaultConfig() {
  const cliConfig = {
    home: userHome,
  };
  if (process.env.CLI_HOME) {
    cliConfig['cliHome'] = path.join(userHome, process.env.CLI_HOME);
  } else {
    cliConfig['cliHome'] = path.join(userHome, constant.DEFAULT_CLI_HOME);
  }
  process.env.CLI_HOME_PATH = cliConfig.cliHome;
}

//最终缓存路径 /Users/sam/.imooc-cli

通用 npm API 模块封装

url-join库作用: 

        Join all arguments together and normalize the resulting URL.

//用法

import urlJoin from 'url-join';

const fullUrl = urlJoin('http://www.google.com', 'a', '/b/cd', '?foo=123');

console.log(fullUrl);

//Prints:
//'http://www.google.com/a/b/cd?foo=123'

步骤:

        1. 获取当前版本号和模块名

        2. 调用 npm API(https://registry.npmjs.org/模块名称、https://registry.npm.taobao.org/模块名称 ),获取所有版本号

        3. 提取所有版本号,比对哪些版本号是大于当前版本号

        4. 获取最新的版本号,提示用户更新到该版本 

操作:

lerna create get-npm-info ./utils/get-npm-info

        看实际情况调整 get-npm-info package 位置,lib/get-npm-info.js 改为 lib/index.js,package.json 中 main 属性相应修改。

//core/cli 的 package.json 中注册

"dependencies": {
    "@imooc-cli-dev/get-npm-info": "file:../../utils/get-npm-info",
    "colors": "^1.4.0"
}

//core/cli 命令行中执行 npm link
lerna add axios utils/get-npm-info/

lerna add semver utils/get-npm-info/

lerna add url-join utils/get-npm-info/


// utils/get-npm-info/命令行中
npm link

npm 全局更新功能开发

async function checkGlobalUpdate() {
  const currentVersion = pkg.version;
  const npmName = pkg.name;
  const { getNpmSemverVersion } = require('@imooc-cli-dev/get-npm-info');
  const lastVersion = await getNpmSemverVersion(currentVersion, npmName);
  if (lastVersion && semver.gt(lastVersion, currentVersion)) {
    log.warn(colors.yellow(`请手动更新 ${npmName},当前版本:${currentVersion},最新版本:${lastVersion}
                更新命令: npm install -g ${npmName}`));
  }
}
'use strict';

const axios = require('axios');
const urlJoin = require('url-join');
const semver = require('semver');

function getNpmInfo(npmName, registry) {
  if (!npmName) {
    return null;
  }
  const registryUrl = registry || getDefaultRegistry();
  const npmInfoUrl = urlJoin(registryUrl, npmName);
  return axios.get(npmInfoUrl).then(response => {
    if (response.status === 200) {
      return response.data;
    }
    return null;
  }).catch(err => {
    return Promise.reject(err);
  });
}

function getDefaultRegistry(isOriginal = false) {
  return isOriginal ? 'https://registry.npmjs.org' : 'https://registry.npm.taobao.org';
}

async function getNpmVersions(npmName, registry) {
  const data = await getNpmInfo(npmName, registry);
  if (data) {
    return Object.keys(data.versions);
  } else {
    return [];
  }
}

function getSemverVersions(baseVersion, versions) {
  return versions
    .filter(version => semver.satisfies(version, `>${baseVersion}`))
    .sort((a, b) => semver.gt(b, a) ? 1 : -1);
}

async function getNpmSemverVersion(baseVersion, npmName, registry) {
  const versions = await getNpmVersions(npmName, registry);
  const newVersions = getSemverVersions(baseVersion, versions);
  if (newVersions && newVersions.length > 0) {
    return newVersions[0];
  }
  return null;
}

async function getNpmLatestVersion(npmName, registry) {
  let versions = await getNpmVersions(npmName, registry);
  if (versions) {
    return versions.sort((a, b) => semver.gt(b, a))[0];
  }
  return null;
}

module.exports = {
  getNpmInfo,
  getNpmVersions,
  getNpmSemverVersion,
  getDefaultRegistry,
  getNpmLatestVersion,
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chengbo_eva

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值