我有这个Makefile:
node_modules: yarn.lock
yarn install --production=false
touch node_modules
yarn.lock: package.json
yarn install --production=false
touch yarn.lock
Run Code Online (Sandbox Code Playgroud)
基本上,如果node_modules目录丢失(或者有人通过添加/删除文件篡改了它),或者yarn.lock已经更新,那么它应该运行yarn install以重建/完整性检查node_modules目录.
但是,如果yarn.lock缺少,可以重建package.json,或者如果package.json更新,则应安装并重建锁文件.
问题是当两个node_modules 和 yarn.lock丢失,那么相同的命令运行两次.
我怎么能阻止这个?
我几乎把它通过包裹在有条件的指令来工作:
ifneq ("$(wildcard yarn.lock)","")
node_modules: yarn.lock
@yarn install --production=false
touch node_modules
yarn.lock: package.json
touch yarn.lock
else # yarn.lock does not exist
node_modules: yarn.lock
touch node_modules
yarn.lock: package.json
@yarn install --production=false
endif
Run Code Online (Sandbox Code Playgroud)
现在,如果你touch package.json再make node_modules和yarn.lock存在,那么它会随后touch yarn.lock这将导致node_modules重建,就像我想要的.
但是,如果您touch package.json和然后make yarn.lock,从技术上讲它应该尝试yarn install但不会,因为我从该指令中删除了命令:
yarn.lock: package.json
touch yarn.lock
Run Code Online (Sandbox Code Playgroud)
防止它在前一个场景中运行两次.
首先,考虑这里说明的方法:
Makefile(1)
.PHONY: all clean
all: yarn.lock
yarn.lock: node_modules package.json
$(MAKE clean)
yarn install --production=false
node_modules:
mkdir -p $@
clean:
rm -fr node_modules yarn.lock
Run Code Online (Sandbox Code Playgroud)
这将永远不会运行yarn install冗余,这是一个稍微比你正在考虑更强大的解决方案.我会解释一下.
问题中的一个源项是package.json.它是其他一切的唯一逻辑先决条件,而不是它本身的构建.
这yarn.lock是一个构建人工制品,其生产意味着
yarn install在完成package.json时存在的快照成功完成.yarn install随后将认为安装是最新的,yarn.lock
并且具有与package.json通过算法体现的标准"一致"的内容yarn install.
因此,简单地看一下,这个版本的任务就是在以下方面做到yarn.lock
最新package.json:
yarn.lock: package.json
yarn install --production=false
Run Code Online (Sandbox Code Playgroud)
但它实际上更复杂.yarn.lock是构建目标,但它不是唯一的构建伪差,这是不连的一个主值的假象.当然,这些都是node-modules因为跑步而填充的人工制品
yarn install.
因此,主要的构建工具看起来像这个构建的副作用,而实际的目标,yarn.lock对我们来说只是作为一个象征,即主要的人工制品,无论它们是什么,都是最新的package.json.
它是一个虚弱的标记.代理商可以搞乱内容
node_modules- 添加不应该存在的文件,删除或修改应该 - 并且yarn install不会做任何事情来纠正它,只要它根据自己的标准考虑yarn.lock最新package.json.
你在解释建议的食谱时对这种脆弱性做了广告:
node_modules: yarn.lock
yarn install --production=false
touch node_modules
Run Code Online (Sandbox Code Playgroud)
如果缺少node_modules目录(或者有人通过添加/删除文件篡改了它),或者已经更新了yarn.lock,那么它应该运行yarn install来重建/完整性检查node_modules目录.
但是这种规则是由这种篡改引发的错误方式.篡改 - 如果你很幸运 - 将更新修改时间node_modules.但这将使它更年轻,而不是更老yarn.lock,而且不会解雇配方.配方仅适用于node_modules不存在的情况.
配方可以缓解这种弱点:
yarn.lock: node_modules package.json
$(MAKE) clean
yarn install --production=false
Run Code Online (Sandbox Code Playgroud)
如果yarn.lock不存在,或者对于任何一个 node_modules
或者过时package_json,我们将从头开始重新制作所有构建工件.
这是更好的,但是它带来了开机的问题,当既没有文物yarn.lock或node_modules存在是node_modules-这是填充作为由产品制造的yarn.lock-也是一个额外补贴的yarn.lock.
然而,这是一个微不足道的问题.为先决条件yarn.lock是仅仅存在
的node_modules,它使得之前是满足的yarn.lock,而
内容的node_modules,跟上时代的-只需添加配方:
node_modules:
mkdir -p $@
Run Code Online (Sandbox Code Playgroud)
有了这个,如果node_modules它不存在,它将被创建为一个先决条件yarn.lock,使其更新yarn.lock,并要求
yarn.lock和主要的构建工件.
但...
这个解决方案基本上表达了依赖关系,因此 - 显示了yarn install永远不需要冗余运行.它纠正了篡改检测逻辑中错误的错误.
但仍然没有强大的篡改检测能力.
我们得到的篡改检测机制是:在 node_modules
目录中 发生的事情使其修改日期晚于yarn.lock.这将检测到一些篡改,但不是所有的篡改.
作为文件系统对象,当且仅当添加,删除或重命名直接子对象时,才修改目录 - 并更新其修改时间.所以,篡改检测机构是盲目的任何内部的所有事件子目录的
node_modules和现有的文件或子目录的任何修改
node_modules,除了重新命名它.这留下了足够的空间搞乱了node_modules.
有鉴于此,你可能会决定: -
棒
狡猾的篡改检测比没有好.我不想使用比这更昂贵的东西.
但你可能不会.更可能的替代品:
折
篡改检测这种脆弱并不比没有好,所以我会回到:
yarn.lock: package.json
yarn install --production=false
Run Code Online (Sandbox Code Playgroud)
我认为不正确的篡改是我构建的超出范围.如果它发生了,某些东西会破裂,我会注意到它, make clean 然后再试一次.
提前了
我想要强大的篡改检测.
强大的篡改检测,使相当重的起重-但不是太多重.你需要强制一个干净yarn install,或者不强制,这取决于内容的完整清单之间的旧与新比较的结果node_modules- 显示足够的信息,以便显示任何重大差异.
详细说明每个文件的路径名和修改时间的清单
node_modules是最佳候选者.此清单将包含make
需要知道的信息,并且如果可以拼写出该构建的难以捉摸的主要人工制品,则将从文件系统获取该信息,并且该信息相对于其上次记录状态的变化是可靠的触发重拍一切.从而:
Makefile(2)
RM := rm -fr
MANIFEST_DIR := .manifest
LAST_MANIFEST := $(MANIFEST_DIR)/node_modules.last
NEW_MANIFEST := $(MANIFEST_DIR)/node_modules.peek
GEN_MANIFEST := find node_modules/ -exec stat -c '%n %y' {} \;
$(shell mkdir -p $(MANIFEST_DIR) node_modules)
$(if $(wildcard $(LAST_MANIFEST)),,$(shell touch $(LAST_MANIFEST)))
$(shell $(GEN_MANIFEST) > $(NEW_MANIFEST))
$(shell cmp -s $(LAST_MANIFEST) $(NEW_MANIFEST) || touch node_modules)
.PHONY: all clean
all: $(LAST_MANIFEST)
yarn.lock: node_modules package.json
$(RM) yarn.lock node_modules
yarn install --production=false
$(LAST_MANIFEST): yarn.lock
$(GEN_MANIFEST) > $@
clean:
$(RM) yarn.lock node_modules $(MANIFEST_DIR)
Run Code Online (Sandbox Code Playgroud)
这开发了Makefile(1),主要是在顶部无条件执行的设备,其中: -
node_modules目录开始,即使是空的..manifest)开始工作,并保持最新的清单node_modules.(类似于.deps在C/C++中经常用于保存自动依赖文件的隐藏目录).find node_modules/ -exec stat -c '%n %y' {} \;写入.此快照是真正的,因为它是,但不一定是真实的,因为它应该是.(它应该遵循符号链接吗? - ?否.因为不会遵循目标或先决条件的符号链接).<filename> <modification_time>node_modulesnode_modules node_modulesfind -L ...makenode_modules.这相当于构建前导码,它将node_modules通过强大的篡改检测测试来更新或不更新修改时间.然后构建就像以前一样,除了它的目标不再是
yarn.lock,而是一个新的持久化清单$(LAST_MANIFEST),它始终是一个立即的后yarn-install快照,因此依赖于
yarn.lock.
Makefile的锻炼(2)
对于实验室老鼠,package.json
我将使用:
{
"name": "node-js-sample",
"version": "0.2.0",
"description": "A sample Node.js app using Express 4",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.13.3"
},
"engines": {
"node": "4.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/heroku/node-js-sample"
},
"keywords": [
"node",
"heroku",
"express"
],
"author": "Mark Pundsack",
"contributors": [
"Zeke Sikelianos <zeke@sikelianos.com> (http://zeke.sikelianos.com)"
],
"license": "MIT"
}
Run Code Online (Sandbox Code Playgroud)
从头开始制作
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.17s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
什么都不改变,重拍
$ make
make: Nothing to be done for 'all'.
Run Code Online (Sandbox Code Playgroud)
node_modules仅触摸
$ touch node_modules/
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.01s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
package.json仅触摸
$ touch package.json
imk@imk-ThinkPad-T420:~/develop/so/make_prob$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.22s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
触摸node_modules和package.json
$ touch package.json node_modules/
imk@imk-ThinkPad-T420:~/develop/so/make_prob$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.05s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
触摸 yarn.lock
$ touch yarn.lock
$ make
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
删除 yarn.lock
$ rm yarn.lock
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.17s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
更改依赖项 package.json
$ sed -i 's/4\.13\.3/4.15.3/' package.json
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.03s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
撤消更改
$ sed -i 's/4\.15\.3/4.15.3/' package.json
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 2.35s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
触摸子目录中的现有文件 node_modules
$ ls node_modules/vary/
HISTORY.md index.js LICENSE package.json README.md
$ touch node_modules/vary/README.md
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.02s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
将文件添加到的子目录 node_modules
$ touch node_modules/vary/interloper
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.20s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)
从子目录中删除文件 node_modules
$ rm node_modules/vary/README.md
$ make
rm -fr yarn.lock node_modules
yarn install --production=false
yarn install v0.24.5
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 1.16s.
find node_modules/ -exec stat -c '%n %y' {} \; > .manifest/node_modules.last
Run Code Online (Sandbox Code Playgroud)