How to add the express application generated by Angular Universal in an existing node project

孤街浪徒 提交于 2019-12-11 06:56:18

问题


My situation is as follows: I have a node server with express that serves me on the one hand several angular applications and on the other hand responds to requests from the api. Each of them is configured for a route and finally everything is listening from a single port.

Now I am preparing a new angular application with Angular Universal. Following the steps of the official angular guide to implement Universal with express, genre a server.ts file. This file will be responsible for rendering the content and raising the server listening in a port.

This is where my question comes from. My intention is that this server does not listen to any port, instead, I want to export the app variable and import it into my existing node project, in this way I keep several applications listening in a single port. I know I can add to the server.ts file the content of my node server but I want to keep it separated for several important reasons.

I have tried to export the variable app in the file server.ts, genre the server.js with webpack, import the variable in my existing node server and add app.use (universalapp) to add it. I have tried it in many ways but I do not get it, in most cases importing server.js returns undefined or {}. I hope to have explained myself well, and if you need more data do not hesitate to tell me. Thank you very much for the help, I await your answers.

To make it better understood, here my code:

My existing node server (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;

My existing node 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);
    });    
});

My Angular Universal Node App in TypeScript (server.ts)

'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;

A fragment of the server.js file generated with webpack (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 scripts:

"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",

What I would like is to do something like that:

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 ...

UPDATE 2018/10/17

I had tried to create server.js instead of server.ts with the same code but in javascript, but it gives me errors when I do not recognize the import of ECMAScript2015. I put the port that I have made and the error so that it is understood better. So you can understand it better I show you the code:

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;

Node output error:

import { Injectable, Inject } from '@angular/core';
^^^^^^

SyntaxError: Unexpected token import

来源:https://stackoverflow.com/questions/52807640/how-to-add-the-express-application-generated-by-angular-universal-in-an-existing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!