使用node-prune优化Docker镜像时tsc构建失败的原因及解决方法
问题
我在Dockerfile配置中使用node-prune,在yarn install后移除所有不必要文件以减小镜像体积,配置如下:
FROM node:16-alpine3.15 RUN apk add curl RUN curl -sf https://gobinaries.com/tj/node-prune | sh COPY package*.json ./ RUN yarn install --production=true RUN yarn global add typescript RUN node-prune COPY . . RUN tsc -p tsconfig.build.json
但构建过程中,tsc抛出如下错误栈:
> [server-builder 10/10] RUN tsc -p tsconfig.build.json: #26 5.940 error TS2688: Cannot find type definition file for 'body-parser'. #26 5.940 The file is in the program because: #26 5.940 Entry point for implicit type library 'body-parser' #26 5.942 error TS2688: Cannot find type definition file for 'component-emitter'. #26 5.942 The file is in the program because: #26 5.942 Entry point for implicit type library 'component-emitter' #26 5.942 error TS2688: Cannot find type definition file for 'compression'. #26 5.942 The file is in the program because: ... and many more
移除RUN node-prune后镜像构建正常。请问为何node-prune会导致构建失败,该如何解决?
解答
原因
node-prune的默认行为会删除node_modules中它判定为“非生产必需”的文件,包括类型定义文件(.d.ts)、文档、测试代码等。而TypeScript编译(tsc)必须依赖这些.d.ts文件完成类型检查,你在TS编译前执行node-prune,导致必要的类型文件被清理,自然触发找不到类型定义的错误。
另外你使用了yarn install --production=true,该命令会跳过devDependencies的安装,若项目的类型定义包(如@types/xxx)属于devDependencies,本身就没被安装,再加上node-prune清理残留的类型文件,双重导致编译失败。
解决方法
推荐两种可行方案:
方案1:调整node-prune执行时机(更稳妥)
将node-prune放到TS编译完成之后,先保证编译所需的依赖和类型文件齐全,再清理冗余内容缩小镜像:
FROM node:16-alpine3.15 RUN apk add curl RUN curl -sf https://gobinaries.com/tj/node-prune | sh COPY package*.json ./ # 先安装全部依赖(包含devDependencies,满足编译对类型文件的需求) RUN yarn install RUN yarn global add typescript COPY . . # 完成TypeScript编译 RUN tsc -p tsconfig.build.json # 切换为生产依赖并执行清理 RUN yarn install --production=true RUN node-prune
方案2:配置node-prune保留类型文件
在项目根目录创建.pruneignore文件,添加规则让node-prune保留.d.ts文件:
!**/*.d.ts
然后在Dockerfile中同步拷贝该文件,再执行node-prune:
FROM node:16-alpine3.15 RUN apk add curl RUN curl -sf https://gobinaries.com/tj/node-prune | sh # 同步拷贝.pruneignore规则文件 COPY package*.json .pruneignore ./ # 注意:若类型定义在devDependencies中,需去掉--production=true,或提前单独安装类型包 RUN yarn install RUN yarn global add typescript RUN node-prune COPY . . RUN tsc -p tsconfig.build.json
此方案需注意:如果类型定义包属于devDependencies,必须确保它们被安装,否则仍会出现类型找不到的问题。
内容的提问来源于stack exchange,提问作者great programmer
相关产品推荐
相关产品推荐

