在項目中採用nodejs作中間層,作頁面的首屏渲染,同時採用express做爲主web框架,其中express的router頁面路由我採用ts語言來編寫。以下:javascript
//page.ts 文件 import request = require('request'); module.exports = function(router) { router.get('/', function(req, resp) { resp.render('xxx/page'); }); };
編寫完ts後運行tsc命令將相應的ts文件編譯爲對應的js文件,以下:html
//page.js 文件 var request = require('request'); module.exports = function(router) { router.get('/', function(req, resp) { resp.render('xxx/page'); }); };
其實這裏只是import
變成了var
而已,但其意義在於在ts代碼中採用import
載入的模塊能夠享用強類型檢查,以及代碼自動補全,預編譯檢查等。java
可是在啓動node服務時卻報錯,錯誤信息以下: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以後發現雖然提問的人不少,但幾乎沒人回答正確的解決方案,搜索無果後只能本身查爲何會出現這個問題。web
在受到stackoverflow上某一個回答(http://stackoverflow.com/a/23113558/6001468) 的啓發後,發現個人路由代碼的code.ts和編譯後的code.js文件都在express下的router文件夾下,而經過在這兩個文件分別輸出log發現均會輸出,而實際上我但願只有.js文件被識別,ts文件在編譯完成後就再也不參與node的執行。
因此問題的緣由就在於本不該該被node載入的.ts也被拉去進行執行。express
經過斷點後發現,問題的緣由在於核心模塊的module.js
文件裏面的343行:json
// Given a file name, pass it to the proper extension handler. Module.prototype.load = function(filename) { debug('load %j for module %j', filename, this.id); assert(!this.loaded); this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; };
在倒數第4行,若是某個文件的擴展名沒有在Module._extensions
字典內的文件,均被強制識別爲.js文件,而後按照js代碼去執行。而_extensions
字典內只有js,json和node文件,以下圖:
api
因此問題找到了,可是由於module.js是核心模塊,不能修改其代碼,因此只能去更上層的Express的代碼去改。框架
在node_modules/express-enrouten/lib/directory.js
中,有一個isFileModule
的函數,用來判斷當前文件是否一個模塊,從而來決定是否要用node去加載它,能夠經過修改這個函數來達到目的。ide
/** * Returns true if `require` is able to load the provided file * or false if not. * http://nodejs.org/api/modules.html#modules_file_modules * @param file the file for which to determine module-ness. * @returns {boolean} */ function isFileModule(file) { var ext = path.extname(file); // 新增:若是文件擴展名是.ts則不進行加載 --xxcanghai@博客園 if(ext === ".ts") { return false; } // Omit dotfiles // NOTE: Temporary fix in lieu of more complete (cross platform) // fix using file flags/attributes. if (path.basename(file, ext)[0] === '.') { return false; } try { // remove the file extension and use require.resolve to resolve known // file types eg. CoffeeScript. Will throw if not found/loadable by node. file = ext ? file.slice(0, -ext.length) : file; require.resolve(file); return true; } catch (err) { return false; } }
若是當前文件的擴展名是.ts則判斷爲非模塊,而不去加載。
修改後問題解決了。
雖然問題解決了,可是修改框架代碼這種事實際上是有很是多的坑的,並且我本人也極力反感這種行爲。
好比之後如何面臨框架升級,還有由於修改了源碼而帶來的其餘bug怎麼辦,等等。
可是目前現階段而言有沒有什麼其餘更好的辦法,因此只能先這樣了,若是有哪位博客園友知道能好的解決方案,還望不吝賜教。
完