Angular Универсальный в производстве с Node Express - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь развернуть приложение Angular, используя Angular universal с Node и Express в бэкэнде. Он отлично работал без angular универсального, но теперь я сталкиваюсь с несколькими проблемами.
Должен ли я просто иметь файл server.ts и избавиться от файла server. js в бэкэнде, поскольку они делают то же самое ? Приложение загружается нормально, но когда я пытаюсь войти в систему, возникают проблемы с CORS.
Следует ли мне настраивать заголовки в файле server.ts? / N Кроме того, используются переменные среды dev, несмотря на добавление файла замена соответственно в файле angular. json. Я запустил сборку: ssr, переместил приложение в папку backend, а также файл main. js, созданный сборкой в ​​папке dist.
Любая помощь будет принята с благодарностью.

angular. json:

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "mean-app": {
            "root": "",
            "sourceRoot": "src",
            "projectType": "application",
            "prefix": "app",
            "schematics": {
                "@schematics/angular:component": {
                    "style": "sass"
                }
            },
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                        "outputPath": "backend/mean-app/browser",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "src/tsconfig.app.json",
                        "assets": [
                            "src/favicon.ico",
                            "src/assets"
                        ],
                        "styles": [
                            "src/sass/styles.sass",
                            "node_modules/bootstrap/dist/css/bootstrap.css",
                            "node_modules/@fortawesome/fontawesome-pro/js/all.js",
                            "src/sass/my-themes.sass"
                        ],
                        "scripts": [
                            "node_modules/jquery/dist/jquery.js",
                            "node_modules/popper.js/dist/umd/index.js",
                            "node_modules/bootstrap/dist/js/bootstrap.js",
                            "node_modules/@fortawesome/fontawesome-pro/js/all.js"
                        ],
                        "stylePreprocessorOptions": {
                            "includePaths": [
                                "node_modules/",
                                "./src/sass"
                            ]
                        }
                    },
                    "configurations": {
                        "production": {
                            "fileReplacements": [{
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }],
                            "optimization": true,
                            "outputHashing": "all",
                            "extractCss": true,
                            "namedChunks": false,
                            "aot": true,
                            "extractLicenses": true,
                            "vendorChunk": false,
                            "buildOptimizer": true,
                            "budgets": [{
                                "type": "initial",
                                "maximumWarning": "2mb",
                                "maximumError": "15mb"
                            }]
                        }
                    }
                },
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "options": {
                        "browserTarget": "mean-app:build"
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "mean-app:build:production"
                        }
                    }
                },
                "extract-i18n": {
                    "builder": "@angular-devkit/build-angular:extract-i18n",
                    "options": {
                        "browserTarget": "mean-app:build"
                    }
                },
                "test": {
                    "builder": "@angular-devkit/build-angular:karma",
                    "options": {
                        "main": "src/test.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "src/tsconfig.spec.json",
                        "karmaConfig": "src/karma.conf.js",
                        "styles": [
                            "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
                            "src/styles.sass"
                        ],
                        "scripts": [],
                        "assets": [
                            "src/favicon.ico",
                            "src/assets"
                        ]
                    }
                },
                "lint": {
                    "builder": "@angular-devkit/build-angular:tslint",
                    "options": {
                        "tsConfig": [
                            "src/tsconfig.app.json",
                            "src/tsconfig.spec.json",
                            "src/tsconfig.server.json"
                        ],
                        "exclude": [
                            "**/node_modules/**"
                        ]
                    }
                },
                "server": {
                    "builder": "@angular-devkit/build-angular:server",
                    "options": {
                        "outputPath": "dist/mean-app/server",
                        "main": "server.ts",
                        "tsConfig": "src/tsconfig.server.json",
                        "stylePreprocessorOptions": {
                            "includePaths": [
                                "src/",
                                "src/sass",
                                "src/sass/styles.sass",
                                "node_modules"
                            ]
                        }
                    },
                    "configurations": {
                        "production": {
                            "outputHashing": "media",
                            "fileReplacements": [{
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }],
                            "sourceMap": false,
                            "optimization": true
                        }
                    }
                },
                "serve-ssr": {
                    "builder": "@nguniversal/builders:ssr-dev-server",
                    "options": {
                        "browserTarget": "mean-app:build",
                        "serverTarget": "mean-app:server",
                        "stylePreprocessorOptions": {
                            "includePaths": [
                                "src/sass/styles.sass",
                                "node_modules"
                            ]
                        }
                    },
                    "configurations": {
                        "production": {
                            "browserTarget": "mean-app:build:production",
                            "serverTarget": "mean-app:server:production",
                            "fileReplacements": [{
                                "replace": "src/environments/environment.ts",
                                "with": "src/environments/environment.prod.ts"
                            }]
                        }
                    }
                },
                "prerender": {
                    "builder": "@nguniversal/builders:prerender",
                    "options": {
                        "browserTarget": "mean-app:build:production",
                        "serverTarget": "mean-app:server:production",
                        "routes": [
                            "/"
                        ]
                    },
                    "configurations": {
                        "production": {}
                    }
                }
            }
        },
        "mean-app-e2e": {
            "root": "e2e/",
            "projectType": "application",
            "prefix": "",
            "architect": {
                "e2e": {
                    "builder": "@angular-devkit/build-angular:protractor",
                    "options": {
                        "protractorConfig": "e2e/protractor.conf.js",
                        "devServerTarget": "mean-app:serve"
                    },
                    "configurations": {
                        "production": {
                            "devServerTarget": "mean-app:serve:production"
                        }
                    }
                },
                "lint": {
                    "builder": "@angular-devkit/build-angular:tslint",
                    "options": {
                        "tsConfig": "e2e/tsconfig.e2e.json",
                        "exclude": [
                            "**/node_modules/**"
                        ]
                    }
                }
            }
        }
    },
    "defaultProject": "mean-app"
}

