用于NodeJS的TypeScript通过SystemJS
我想在我的NodeJS应用程序中使用TypeScript。 为了做到这一点,我认为这将是很好的使用SystemJS使我的源文件飞到JavaScript脚本。 我设法绕过了大部分与SystemJSconfiguration相关的问题,除了以下内容:
如何使SystemJS防止处理某些import,并使其使用原来的require
?
SystemJS通过它自己的require
实现将所有的东西都包含在它自己的模块表示中,而不考虑模块的原始types。 它使这样的NodeJS模块express
一个对象而不是函数(问题在于下面的代码中)
'use strict'; console.log('In server.ts'); if ('production' === process.env.NODE_ENV) require('newrelic'); let PORT = process.env.PORT || 3333; import * as fs from 'fs'; import * as os from 'os'; import * as https from 'https'; import * as express from 'express'; // <------------- SystemJS makes express an object import * as socketio from 'socket.io'; import { Routes } from './routes/index'; import { DBConfig } from './config/db.conf'; import { RoutesConfig } from './config/routes.conf'; import { SocketServer } from "./reflex/SocketServer"; const app = express(); // <------------ This is object, so no way to initialize RoutesConfig.init(app); DBConfig.init(); Routes.init(app, express.Router()); const opts = { key: fs.readFileSync(__dirname + '/cert/server.key'), cert: fs.readFileSync(__dirname + '/cert/server.crt') }; let server = https.createServer(opts, <any>app); let socket = socketio(server, { transports: ['websocket'] }); let socketServer = new SocketServer(100, socket); server.listen(PORT, () => { console.log(`Application is up and running @: ${os.hostname()} on port: ${PORT}`); console.log(`enviroment: ${process.env.NODE_ENV}`); });
另一个问题是,通过replace原来的需求,不仅每个模块应该覆盖SystemJSconfiguration,而且每个子模块都是一个矫枉过正的问题。
这是我的SystemJSconfiguration:
SystemJS.config({ transpiler: 'typescript', defaultJSExtensions: false, map: { // ------ system modules ------ "console": "@node/console", "buffer": "@node/buffer", "querystring": "@node/querystring", "events": "@node/events", "http": "@node/http", "cluster": "@node/cluster", "zlib": "@node/zlib", "os": "@node/os", "https": "@node/https", "punycode": "@node/punycode", "repl": "@node/repl", "readline": "@node/readline", "vm": "@node/vm", "child_process": "@node/child_process", "url": "@node/url", "dns": "@node/dns", "net": "@node/net", "dgram": "@node/dgram", "fs": "@node/fs", "path": "@node/path", "string_decoder": "@node/string_decoder", "tls": "@node/tls", "crypto": "@node/crypto", "stream": "@node/stream", "util": "@node/util", "assert": "@node/assert", "tty": "@node/tty", "domain": "@node/domain", "constants": "@node/constants", // ------ common modules ------ 'helmet': '@node/helmet', 'morgan': '@node/morgan', 'express': '@node/express', 'mongoose': '@node/mongoose', 'socket.io': '@node/socket.io', 'socket.io-client': '@node/socket.io-client', // <----- this module is being referenced by 'socket.io' 'body-parser': '@node/body-parser', // ------ SystemJS configuration ------ json: './node_modules/systemjs-plugin-json/json.js' }, meta: { '*.json': { loader: 'json' } }, paths: { 'typescript': './node_modules/typescript', }, packages: { 'typescript': { main: 'lib/typescript' }, 'server': { defaultExtension: 'ts' } }, typescriptOptions: tsconfig });
所以问题是如下:如何使SystemJS忽略某些导入(通过configuration),并绕过控制本地NodeJS require
实现?
先谢谢你!
如果你看看express.js如何导出东西,你会看到
exports = module.exports = createApplication;
接着
exports.application = proto; exports.request = req; exports.response = res;
当SystemJS将其转换为模块时,您需要的函数createApplication
成为默认导出 。
只有导入默认值的简写语法
import express from 'express'; console.log(typeof express); // function
当然,分配给它的所有属性 – application
, request
等等仍然可用。
或者,如果您偏好原始表单进行导入,则可以将其作为default
属性进行访问
import * as express from 'express'; console.log(typeof express.default); // function
现在你的问题
如何使SystemJS忽略某些导入(通过configuration)和绕过控制本地NodeJS需要实现?
在configurationAFAIK中没有这样的选项,但是SystemJS提供原始的节点需求作为System._nodeRequire
,所以你可以在代码中使用这个作为回退:
var express = System._nodeRequire('express');
注意:正如Lu4在注释中指出的, 'express': '@node/express'
SystemJSconfiguration中的'express': '@node/express'
映射是非常重要的。 除了从node_modules
加载node_modules
, @node
特殊符号告诉SystemJS模块内部所需的所有软件包及其依赖关系都将被加载,并且不会被转换为模块。 这有时是必需的,因为SystemJS模块parsingalgorithm与nodejs不同,正如SystemJS文档中的CommonJS模块格式部分所述。