Description
What is the problem this feature will solve?
The flags --experimental-strip-types and --experimental-transform-types enable Node.js to run almost all TypeScript files. #54283
This feature of running .ts files directly is great. I recently removed the step of compiling .ts files to .js and started the project directly through node entry.ts
, and then directly imported other .ts modules.
However, in a large project with many files, compiling .ts files takes up a lot of startup time (about 200ms for all files using .js, and about 700ms for .ts). If there is a compilation cache, skipping the compilation of the same .ts file and directly using the .js compilation result, it will be very efficient.
What is the feature you are proposing to solve the problem?
After I got this idea, I tried to simply modify lib/internal/modules/esm/translators.js
and add local file cache. Now the speed of running .ts file for the second time is exactly the same as .js.
I hope someone can combine .ts compilation cache with the current .js compilation cache in node.js.
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
index b1e7b860..8eb172b1 100644
--- a/lib/internal/modules/esm/translators.js
+++ b/lib/internal/modules/esm/translators.js
@@ -24,8 +24,9 @@ const {
const { BuiltinModule } = require('internal/bootstrap/realm');
const assert = require('internal/assert');
-const { readFileSync } = require('fs');
-const { dirname, extname, isAbsolute } = require('path');
+const { readFileSync, writeFileSync } = require('fs');
+const { dirname, extname, basename, isAbsolute } = require('path');
+const crypto = require('crypto')
const {
assertBufferSource,
loadBuiltinModule,
@@ -484,11 +485,38 @@ translators.set('commonjs-typescript', function(url, source) {
return FunctionPrototypeCall(translators.get('commonjs'), this, url, code, false);
});
+
+// --- patch: Compile .ts esm files with typescirpt and cache
+const filepath_cache = process.env.NODE_COMPILE_CACHE + '/'
+
// Strategy for loading an esm TypeScript module
translators.set('module-typescript', function(url, source) {
- emitExperimentalWarning('Type Stripping');
- assertBufferSource(source, false, 'load');
- const code = stripTypeScriptTypes(stringify(source), url);
- debug(`Translating TypeScript ${url}`);
- return FunctionPrototypeCall(translators.get('module'), this, url, code, false);
-});
+ emitExperimentalWarning('Type Stripping');
+ assertBufferSource(source, false, 'load')
+
+ const str_source = stringify(source)
+
+ const [
+ code = stripTypeScriptTypes(str_source, url),
+ filepath_js
+ ] = (() => {
+ const filepath_js = filepath_cache +
+ url.slice('file:///'.length).replaceAll(':', '_').replaceAll('/', '_').slice(0, -2) +
+ crypto.hash('sha256', str_source).slice(0, 8) +
+ '.js'
+
+ try {
+ return [readFileSync(filepath_js, 'utf-8')]
+ } catch { }
+
+ return [undefined, filepath_js]
+ })()
+
+ if (filepath_js)
+ try {
+ writeFileSync(filepath_js, code)
+ } catch { }
+
+ return FunctionPrototypeCall(translators.get('module'), this, url, code, false)
+})
+
@nodejs/typescript
@marco-ippolito @joyeecheung
What alternatives have you considered?
No response