问题出现场景
在项目中采用nodejs做中间层,做页面的首屏渲染,同时采用express作为主web框架,其中express的router页面路由我采用ts语言来编写。如下:
((router) (req); };
编写完ts后运行tsc命令将相应的ts文件编译为对应的js文件,如下:
((router) (req); };
其实这里只是import变成了var而已,但其意义在于在ts代码中采用import载入的模块可以享用强类型检查,以及代码自动补全,预编译检查等。
但是在启动node服务时却报错,错误信息如下:
Debugger listening on port 45864 /Users/WebSite/routes/xxx/page.ts:8 import request = require('request'); ^^^^^^ SyntaxError: Unexpected reserved word at exports.runInThisContext (vm.js:53:16) at Module._compile (module.js:373:25) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Module.require (module.js:353:17) at require (internal/module.js:12:17) ...提示import关键字非法,是保留字不能使用,在搜了Google以及Stackflow之后发现虽然提问的人很多,但几乎没人回答正确的解决方案,搜索无果后只能自己查为什么会出现这个问题。
原因分析在受到stackoverflow上某一个回答() 的启发后,发现我的路由代码的code.ts和编译后的code.js文件都在express下的router文件夹下,而通过在这两个文件分别输出log发现均会输出,而实际上我希望只有.js文件被识别,ts文件在编译完成后就不再参与node的执行。
所以问题的原因就在于本不应该被node载入的.ts也被拉去进行执行。
通过断点后发现,问题的原因在于核心模块的module.js文件里面的343行:
(filename) filename(....(..
在倒数第4行,如果某个文件的扩展名没有在Module._extensions字典内的文件,均被强制识别为.js文件,然后按照js代码去执行。而_extensions字典内只有js,json和node文件,如下图:
所以问题找到了,但是因为module.js是核心模块,不能修改其代码,所以只能去更上层的Express的代码去改。
解决方案在node_modules/express-enrouten/lib/directory.js中,有一个isFileModule的函数,用来判断当前文件是否一个模块,从而来决定是否要用node去加载它,可以通过修改这个函数来达到目的。
(file) .(ext (file .(err)
如果当前文件的扩展名是.ts则判断为非模块,而不去加载。
修改后问题解决了。
后记虽然问题解决了,但是修改框架代码这种事其实是有非常多的坑的,而且我本人也极力反感这种行为。
比如以后如何面临框架升级,还有因为修改了源码而带来的其他bug怎么办,等等。
但是目前现阶段而言有没有什么其他更好的办法,所以只能先这样了,如果有哪位博客园友知道能好的解决方案,还望不吝赐教。
完