server.ts:

import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';

import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
    const server = express();
    const distFolder = join(process.cwd(), 'backend/mean-app/browser');
    const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

    // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
    server.engine('html', ngExpressEngine({
        bootstrap: AppServerModule,
    }));

    server.set('view engine', 'html');
    server.set('views', distFolder);

    // Example Express Rest API endpoints
    // server.get('/api/**', (req, res) => { });
    // Serve static files from /browser
    server.get('*.*', express.static(distFolder, {
        maxAge: '1y'
    }));

    // All regular routes use the Universal engine
    server.get('*', (req, res) => {
        res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
    });

    return server;
}

function run(): void {
    const port = process.env.PORT || 4000;

    // Start up the Node server
    const server = app();
    server.listen(port, () => {
        console.log(`Node Express server listening on http://localhost:${port}`);
    });
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
    run();
}

export * from './src/main.server';

app. js:

const express = require('express');
require('./db/mongoose');
const app = express();
const postsRoutes = require('./routers/posts');
const userRoutes = require('./routers/user');
const groupsRoutes = require('./routers/group');
const topicsRoutes = require('./routers/topics');
const path = require('path');

app.use(express.json());
app.use("/images", express.static(path.join(__dirname, "images")));
app.use("/", express.static(path.join(__dirname, "mean-app/browser")));

app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', "*");
    res.setHeader('Access-Control-Allow-Headers', "Origin, X-Request-With, Content-Type, Accept, Authorization");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
    next();
});

app.use('/api/posts', postsRoutes);
app.use('/api/users', userRoutes);
app.use('/api/groups', groupsRoutes);
app.use('/api/topics', topicsRoutes);
app.use((req, res, next) => {
    res.sendFile(path.join(__dirname, "mean-app/browser", "index.html"));
});

module.exports = app;

сервер. js

const http = require('http');
const debug = require('debug')("node-kit");
const app = require('./app');
const { socket } = require('./socket');

const normalizePort = val => {
    var port = parseInt(val, 10);
    if (isNaN(port)) {
        return val;
    }
    if (port >= 0) {
        return port;
    }
    return false;
};

const onError = error => {
    if (error.syscall !== 'listen') {
        throw error
    }
    const bind = typeof addr === "string" ? "pipe" + addr : "port" + port;
    switch (error.code) {
        case "EACCES":
            console.error(bind + " requires elevated privileges");
            process.exit(1);
            break;
        case "EADDRINUSE":
            console.error(bind + " is already in use");
            process.exit(1);
            break;
        default:
            throw error;
    }
};

const onListening = () => {
    const addr = server.address();
    const bind = typeof addr === "string" ? "pipe" + addr : "port" + port;
    debug("Listening on " + bind);
};

const port = normalizePort(process.env.PORT || "3000");
app.set('port', port);

const server = http.createServer(app);
server.on('error', onError);
server.on('listening', onListening);
socket(server);

server.listen(port, () => {
    console.log('Server server.js running on port...' + port);
});
...