【obd解析源码】【侧滑html源码】【火山开发源码】symlink源码

来源:微课堂源码文件

1.udev的rules定制和调试
2.使用lerna管理monorepo及发npm包实战教程

symlink源码

udev的rules定制和调试

       udev的rules定制和调试

        在定制项目中,对外设的热插拔的管理基本都在udev/systemd-udev来管理。这里没有对基本的udev使用/rules书写进行介绍。

        1. udev的rules可能的位置

        /lib/udev/rules.d -- udev默认/预置的rules

        /etc/udev/rules.d/ -- 定制的rules, 优先级高于/lib/udev/rules.d,官方建议客户写的rules都放这里

        至于放在哪个位置,自己决定就好,既然你在修改系统就应该知道你在做什么

        2. 定制自己的rules

        定制热插拔的事件,具体到rules就是:

          1)过滤到正确的udev事件。

          2)指定执行的动作,rules里的“RUN”,通常是脚本(毕竟要完成一个功能,绝大多数场景都不是一个命令能搞定的)

        3.到这里就要设计到rules的调试了

          1)如何知道要过滤的是条件?

          2)如何将必要的参数传递给RUN执行的脚本?

        方法1:

        udevadm monitor -p

        -- 监测所以的kernel/udevd的热插拔事件, -p选项很有必要,打印出本次热插拔事件的一些属性

       è¿™é‡Œå°±æ˜¯æ¯”较设备插入和拔出时的事件属性的不同,可作为过滤的条件

        比如:

        rules文件对于规则:

        到这里很多时候就能满足要求了,如果还有解决不里的场景,就要进一步修改过滤条件。

        man udev里会有绝大部分的关键字的信息(想全部的就只能去撸源码)。

       æ–¹æ³•2:

        通过在RUN指定的脚本里传递参数,来找到设备存在和不存在的属性差异。

        比如:

        参考信息:

        a)、udev 规则的匹配键

        ACTION:          事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 )。

        KERNEL:          内核设备名称,例如:sda, cdrom。

        DEVPATH:         设备的 devpath 路径。

        SUBSYSTEM:        设备的子系统名称,例如:sda 的子系统为 block。

        BUS:            设备在 devpath 里的总线名称,例如:usb。

        DRIVER:           设备在 devpath 里的设备驱动名称,例如:ide-cdrom。

        ID:             设备在 devpath 里的识别号。

        SYSFS{ filename}:     设备的 devpath 路径下,设备的属性文件“filename”里的内容。

                       例如:SYSFS{ model}==“STSS”表示:如果设备的型号为 STSS,则该设备匹配该 匹配键。

                       在一条规则中,可以设定最多五条 SYSFS 的 匹配键。

        ENV{ key}:          环境变量。在一条规则中,可以设定最多五条环境变量的 匹配键。

        PROGRAM:        调用外部命令。

        RESULT:           外部命令 PROGRAM 的返回结果。

        b)、udev 的重要赋值键

        NAME:           在 /dev下产生的设备文件名。只有第一次对某个设备的 NAME 的赋值行为生效,之后匹配的规则再对该设备的 NAME 赋值行为将被忽略。如果没有任何规则对设备的 NAME 赋值,udev 将使用内核设备名称来产生设备文件。

        SYMLINK:          为 /dev/下的设备文件产生符号链接。由于 udev 只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接。

        OWNER, GROUP, MODE:  为设备设定权限。

        ENV{ key}:         导入一个环境变量。

        c)、udev 的值和可调用的替换操作符

        Linux 用户可以随意地定制 udev 规则文件的值。例如:my_root_disk, my_printer。同时也可以引用下面的替换操作符:

        $kernel, %k:        设备的内核设备名称,例如:sda、cdrom。

        $number, %n:        设备的内核号码,例如:sda3 的内核号码是 3。

        $devpath, %p:       设备的 devpath路径。

        $id, %b:          设备在 devpath里的 ID 号。

        $sysfs{ file}, %s{ file}:    设备的 sysfs里 file 的内容。其实就是设备的属性值。

        $env{ key}, %E{ key}:   一个环境变量的值。

        $major, %M:        设备的 major 号。

        $minor %m:        设备的 minor 号。

        $result, %c:        PROGRAM 返回的结果。

        $parent, %P:          父设备的设备文件名。

        $root, %r:          udev_root的值,默认是 /dev/。

        $tempnode, %N:      临时设备名。

        %%:            符号 % 本身。

        $$:             符号 $ 本身。

        对比一下和man里的差别,$sysfs{ file},这个在实际解决问题的时候是很有用的。

        这种方法适合调试系统启动的时候对rules的调试,这个过程中是没得udevadmin monitor使用的。(当然,可以尝试自己写一个systemd启动服务,这就涉及到启动的时机、关联、影响,实际操作会比预想的复杂)

        这里提两个点:

        1. env - 可以是udev事件里的属性(-p打印的)

        2. $sysfs{ file}, 这里的file就是在系统/sys目录下对应的节点下的文件,有些情况下只能在sysfs的file的内存才能准确区分事件。

