Я пытаюсь развернуть приложение 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);
});