Our project uses React / Typescript and Nx with WebPack and Babel. Our monorepo contains dozens of applications. As part of our i18n initiative, I am working on a git hook that will scan each application directory and create a default libs/pages/xyz/src/i18n/translations/messages-en-US.json
file that our translation team can ingest into their custom built system in order to generate additional files for other languages like messages-fr-CA.json
.
Our first approach is for the Node script to find each root application messages file (ex: libs/pages/xyz/src/i18n/messages.ts
), transpile it to ES2022, write it to a temporary file, and then dynamically import that file via import(temp.js)
so we can do multiple transformations to that that JSON before writing it to the default libs/pages/xyz/src/i18n/translations/messages-en-US.json
.
However, I am running into "module not found" errors when trying to dynamically import these files because each messages.ts
file contains aliased import paths...
(ex: messages.ts import's from common/foo/xyz
but in our tsconfig.json paths it would be mapped to project-root/libs/shared/common/foo/src/xyz.ts
.)
Transpiling the code works fine when using ts.transpileModule(filePath, compilerOptions).outputText
but when I try to const module = await import(compiledJSFilePath)
I get module resolution errors because the aliased paths as defined in my tsConfig.json
are not used when dynamically importing a single file with aliased imports...
// my-app/src/i18n/messages.ts
import fooMessages from 'Common/foo/messages';
import barMessages from 'Common/bar/messages';
... other required imports ...
export default {
...fooMessages,
...barMessages,
... other message files ...
}
// extract-messages.mjs
...
import * as fsp from 'node:fs/promises';
import ts from 'typescript';
...
tsContent = await fsp.readFile(targetAppRootMessageFile, { encoding: 'utf8' });
jsContent = ts.transpileModule(tsContent, compilerOptions).outputText;
await fsp.writeFile(tempOutputFile, jsContent);
const { default: messages } = await import(tempOutputFile);
... do transformations here ...
await fsp.writeFile(defaulti18nEnUSFile, JSON.stringify(transformedMessages, null, 2));
... delete temp file ...
... iterate to next application ...
I am not a NodeJS / Typescript Compiler guru, so any suggestions or guidance would be greatly appreciated...
paths
alias intsconfig.json
is only meant for thetsc
compiler for types, not for the actually emitted JS code:I guess your projects have a specific webpack path alias configuration, and the
tsconfig
just replicates those, as described in above quote.Now IIUC, you are writing a new tool script, that will import your compiled TS file as well. Therefore you need to implement the path alias in JS side again. You could e.g. use the
tsconfig-paths
library:Then when executing your new script, enable tsconfig-paths so that it adjusts node module resolution according to the tsconfig: