TypeScript + Node.js + Handlebars Impor File sebagai String


Saya sedang bekerja dengan aplikasi Node.js menggunakan TypeScript dan templating dengan Handlebars. Saya mengalami kesulitan dalam mengimpor file Handlebars (.hbs) sebagai string dengan sukses. File template ini berbasis template JavaScript; TypeScript dan Node.js mencoba mengimpor ini sebagai modul sehingga menimbulkan error ketika mencoba mengeksekusi kode. Karena file .hbs bukan .ts standar, tujuan saya adalah mengimpor file tersebut sebagai string; meskipun saya bisa dengan mudah melakukan ini menggunakan fs.readFileSync atau fsPromises.readFile dengan encoding utf-8 atau sejenisnya dan langsung memparsing file sebagai string, ini bukan opsi untuk kasus saya karena saya perlu mengimpor file selama proses kompilasi. Saya mengompilasi/menjalankan aplikasi dengan ts-node, misalnya, 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
    }
}

Terjadi Kesalahan

import axios
^^^^^^

SyntaxError: Cannot use import statement outside a module

Saya telah memperhatikan beberapa jawaban yang menunjukkan cara melakukan ini secara efektif pada aplikasi klien menggunakan Webpack dan raw-loader, dan saya sendiri telah berhasil melakukannya dengan .md file sebagai kasus uji untuk aplikasi React (melalui declare module "*.md", kemudian import file from "./file.md" mengembalikan file sebagai string). Namun, saya tidak yakin bahwa solusi ini dapat diterapkan pada Node.js di backend.

Solusi sederhana adalah dengan menulis file template sebagai string di .ts alih-alih sebagai file mentah di .hbs (lihat di bawah), tetapi saya lebih suka menyimpan file sebagai .hbs murni untuk menjaga penyorotan sintaks, format Prettier, dan logika tetap terenkapsulasi.

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);

Ada saran? Masalahnya tampaknya independen dari .hbs; bahkan menggunakan .txt dengan JavaScript native yang sama menghasilkan TypeScript/Node.js mencoba mengimpor file sebagai modul daripada mengirimkan isinya sebagai string.

Artikel terkait