使用TypeScript编译Node.js时Express Handlebars未复制到dist目录
问题:TypeScript编译时未复制views文件夹到dist目录
我使用Express+TypeStack开发项目,大量依赖Express Handlebars模板,但执行tsc编译后,src目录下的views文件夹并未被复制到dist目录中。我的src目录结构如下:
| └── src └── views └── emails └── invitation-email.hbs
托管服务商配置为加载dist目录,该目录必须包含所有必要文件夹(包括未被复制的views和public文件夹)。以下是我的配置文件:
package.json
{ "name": "server", "version": "1.0.0", "description": "", "main": "server.js", "scripts": { "test": "jest", "dev": "nodemon src/server.ts", "build": "tsc -p tsconfig.json", "start": "npm run build && node dist/server.js", "clean": "rimraf dist" }, "keywords": [], "author": "Daniel mihai", "license": "ISC", "dependencies": { "@types/bcryptjs": "^2.4.6", "@types/express": "^4.17.21", "@types/handlebars": "^4.1.0", "@types/mongoose": "^5.11.97", "@types/node": "^20.10.5", "@types/nodemailer": "^6.4.14", "bcryptjs": "^2.4.3", "dotenv": "^16.3.1", "express": "^4.18.2", "express-handlebars": "^7.1.2", "handlebars": "^4.7.8", "hbs": "^4.2.0", "mongoose": "^8.0.3", "nodemailer": "^6.9.8", "nodemon": "^3.0.2" }, "devDependencies": { "@types/jest": "^29.5.11", "@types/supertest": "^6.0.2", "jest": "^29.7.0", "mongodb-memory-server": "^9.1.3", "rimraf": "^5.0.5", "supertest": "^6.3.3", "ts-jest": "^29.1.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" } }
tsconfig.json
{ "compilerOptions": { "target": "es6", "module": "commonjs", "strict": true, "rootDir": "./src", "outDir": "./dist" }, "include": ["src/**/*"] // Adjust the 'include' pattern to match your source files }
目录结构截图

dist目录截图

解决方案
TypeScript默认仅编译.ts/.tsx文件,不会自动复制.hbs等非代码资源文件,以下是三种可行的解决方式:
方法1:修改tsconfig.json让TypeScript复制资源文件
在tsconfig.json中明确指定需要包含的非代码文件类型,确保TypeScript编译时同步复制:
{ "compilerOptions": { "target": "es6", "module": "commonjs", "strict": true, "rootDir": "./src", "outDir": "./dist" }, "include": [ "src/**/*", "src/**/*.hbs", "src/**/*.html" // 如有其他模板/静态文件可补充 ], "exclude": ["node_modules"] }
注意:该方式在TypeScript 5.0+版本中支持更完善,低版本可能无法生效,建议搭配方法2使用。
方法2:在build脚本中添加资源复制命令
使用copyfiles工具实现编译后自动复制资源:
- 安装依赖:
npm install copyfiles --save-dev
- 修改package.json的build脚本:
"scripts": { "test": "jest", "dev": "nodemon src/server.ts", "build": "tsc -p tsconfig.json && copyfiles -u 1 src/**/*.hbs src/public/**/* dist/", "start": "npm run build && node dist/server.js", "clean": "rimraf dist" }
-u 1参数表示移除源路径的第一层目录(确保src/views内容直接复制到dist/views,而非dist/src/views),如需复制public文件夹可追加src/public/**/*。
方法3:用Node脚本实现自定义复制逻辑
如果需要更灵活的资源复制规则,可编写Node脚本:
- 安装
fs-extra工具:
npm install fs-extra --save-dev
- 创建
copy-assets.js脚本:
const fs = require('fs-extra'); async function copyAssets() { await fs.copy('./src/views', './dist/views'); await fs.copy('./src/public', './dist/public'); console.log('资源文件复制完成'); } copyAssets().catch(err => console.error('复制失败:', err));
- 修改package.json的build脚本:
"build": "tsc -p tsconfig.json && node copy-assets.js"
内容的提问来源于stack exchange,提问作者daniel sas
相关产品推荐
相关产品推荐

