我的情况如下:我有一个具有express的节点服务器,一方面为我服务几个角度的应用程序,另一方面响应api的请求。它们每个都配置了一条路由,最后所有内容都从单个端口进行侦听。
现在,我正在使用Angular Universal准备一个新的angular应用程序。按照官方角度指南中的步骤使用Express实施Universal,流派一个server.ts文件。该文件将负责呈现内容并提高服务器在端口中的监听速度。
这是我的问题的出处。我的意图是该服务器不侦听任何端口,相反,我想导出app变量并将其导入到我现有的节点项目中,这样我就可以在单个端口中侦听多个应用程序。我知道我可以将节点服务器的内容添加到server.ts文件中,但是出于几个重要原因,我想将其分开。
我尝试将变量app导出到文件server.ts中,使用webpack风格化server.js,将变量导入我现有的节点服务器中,并添加app.use(universalapp)进行添加。我已经尝试了很多方法,但是我没有得到它,在大多数情况下,导入server.js返回undefined或{}。我希望自己能很好地解释自己,如果您需要更多数据,请不要犹豫告诉我。非常感谢您的帮助,我等待您的答复。
为了更好地理解它,这里是我的代码:
我现有的节点服务器(app.js):
'use strict'
// Imports y variables
var express = require("express"),
bodyParser = require("body-parser"),
cors = require("cors"),
morgan = require("morgan"),
methodOverride = require("method-override"),
https = require("https"), // --> PARA PRODUCCIÓN
// http = require("http"), // --> PARA LOCAL
helmet = require("helmet"),
path = require("path"),
compression = require("compression"),
fs = require('fs'),
appConfig = require('./config/global').config.app,
app = express();
var option = {
key: fs.readFileSync(appConfig.certOptions.sslPath + appConfig.certOptions.key),
cert: fs.readFileSync(appConfig.certOptions.sslPath + appConfig.certOptions.cert),
ca: fs.readFileSync(appConfig.certOptions.sslPath + appConfig.certOptions.ca)
}; // --> PARA PRODUCCIÓN
var server = https.createServer(option, app); // --> PARA PRODUCCIÓN
// var server = http.createServer(app); // --> PARA LOCAL
// Middlewares
app.use(bodyParser.urlencoded({
limit: appConfig.limit,
parameterLimit: appConfig.parameterLimit,
extended: false
}));
app.use(bodyParser.json({
limit: appConfig.limit
}));
app.use(methodOverride());
app.use(morgan(appConfig.logMode)); // Genera logs
app.use(helmet()); // Seguridad
app.use(cors()); // Habilita las cabeceras y accesos
app.use(compression());
// Para servir la aplicación angular
app.use(express.static(path.join(__dirname, 'dist'))); // Panel web
app.use('/clientes', express.static(path.join(__dirname, 'clientes/dist/coplanapwa'))); // App web
// Cualquier otra ruta devulve la aplicación angular
var web = require('./routes/web');
// API - Rutas
var user_routes = require('./routes/user'),
map_routes = require('./routes/map'),
doc_routes = require('./routes/doc'),
plaga_routes = require('./routes/plaga'),
recomendacion_routes = require('./routes/recomendacion'),
valoracion_routes = require('./routes/valoracion'),
app_routes = require('./routes/app');
// API - Middlewares
app.use('/api', user_routes);
app.use('/api', map_routes);
app.use('/api', doc_routes);
app.use('/api', plaga_routes);
app.use('/api', recomendacion_routes);
app.use('/api', valoracion_routes);
app.use('/api', app_routes);
app.use(web);
module.exports = server;
我现有的节点服务器(index.js):
'use strict'
var mongoose = require('mongoose');
var server = require('./app');
var db = require('./config/global').config.db;
var port = require('./config/global').config.app.port;
// Conexión e inicio server
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGODB_URI || 'mongodb://'+db.user+':'+db.password+'@'+db.host+':'+db.port+'/'+db.scheme, function(err, res) {
if(err) {
console.log('ERROR: No ha sido posible conectar a la base de datos. ' + err);
}
server.listen(port, function() {
console.log("El servidor local con Node y Express está corriendo correctamente en https://xyz.ab:" + port);
});
});
我在TypeScript(server.ts)中的Angular通用节点应用
'use strict'
// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { enableProdMode } from '@angular/core';
import * as express from 'express';
import { join } from 'path';
// FIX para los accesores al dom y propiedades exclusivas del navegador
const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['document'] = mock.getDocument();
global['window'] = mock.getWindow();
global['location'] = mock.getLocation();
global['navigator'] = mock.getNavigator();
global['history'] = mock.getHistory();
global['localStorage'] = mock.getLocalStorage();
global['sessionStorage'] = mock.getSessionStorage();
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const DIST_FOLDER = join(process.cwd(), 'clientes/dist');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./clientes/dist/coplanapwa-server/main');
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'coplanapwa'));
// Server static files from /coplanapwa
app.get('*.*', express.static(join(DIST_FOLDER, 'coplanapwa')));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
// const PORT = process.env.UNIVERSAL_PORT || 8002;
// app.listen(PORT, () => {
// console.log(`El servidor local con Node y Express está corriendo correctamente en https://xyz.ab:${PORT}`);
// });
export default app;
由webpack(server.js)生成的server.js文件的片段:
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var zone_js_dist_zone_node__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var zone_js_dist_zone_node__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(zone_js_dist_zone_node__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var reflect_metadata__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
/* harmony import */ var reflect_metadata__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(reflect_metadata__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
/* harmony import */ var express__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208);
/* harmony import */ var express__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(express__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(215);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _nguniversal_express_engine__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1069);
/* harmony import */ var _nguniversal_module_map_ngfactory_loader__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1071);
// These are important and needed before anything else
// FIX para los accesores al dom y propiedades exclusivas del navegador
var MockBrowser = __webpack_require__(333).mocks.MockBrowser;
var mock = new MockBrowser();
global['document'] = mock.getDocument();
global['window'] = mock.getWindow();
global['location'] = mock.getLocation();
global['navigator'] = mock.getNavigator();
global['history'] = mock.getHistory();
global['localStorage'] = mock.getLocalStorage();
global['sessionStorage'] = mock.getSessionStorage();
// Faster server renders w/ Prod mode (dev mode never needed)
Object(_angular_core__WEBPACK_IMPORTED_MODULE_2__["enableProdMode"])();
// Express server
var app = express__WEBPACK_IMPORTED_MODULE_3__();
// let app: any = express();
var DIST_FOLDER = Object(path__WEBPACK_IMPORTED_MODULE_4__["join"])(process.cwd(), 'clientes/dist');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
var _a = __webpack_require__(917), AppServerModuleNgFactory = _a.AppServerModuleNgFactory, LAZY_MODULE_MAP = _a.LAZY_MODULE_MAP;
// Express Engine
// Import module map for lazy loading
app.engine('html', Object(_nguniversal_express_engine__WEBPACK_IMPORTED_MODULE_5__["ngExpressEngine"])({
bootstrap: AppServerModuleNgFactory,
providers: [
Object(_nguniversal_module_map_ngfactory_loader__WEBPACK_IMPORTED_MODULE_6__["provideModuleMap"])(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', Object(path__WEBPACK_IMPORTED_MODULE_4__["join"])(DIST_FOLDER, 'coplanapwa'));
// Server static files from /coplanapwa
app.get('clientes/*.*', express__WEBPACK_IMPORTED_MODULE_3__["static"](Object(path__WEBPACK_IMPORTED_MODULE_4__["join"])(DIST_FOLDER, 'coplanapwa')));
// All regular routes use the Universal engine
app.get('clientes/*', function (req, res) {
res.render('index', { req: req });
});
...And about 28,000 more lines
Package.json构建脚本:
"build:prod": "ng build --configuration production --build-optimizer --vendor-chunk --base-href /clientes/ --deploy-url /clientes/",
"build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
"serve:ssr": "node clientes/dist/server",
"build:client-and-server-bundles": "npm run build:prod && ng run coplanapwa:server",
"webpack:server": "webpack --config webpack.server.config.js --progress --colors",
我想要做的是这样的事情:
server.ts:
// Express server
const app = express();
// More code ...
export default app;
app.js:
var express = require("express");
var app = express();
var universalapp = require("./universalapp/server.js");
app.use('/clientes', universalapp);
// More code ...
更新2018/10/17
我曾尝试使用javascript用相同的代码创建server.js而不是server.ts,但是当我不识别ECMAScript2015的导入时,它给了我错误。我放置了我已经创建的端口和错误,以便更好地理解它。因此,您可以更好地理解它,我向您展示代码:
server.js
'use strict'
// These are important and needed before anything else
require('zone.js/dist/zone-node');
require('reflect-metadata');
const { enableProdMode } = require('@angular/core');
const express = require('express');
const { join } = require('path');
// FIX para los accesores al dom y propiedades exclusivas del navegador
const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['document'] = mock.getDocument();
global['window'] = mock.getWindow();
global['location'] = mock.getLocation();
global['navigator'] = mock.getNavigator();
global['history'] = mock.getHistory();
global['localStorage'] = mock.getLocalStorage();
global['sessionStorage'] = mock.getSessionStorage();
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const DIST_FOLDER = join(process.cwd(), 'clientes/dist');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('clientes/dist/coplanapwa-server/main');
// Express Engine
const { ngExpressEngine } = require('@nguniversal/express-engine');
// Import module map for lazy loading
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'coplanapwa'));
// Server static files from /coplanapwa
app.get('*.*', express.static(join(DIST_FOLDER, 'coplanapwa')));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
const PORT = process.env.UNIVERSAL_PORT || 8002;
app.listen(PORT, () => {
console.log(`El servidor local con Node y Express está corriendo correctamente en https://xys.ab:${PORT}`);
});
// export default app;
// export const APP = app;
节点输出错误:
import { Injectable, Inject } from '@angular/core';
^^^^^^
SyntaxError: Unexpected token import