Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[package]edp-package流程整理 #332

Open
otakustay opened this issue Jun 3, 2015 · 17 comments
Open

[package]edp-package流程整理 #332

otakustay opened this issue Jun 3, 2015 · 17 comments

Comments

@otakustay
Copy link
Member

@leeight 因为现在的edp-package在使用过程中还是有不少细节有问题的,这些细节很难说清楚,所以我整理了一个我认为合理的流程,看看是否能采纳到现在的功能中

第一次写完发现自己想的不对,又重写了一下……其实importupdate就是同一个过程,只有一些细枝末节上是不同的,所以我整理成一个流程了

效果

  1. 被使用者明确指定的包是不用让使用者确认的,都明确输入指令要引入/更新一个包了,再问它“是否要引入/更新XXX”是多余的
  2. 如果一个包在本地是没有的,但edp判断这个包是需要的(被依赖),也不用问用户要不要引入,不引入就完蛋了
  3. importupdate过程中,是可能涉及已经存在的包的update的,此时是需要询问用户的,要按照下面说的的流程进行
  4. 开发者指定import一个已经存在的包不应该被允许,应该提示“请使用edp update”。同样update一个不存在的包也是不行的
  5. importupdate过程不应该把未指定的包(如被依赖的包)加入到package.json中,比如我edp import er,你不能在package.jsondep中加上eoo这一项
  6. 任何时候不要依赖dep下有多少目录,这个逻辑肯定是不对的,package.jsonmodule.conf才是入口

使用方法

  1. edp import/update package用来拉取1个指定的包,区别就在上面说的,已经存在的包不能import,不存在的包不能update
  2. edp import/update package package ...用来拉取n个指定的包,此过程是对过程1的n次重复,这N交是串行的(并行会让你在处理依赖的时候头疼),任意一次失败都不应该影响其它的拉取,完成后提示“xxx包拉取失败”,以便使用者补救
  3. edp import/update没有参数时根据package.json来拉取所有需要的依赖,此过程是从package.json中读取包列表并执行过程2,注意这里看package.json就行,如果一个包不在package.json中,且不会在其它包更新过程中因为依赖问题一起更新的话,说明这个包根本没用了,没删掉它已经很客气了还更新啥
  4. edp import/update url根据URL来拉取1个指定的包,这个过程是第1步的子集,具体对照下文的流程应该比较容易理解

拉取单个包的流程

针对过程1,其实际执行应该是这样的:

  1. 从registry查找对应的meta信息
  2. 根据meta信息找符合指定版本要求(从package.json来或者@xxx指定的)的最新版本
  3. 根据第2步拿到的版本,去registry拿这个版本对应的package.json【注1】
  4. 根据package.json找到所有的依赖
  5. 对每个依赖,重复1-4的过程,把整个依赖树建起来
  6. 把这个树合并成一个数组,合并时注意根据包名去重,数组中每一项是{packageName, version},一个包在数组中应该只出现一次【注2】
  7. 根据第6步得出的数组,查看每一项,按以下分支走
    1. 如果本地有了,并且我们需要的版本比本地存在的更新(版本更新通过本地的package.json里的version比较),则询问用户“是否把xxx从1.0更新至2.0”,用户选Yes则下载更新,选No则跳过。下载更新是简单粗暴地“删除本地再下载安装”的过程(后续会加MD5比对之类的需求,所以不要和下面第3步的直接安装混在一起)
    2. 如果本地有了,且本地的版本比我们要的还新,直接跳过
    3. 本地没有这个包,则直接下载安装,不用问用户
  8. 全搞完后更新module.conf

以上步骤中有任何一步出错,整个过程回滚,打印错误信息,应该就像什么都没发生过一样,不能有残留的文件变更出现

【注1】如果用的是edp import/update url拉某个URL的话,此时没有registry,所以是直接拉下来进第4步就行

注意这种直接从URL拉过来的东西,不要在package.json里留下dependencies项,不然会影响以后的edp update更新所有包(会在registry上找不到这个包),这种包以后更新也肯定是edp update url更新的,在package.json中出现没有用

【注2】这里涉及到多个包依赖同一个包且版本要求不同时的原则,比如foo依赖underscore@1.5.xbar依赖underscore@1.x,而当前的underscore版本是1.7.2

  1. 找符合一个包的要求的最新的,则因为1.7.2符合1.x,所以使用1.7.2
  2. 找符合所有包的要求最新的,则用1.5.6

另外,有可能foobar依赖的版本根本是冲突的,比如1.5.x1.7.x,那么也要考虑上面2个原则用哪个,反正edp是不支持多版本共存和map的自动配置了,要玩开发者自己去玩儿去

我建议采用选新的方式,上面的案例我们用1.7.2

总结和关键点

  1. importupdate的流程是高度相同的
  2. 拉取package.json这事似乎是做不到的,要拉取整个包再解压找package.json,但后续下载安装又会用到这个包,所以这里设个缓存避免多次的下载
  3. 全程我们只看项目及各个包的package.json,不要有其它的信息来干扰
  4. 询问最少原则,只在本地有这个包且版本比较旧时才触发询问,一个包也只应该被询问一次(这就是建立依赖树再打平成数组的目的)
  5. 要考虑v1v2的两种layout

