如何在现有节点项目中添加由Angular Universal生成的快速应用程序

时间:2018-10-14 22:33:05

标签: node.js angular express webpack angular-universal

我的情况如下:我有一个具有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

0 个答案:

没有答案