TypeScript + Node.js + Handlebars 将文件作为字符串导入
我正在使用 TypeScript 开发一个 Node.js 应用,并使用 Handlebars 进行模板处理。我在将 Handlebars 文件(.hbs)作为字符串成功导入时遇到了困难。模板文件基于 JavaScript 模板;TypeScript 和 Node.js 尝试将这些文件作为模块导入,因此在尝试执行代码时会抛出错误。由于 .hbs 文件不是标准的 .ts 文件,我的目标是将文件作为字符串导入;虽然我可以使用 fs.readFileSync 或 fsPromises.readFile 并指定 utf-8 编码轻松读取并直接将文件解析为字符串,但这对我的用例来说不可行,因为我需要在编译期间 import 这些文件。我使用 ts-node 编译/运行应用,例如 mymachine$ts-node src/index.ts。
index.ts
/// <reference path="./index.d.ts" />
import test from "./templates/test.hbs";
console.log(test);
index.d.ts
declare module "*.hbs";
// also have tried:
declare module "*.hbs" {
const value: string;
export default value;
}
test.hbs
// This Handlebars template is to generate some JavaScript / TypeScript code
import axios from 'axios'
console.log("ABC123");
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"typeRoots": [
"./node_modules/@types",
"./@types"
],
"resolveJsonModule": true,
"allowJs": true,
"declaration": true,
"outDir": "./dist",
"downlevelIteration": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true
},
"ts-node": {
"files": true
}
}
抛出错误
import axios
^^^^^^
SyntaxError: Cannot use import statement outside a module
我注意到有几个答案展示了如何在客户端应用中使用 Webpack 和 raw-loader 有效地实现这一点,并且我个人已经成功地以 .md 文件作为测试案例在 React 应用中实现了这一点(通过 declare module "*.md",然后 import file from "./file.md" 返回 file 作为字符串)。然而,我不确定这些解决方案是否适用于后台的 Node.js。
一个简单的解决方法是直接在 .ts 中将模板文件写为字符串,而不是作为 .hbs 的原始文件(见下文),但我更希望将文件保持为纯 .hbs,以保留语法高亮、Prettier 格式化和逻辑封装。
workaround.ts
import Handlebars from "handlebarsHelpers";
export const test = Handlebars.compile(`
// This Handlebars template is to generate some JavaScript / TypeScript code
import axios from 'axios'
console.log("ABC123");
`);
workaround-index.ts
import test from "./workaround";
console.log(test);
有什么建议吗?这个问题似乎与 .hbs 无关;即使使用一个包含相同原生 JavaScript 的 .txt 文件,TypeScript/Node.js 也会尝试将该文件作为模块导入,而不是将内容作为字符串传递。