findxc / blog

88 stars 5 forks source link

在 package.json scripts 中使用 ** (globstar)匹配文件不生效的问题 #34

Open findxc opened 3 years ago

findxc commented 3 years ago

背景

项目接入了 Sentry ,希望在项目打包后把 sourcemap 删掉(sourcemap 上传到 sentry 是在打包过程中就完成了的),不然部署到生产环境由于有 sourcemap 源码可以被看到。

测试一下方案是否可行

假设 dist 目录结构如下:

image

一开始就是想着直接在打包命令后面跟一句 rm -rf dist/**/*.map 就行了(** 会匹配所有目录层级),在命令行里也测试了这个命令确实会删掉所有的 .map 文件。

然后写了个 package.json ,scripts 如下。

"scripts": {
  "build": "the_build_command && npm run rm-sourcemap",
  "rm-sourcemap": "rm -rf dist/**/*.map"
}

结果发现只删掉了 dist/b/b.js.map ,而 dist/a.js.mapdist/b/c/c.js.map 没有被删掉...

呃,很奇怪,命令行直接执行的结果和 npm scripts 执行的结果不一样竟然...

谷歌,谷歌,还是谷歌

然后在谷歌冲浪了好久好久好久...

然后我又测试了下使用 rimraf 这个库来实现,然后发现如果是写 "rimraf dist/**/*.map" 的话也是删不干净,但是如果写成 "rimraf 'dist/**/*.map'" (多了单引号)就能按预期删干净。

然后我又在谷歌冲浪了好久好久好久...

然后看到了这个 deployment - How to clean (delete contents) folder with npm - Stack Overflow

image

不是所有的 unix 系统都默认支持 ** 语法,那不就快要破案了吗啊哈哈哈。

然后又看到了这个 npm run script file glob not respecting ** · Issue #10481 · npm/npm · GitHub

image

bash 版本问题?

那 npm 在执行 scripts 时用的是哪个 shell 呢,用 "echo $0" 测试发现是 sh ,然后我本地的 sh 版本是 3.2 ,然后试了下切到这个 shell 后果然 rm -rf dist/**/*.map 删不干净(我默认是使用 zsh ,然后 zsh 是支持 ** 这个语法的) ... 呃 ... 原来如此 ...

更多细节在Why you should always quote your globs in NPM scripts(一定要看!)里都讲了,简单来说就是我自己使用的 shell 和 npm 使用的 shell 不一样,一个支持 ** 语法一个不支持,就产生了不一样的结果。

然后最后我是用 "find ./dist -name '*.map' -delete" 这个命令来删除所有的 sourcemap 文件的 ...

恩,破案破案,对此,我只想说一句,谷歌,yyds !👋

findxc commented 3 years ago

好吧,又去看了眼 eslint 文档,其实也有提到这个问题 -.-

image