edp
edp copied to clipboard
[package]edp-package流程整理
@leeight 因为现在的edp-package
在使用过程中还是有不少细节有问题的,这些细节很难说清楚,所以我整理了一个我认为合理的流程,看看是否能采纳到现在的功能中
第一次写完发现自己想的不对,又重写了一下……其实import
和update
就是同一个过程,只有一些细枝末节上是不同的,所以我整理成一个流程了
效果
- 被使用者明确指定的包是不用让使用者确认的,都明确输入指令要引入/更新一个包了,再问它“是否要引入/更新XXX”是多余的
- 如果一个包在本地是没有的,但edp判断这个包是需要的(被依赖),也不用问用户要不要引入,不引入就完蛋了
- 在
import
或update
过程中,是可能涉及已经存在的包的update
的,此时是需要询问用户的,要按照下面说的的流程进行 - 开发者指定
import
一个已经存在的包不应该被允许,应该提示“请使用edp update
”。同样update
一个不存在的包也是不行的 -
import
或update
过程不应该把未指定的包(如被依赖的包)加入到package.json
中,比如我edp import er
,你不能在package.json
的dep
中加上eoo
这一项 - 任何时候不要依赖
dep
下有多少目录,这个逻辑肯定是不对的,package.json
和module.conf
才是入口
使用方法
-
edp import/update package
用来拉取1个指定的包,区别就在上面说的,已经存在的包不能import
,不存在的包不能update
-
edp import/update package package ...
用来拉取n个指定的包,此过程是对过程1的n次重复,这N交是串行的(并行会让你在处理依赖的时候头疼),任意一次失败都不应该影响其它的拉取,完成后提示“xxx包拉取失败”,以便使用者补救 -
edp import/update
没有参数时根据package.json
来拉取所有需要的依赖,此过程是从package.json
中读取包列表并执行过程2,注意这里看package.json
就行,如果一个包不在package.json
中,且不会在其它包更新过程中因为依赖问题一起更新的话,说明这个包根本没用了,没删掉它已经很客气了还更新啥 -
edp import/update url
根据URL来拉取1个指定的包,这个过程是第1步的子集,具体对照下文的流程应该比较容易理解
拉取单个包的流程
针对过程1,其实际执行应该是这样的:
- 从registry查找对应的meta信息
- 根据meta信息找符合指定版本要求(从
package.json
来或者@xxx
指定的)的最新版本 - 根据第2步拿到的版本,去registry拿这个版本对应的package.json【注1】
- 根据
package.json
找到所有的依赖 - 对每个依赖,重复1-4的过程,把整个依赖树建起来
- 把这个树合并成一个数组,合并时注意根据包名去重,数组中每一项是
{packageName, version}
,一个包在数组中应该只出现一次【注2】 - 根据第6步得出的数组,查看每一项,按以下分支走
- 如果本地有了,并且我们需要的版本比本地存在的更新(版本更新通过本地的
package.json
里的version
比较),则询问用户“是否把xxx从1.0更新至2.0”,用户选Yes则下载更新,选No则跳过。下载更新是简单粗暴地“删除本地再下载安装”的过程(后续会加MD5比对之类的需求,所以不要和下面第3步的直接安装混在一起) - 如果本地有了,且本地的版本比我们要的还新,直接跳过
- 本地没有这个包,则直接下载安装,不用问用户
- 如果本地有了,并且我们需要的版本比本地存在的更新(版本更新通过本地的
- 全搞完后更新
module.conf
以上步骤中有任何一步出错,整个过程回滚,打印错误信息,应该就像什么都没发生过一样,不能有残留的文件变更出现
【注1】如果用的是edp import/update url
拉某个URL的话,此时没有registry,所以是直接拉下来进第4步就行
注意这种直接从URL拉过来的东西,不要在package.json
里留下dependencies
项,不然会影响以后的edp update
更新所有包(会在registry上找不到这个包),这种包以后更新也肯定是edp update url
更新的,在package.json
中出现没有用
【注2】这里涉及到多个包依赖同一个包且版本要求不同时的原则,比如foo
依赖[email protected]
,bar
依赖[email protected]
,而当前的underscore
版本是1.7.2
:
- 找符合一个包的要求的最新的,则因为
1.7.2
符合1.x
,所以使用1.7.2
- 找符合所有包的要求最新的,则用
1.5.6
另外,有可能foo
和bar
依赖的版本根本是冲突的,比如1.5.x
和1.7.x
,那么也要考虑上面2个原则用哪个,反正edp是不支持多版本共存和map
的自动配置了,要玩开发者自己去玩儿去
我建议采用选新的方式,上面的案例我们用1.7.2
的
总结和关键点
-
import
和update
的流程是高度相同的 - 拉取
package.json
这事似乎是做不到的,要拉取整个包再解压找package.json
,但后续下载安装又会用到这个包,所以这里设个缓存避免多次的下载 - 全程我们只看项目及各个包的
package.json
,不要有其它的信息来干扰 - 询问最少原则,只在本地有这个包且版本比较旧时才触发询问,一个包也只应该被询问一次(这就是建立依赖树再打平成数组的目的)
- 要考虑
v1
和v2
的两种layout
其它功能
-
edp import
应该增加--save
参数来指定要不要更新package.json
- 最好有个
edp dep
来查看整个依赖树关系 - 【非常未来】考虑到通过配置
require.config
多版本并存、包改名等情况,事实上整个过程是需要结合module.conf
里的信息的,比如edp update er
但可能因为require.config
里的packges
里把er
配成了mvc
,那么比对版本的时候就要看dep/mvc
这个目录。但现在没有去实现它的必要
@leeight 现在有人做不,没有的话7月我看一下算了?
好,交给你了
有一个问题,上面的方案认为module.conf
用于存储项目当前引入包的源信息。但是包改名、多版本并存之类的事情就没法支持了。是不是应该有个新的隐藏文件,用于存储当前引入包的源信息,而module.conf
经过这个文件生成。
其实,最初设计的时候,module.conf
仅仅是用于生成require.config的
另外,原先有部分依赖包信息是存在.edpproj文件里的,是继续保留,还是废掉这个逻辑,必须存package.json?
我个人建议是废掉
另外, @beenlee 从package.json里读dependencies的逻辑是这样的:
先看存不存在edp.dependencies,再看存不存在efe.dependencies,再看存不存在dependencies
@errorrik edp.dependencies, efe.dependencies, dependencies这三个是什么区别,在import时是按什么规则写入的? 现在的逻辑好像是将依赖写入到package.json的edp.dependencies,如果没有这个文件,就尝试去找.edpproj下的metadata写到metadata的dependencies里 那个efe.dependencies是什么情况下写入的呢。
先说dependencies
和edp.dependencies
。
在通常情况下看来,一个package的依赖,应该写在dependencies里,这很好理解。但是有一种特殊的情况:这个package是一个浏览器端和browser端都能跑的package,甚至这就是一个node写的业务项目。
在上面的情况下,node package的依赖与browser的依赖很可能不同。所以我们需要两个:
-
dependencies
node 依赖 -
edp.dependencies
browser 依赖
但是,大部分情况下,我们的包是纯粹的(就是个browser package或者node package)。如果我是单纯的browser package,但是我非要写edp.dependencies
,又会觉得很sb。直接写dependencies
就好了。
edp-package是管理browser package的。综上,处理逻辑就会变成:
- 如果有
edp.dependencies
,就认它 - 如果没有,就认
dependencies
那么在最后,efe.dependencies
是个什么鬼货色呢?其实丫啥也不是,现在没有任何地方实现它。因为efe代表的是技术体系,edp代表的是开发平台,所以我个人觉得可能efe.dependencies
会更好些。但是想了想,没必要搞这么多名字出来。考虑dependencies
和edp.dependencies
就好了。如果想要扩展性好点,可以留出配置口。
看到在说这个区别,我补一下,请顺便把main
的问题解决了,对edp
来说main: 'foo'
会想找src/foo.js
,而node并不会,这个需要区别对待
我们是否应该期待所有的配置都在edp
下可以被override呢
我们是否应该期待所有的配置都在edp下可以被override呢
我觉得可以,再想想除了main好像也没别的了。devDependencies?
比如oo
我们其实就想叫oo
的,但是在npm上显然这名字已经占用了,所以最后改叫eoo
了
不过name
要这么做的话,得 @leeight 那边的registry有支持
我觉得可以,再想想除了main好像也没别的了。devDependencies?
或者改成 edp:main
/ efe:main
/ amd:main
之类的?
我们是否应该期待所有的配置都在edp下可以被override呢
override的目的就是为了少写点儿配置?
我觉得可以,再想想除了main好像也没别的了。devDependencies?
实用角度看有着四个:name, main, dependencies, devDependencies 但也有其他字段需覆盖的场景,比如发版时指定各自的 files、private 等,比较少见
或者改成 edp:main / efe:main / amd:main 之类的?
从好记出发,已经有个 edp
对象了,放里面更方便点儿?
那我大概整理下,主要有以下几个需要做的事~
- 项目的信息全部使用package.json保存,废掉.edpproj中的metadata,module.conf除了用于更新require.config信息之外,我们还能通过他来找到包的源信息
- package.json中使用edp.dependencies(或者直接dependencies)字段来保存且只保存直接依赖的包,而所有的包应该是在module.conf中能查到的这样两者的差也就是间接依赖的包了。这样就可以获得整个的依赖树了
- main的话,在edp下在加一个main,外层的main的路径相对与工程根目录,里面的相对于src目录,这样的话node在用的时候用外层的,edp用的时候,如果里边有就用里面的,如果没有就用外面的在加个src
- 拉取包的整个过程,就是 @otakustay 整理的那些
正好最近打算把一些基础包同时发到npm和edp,需要这里提到的edp.main
的支持,来问一下进度如何
@otakustay 流程整理的这个,已经做完了,unimport也加上了,已发pr,edp.main的这个,现在的edp-project里module.js好像已经对npm和edp的包入口做了处理,可以在第一层的main指定为node的入口,edp下指定main 为edp的入口就可以了
@leeight 你这边有空review吗
可以