使用lerna管理monorepo及发npm包实战教程

       在维护多个package项目的同学来说,都会面临一个选择:这些package是放在一个仓库里维护还是放在多个仓库里单独维护。数量较少的时候,多个仓库维护不会有太大问题,但是当package数量逐渐增多时,一些问题逐渐暴露出来。obd解析源码

       因此,我们需要找寻一条新的道路来管理我们的项目,一个理想的开发环境可以抽象成这样:“只关心业务代码,可以直接跨业务复用而不关心复用方式,调试时所有代码都在源码中。”

       在前端开发环境中,多 Git Repo,多 npm 则是这个理想的阻力,它们导致复用要关心版本号,调试需要npm link。而这些是侧滑html源码Lerna + MonoRepo 最大的优势。

       什么是lerna

       用于管理具有多个包的JavaScript项目的工具。这个介绍可以说很清晰了,引入lerna后,上面提到的问题不仅迎刃而解,更为开发人员提供了一种管理多packages javascript项目的方式。

       什么是monorepo

       Monorepo 的全称是 monolithic repository,即单体式仓库,与之对应的是 Multirepo(multiple repository),这里的“单”和“多”是指每个仓库中所管理的模块数量。

       Multirepo 是比较传统的做法,即每一个 package 都单独用一个仓库来进行管理。例如:Rollup, ...

       Monorep 是把所有相关的 package 都放在一个仓库里进行管理,每个 package 独立发布。例如:React, Angular, Babel, Jest, Umijs, Vue ...

       了解了基本概念后,详细介绍下使用方法与api。

       常用命令

       我们需要全局安装lerna工具。火山开发源码

       为所有项目安装依赖,类似于npm/yarn i

       提交对项目的更新 运行该命令会执行如下的步骤:

       使用lerna 初始化项目

       类似npm init命令

       为packages文件夹下的package安装依赖

       卸载依赖

       比对包是否发生过变更

       显示packages下的各个package的version

       清理node_modules

       lerna run 运行npm script,可以指定具体的package。

       lerna.json解析

       version:当前库的版本

       useWorkspaces: 是否使用workspace来管理依赖 npmClient: 允许指定命令使用的client, 默认是 npm, 可以设置成 yarn command.publish.ignoreChanges:可以指定那些目录或者文件的变更不会被publish command.bootstrap.ignore:指定不受 bootstrap 命令影响的包 command.bootstrap.npmClientArgs:指定默认传给 lerna bootstrap 命令的参数 command.bootstrap.scope:指定那些包会受 lerna bootstrap 命令影响 packages:指定包所在的目录

       使用lerna的基本工作流

       环境配置

       初始化一个lerna工程

       在本地目录下初始化一个lerna工程。 1、创建一个空的文件夹,命名为my-app:

       2、初始化 通过cmd进入相关目录,进行初始化

       3、添加一个测试package 默认情况下,package是放在packages目录下的。但是自己想做一个组件库,改为了components

       4、安装各packages依赖 这一步操作,iOS声控跳跃源码官网上是这样描述的 在当前的Lerna仓库中引导包。安装所有依赖项并链接任何交叉依赖项。

       5、发布 在发布的时候,就需要git工具的配合了。 所以在发布之前,请确认此时该lerna工程是否已经连接到git的远程仓库。你可以执行下面的命令进行查看。 本篇文章的代码托管在Github上。因此会显示此远程链接信息。 如果你还没有与远程仓库链接,请首先在github创建一个空的仓库,然后根据相关提示信息,进行链接。

       第一次publish前我们需要执行

       在输入用户名及密码之后执行这条命令

       你就可以根据cmd中的提示,一步步的Stl源码剖析 萃取发布packges了。 实际上在执行该条命令的时候,lerna会做很多的工作。

       到这里为止,就是一个最简单的lerna的工作流了。但是lerna还有更多的功能等待你去发掘。生成的packages如下:

       工作模式

       lerna有两种工作模式,Independent mode和Fixed/Locked mode,在这里介绍可能会对初学者造成困扰,但因为实在太重要了,还是有必要提一下的。 lerna的默认模式是Fixed/Locked mode,在这种模式下,实际上lerna是把工程当作一个整体来对待。每次发布packges,都是全量发布,无论是否修改。但是在Independent mode下,lerna会配合Git,检查文件变动,只发布有改动的packge。

       使用lerna提升开发流程体验

       接下来,我们从一个demo出发,了解基于lerna的开发流程。

       项目初始化

       我们需要维护一个UI组件库,其包含2个组件,分别为House(房子)和Window(窗户)组件,其中House组件依赖于Window组件。

       增加依赖

       接下来,我们来为组件增加些依赖,首先House组件不能只由Window构成,还需要添加一些外部依赖(在这里我们假定为lodash)。我们执行:

       这句话会将lodash增添到House的dependencies属性里 我们还需要将Window添加到House的依赖里,执行:

       自动检测到window隶属于当前项目,直接采用symlink的方式关联过去。 symlink:符号链接,也就是平常所说的建立超链接,此时House的node_modules里的Window直接链接至项目里的Window组件,而不会再重新拉取一份,这个对本地开发是非常有用的。

       发布到npm

       接下来,我们只需要简单地执行lerna publish,确认升级的版本号,就可以批量将所有的package发布到远程。 默认情况下会推送到系统目前npm对应的registry里,实际项目里可以根据配置package.json切换所使用的npm客户端。

       更新模块

       接下来,我们变更了Window组件,执行一下lerna updated,便可以得知有哪些组件发生了变更。

       我们可以看到,虽然我们只变更了window组件,但是lerna能够帮助我们检查到所有依赖于它的组件,对于没有关联的组件,是不会出现在更新列表里的,这个对于相比之前人工维护版本依赖的更新,是非常稳健的。

       集中版本号或独立版本号

       截止目前,我们已经成功发布了2个package,现在再新增一个Tree组件,它和其他2个package保持独立,随后我们执行lerna publish,它会提示Tree组件的版本号将会从0.0.0升级至1.0.0,但是事实上Tree组件仅仅是刚创建的,这点不利于版本号的语义化,lerna已经考虑到了这一点,它包含2种版本号管理机制。

       如果需要各个组件维护自身的版本号,那么就使用independent模式,只需要去配置leran.json即可。

       TIPS:

       yarn workspaces 命令 在根目录安装 npm 包,以 lodash 为例:

       总结

       lerna不负责构建,测试等任务,它提出了一种集中管理package的目录模式,提供了一套自动化管理程序,让开发者不必再深耕到具体的组件里维护内容,在项目根目录就可以全局掌控,基于npm scripts,可以很好地完成组件构建,代码格式化等操作,并在最后一公里,用lerna变更package版本,将其上传至远端。

       lerna最佳实践

       项目地址: GitHub - Mrrabbitan/virtualList 为了能够使lerna发挥最大的作用,根据这段时间使用lerna 的经验,总结出一个最佳实践。下面是计划实现的一些特性。

       工具整合 在这里引入的工具都是为了解决一个问题,就是工程和代码的规范问题。

       Happy Hacking~~~

文章所属分类:娱乐频道,点击进入>>