其它功能

  1. edp import应该增加--save参数来指定要不要更新package.json
  2. 最好有个edp dep来查看整个依赖树关系
  3. 【非常未来】考虑到通过配置require.config多版本并存、包改名等情况,事实上整个过程是需要结合module.conf里的信息的,比如edp update er但可能因为require.config里的packges里把er配成了mvc,那么比对版本的时候就要看dep/mvc这个目录。但现在没有去实现它的必要
@otakustay
Copy link
Member Author

@leeight 现在有人做不,没有的话7月我看一下算了?

@leeight
Copy link
Member

leeight commented Jul 7, 2015

好,交给你了

@errorrik
Copy link
Contributor

有一个问题,上面的方案认为module.conf用于存储项目当前引入包的源信息。但是包改名、多版本并存之类的事情就没法支持了。是不是应该有个新的隐藏文件,用于存储当前引入包的源信息,而module.conf经过这个文件生成。

其实,最初设计的时候,module.conf仅仅是用于生成require.config的

@errorrik
Copy link
Contributor

另外,原先有部分依赖包信息是存在.edpproj文件里的,是继续保留,还是废掉这个逻辑,必须存package.json?

我个人建议是废掉

@errorrik
Copy link
Contributor

另外, @beenlee 从package.json里读dependencies的逻辑是这样的:

先看存不存在edp.dependencies,再看存不存在efe.dependencies,再看存不存在dependencies

@daaaabeen
Copy link

@errorrik edp.dependencies, efe.dependencies, dependencies这三个是什么区别,在import时是按什么规则写入的?
现在的逻辑好像是将依赖写入到package.json的edp.dependencies,如果没有这个文件,就尝试去找.edpproj下的metadata写到metadata的dependencies里 那个efe.dependencies是什么情况下写入的呢。

@errorrik
Copy link
Contributor

先说dependenciesedp.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会更好些。但是想了想,没必要搞这么多名字出来。考虑dependenciesedp.dependencies就好了。如果想要扩展性好点,可以留出配置口。

@otakustay
Copy link
Member Author

看到在说这个区别,我补一下,请顺便把main的问题解决了,对edp来说main: 'foo'会想找src/foo.js,而node并不会,这个需要区别对待

我们是否应该期待所有的配置都在edp下可以被override呢

@errorrik
Copy link
Contributor

我们是否应该期待所有的配置都在edp下可以被override呢

我觉得可以,再想想除了main好像也没别的了。devDependencies?

@otakustay
Copy link
Member Author

比如oo我们其实就想叫oo的,但是在npm上显然这名字已经占用了,所以最后改叫eoo

不过name要这么做的话,得 @leeight 那边的registry有支持

@leeight
Copy link
Member

leeight commented Oct 27, 2015

我觉得可以,再想想除了main好像也没别的了。devDependencies?

或者改成 edp:main / efe:main / amd:main 之类的?

我们是否应该期待所有的配置都在edp下可以被override呢

override的目的就是为了少写点儿配置?

@firede
Copy link
Member

firede commented Oct 27, 2015

我觉得可以,再想想除了main好像也没别的了。devDependencies?

实用角度看有着四个:name, main, dependencies, devDependencies
但也有其他字段需覆盖的场景,比如发版时指定各自的 files、private 等,比较少见

或者改成 edp:main / efe:main / amd:main 之类的?

从好记出发,已经有个 edp 对象了,放里面更方便点儿?

@daaaabeen
Copy link

那我大概整理下,主要有以下几个需要做的事~

  1. 项目的信息全部使用package.json保存,废掉.edpproj中的metadata,module.conf除了用于更新require.config信息之外,我们还能通过他来找到包的源信息
  2. package.json中使用edp.dependencies(或者直接dependencies)字段来保存且只保存直接依赖的包,而所有的包应该是在module.conf中能查到的这样两者的差也就是间接依赖的包了。这样就可以获得整个的依赖树了
  3. main的话,在edp下在加一个main,外层的main的路径相对与工程根目录,里面的相对于src目录,这样的话node在用的时候用外层的,edp用的时候,如果里边有就用里面的,如果没有就用外面的在加个src
  4. 拉取包的整个过程,就是 @otakustay 整理的那些

@otakustay
Copy link
Member Author

正好最近打算把一些基础包同时发到npm和edp,需要这里提到的edp.main的支持,来问一下进度如何

@daaaabeen
Copy link

@otakustay 流程整理的这个,已经做完了,unimport也加上了,已发pr,edp.main的这个,现在的edp-project里module.js好像已经对npm和edp的包入口做了处理,可以在第一层的main指定为node的入口,edp下指定main 为edp的入口就可以了

@otakustay
Copy link
Member Author

@leeight 你这边有空review吗

@leeight
Copy link
Member

leeight commented Jan 6, 2016

可以

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants