Angular 9.0 SSR скомпилировано, но я не могу опубликовать sh на сервере - PullRequest
0 голосов
/ 12 февраля 2020

Я обновил свой проект Angular 8 до Angular 9. Я выполнил команду «npm run build: ssr && npm run serve: ssr». Это работало безупречно, и папки «browser» и «server» были созданы в папке «dist».

Я загрузил эти файлы на свой сервер (панель Plesk). Я установил его для чтения файла server / main. js с помощью node.js.

Не удалось, потому что не удалось найти «browser / index.html» в папке «dist». Я создал папку с именем «dist» и переместил в нее папку «browser».

Затем произошел тайм-аут, мой проект не работал. Я запускаю Node.js в режиме разработки, чтобы увидеть ошибку, но он говорит, что время ожидания истекло.

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

const domino = require('domino'); // kb
const fs = require('fs'); // kb
const template = fs.readFileSync('dist/browser/index.html').toString(); // kb
const win = domino.createWindow(template); // kb
global['window'] = win;
global['document'] = win.document;
global["branch"] = null;
global["object"] = win.object;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;

// The Express app is exported so that it can be used by serverless Functions.
export function app() {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/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
  // app.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() {
  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';

main.server.ts

import { enableProdMode } from '@angular/core';

import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

export { AppServerModule } from './app/app.server.module';
export {ngExpressEngine} from '@nguniversal/express-engine';

export { renderModule, renderModuleFactory } from '@angular/platform-server';

tsconfig.app. json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": []
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}

tsconfig.server. json

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "./out-tsc/app-server",
    "baseUrl": ".",
    "types": [
      "node"
    ]
  },
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  },
  "files": [
    "src/main.server.ts",
    "server.ts"
  ]
}

tsconfig. json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "esnext",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  }
}

пакет . json

{
  "name": "kodumunblogu",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "compile:server_bak": "webpack --config webpack.server.config.js --progress --colors",
    "build:ssr_bak": "npm run build:client-and-server-bundles && npm run compile:server",
    "serve:ssr_bak": "node dist/server",
    "build:client-and-server-bundles_bak": "ng build --prod --aot && ng run kodumunblogu:server:production --bundleDependencies all",
    "dev:ssr": "ng run kodumunblogu:serve-ssr",
    "serve:ssr": "node dist/server/main.js",
    "build:ssr": "ng build --prod && ng run kodumunblogu:server:production",
    "prerender": "ng run kodumunblogu:prerender",
    "postinstall": "ngcc"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^9.0.0",
    "@angular/cdk": "^9.0.0",
    "@angular/common": "~9.0.0",
    "@angular/compiler": "~9.0.0",
    "@angular/core": "~9.0.0",
    "@angular/forms": "~9.0.0",
    "@angular/material": "^9.0.0",
    "@angular/platform-browser": "~9.0.0",
    "@angular/platform-browser-dynamic": "~9.0.0",
    "@angular/platform-server": "^9.0.0",
    "@angular/router": "~9.0.0",
    "@fortawesome/angular-fontawesome": "^0.6.0",
    "@fortawesome/fontawesome-svg-core": "^1.2.15",
    "@fortawesome/free-brands-svg-icons": "^5.7.2",
    "@fortawesome/free-solid-svg-icons": "^5.7.2",
    "@fullcalendar/core": "^4.3.1",
    "@nguniversal/express-engine": "^9.0.0",
    "@ngx-share/button": "^7.1.2",
    "@ngx-share/buttons": "^7.1.2",
    "@ngx-share/core": "^7.1.2",
    "bootstrap": "^4.3.1",
    "chart.js": "^2.9.3",
    "core-js": "^2.6.5",
    "express": "^4.17.1",
    "jquery": "^3.3.1",
    "primeicons": "^2.0.0",
    "primeng": "^9.0.0-rc.4",
    "quill": "^1.3.6",
    "rxjs": "~6.5.4",
    "tslib": "^1.10.0",
    "webpack-node-externals": "^1.7.2",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.1",
    "@angular/cli": "~9.0.1",
    "@angular/compiler-cli": "~9.0.0",
    "@angular/language-service": "~9.0.0",
    "@nguniversal/builders": "^9.0.0",
    "@types/express": "^4.17.0",
    "@types/jasmine": "~3.3.10",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.3.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.0.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.5",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-loader": "^4.0.0",
    "ts-node": "~8.0.3",
    "tslint": "~5.14.0",
    "typescript": "~3.7.5",
    "webpack-cli": "^3.1.0"
  }
}

Ответы [ 2 ]

0 голосов
/ 25 апреля 2020

Это шаги, которые я получил Angular 9. net core 3.1, все они работают с использованием Angular Universal и NodeIIS.

Это может помочь вам начать https://medium.com/@MarkPieszak / angular -универсальный серверный рендеринг-deep-dive-dc442a6be7b7 .

Обратите внимание, что мой окончательный проект предварительно не отрендерен, это ssr, что означает, что определенные страницы имеют параметры и будут продолжать расти со временем, поэтому я не могу предварительно отрендерить (кэшировать) определенные страницы, которые должны быть ssr.

Я создал приложение angular в ядре VS. net и добавил универсальное. Затем, после того как вы сможете запустить ng serve, убедитесь, что вы можете запустить следующее в своем приложении angular 9.

  1. ng run YOURAPPNAME: сервер: production --bundleDependencies true
  2. npm run build: ssr
  3. npm run serve: ssr

Обратите внимание, что ваш код будет работать для ssr

Fix Angular JS код для работы в SSR

  1. изменить весь код для локального хранилища, например, if (isPlatformBrowser (this.platformId)) {}
  2. Google global ['window'], global ['document'] и app.use (cors ()); для server.ts, так как вам нужно будет их тоже настроить.

Серверные вещи

  1. посмотрите решение здесь c#. net ядро ​​для работы cors https://www.codeproject.com/Questions/5162494/Currently-I-am-working-on-angular-and-web-API-NET

  2. Выполните шаги, описанные выше, чтобы удалить - в обеих строках я использовал опубликованный мастер прямо в IIS из VS (он копирует папку в root, содержащую множество Dlls et c, папку ClientApp, которая содержит dist и node_modules) См. publi sh делает всю тяжелую работу за вас. Если вы делаете это вручную, вы копируете все содержимое из папки debug ... \ publi sh. Мне даже не пришлось возиться с файлом web.config. Как только он будет опубликован, я настрою домен так, чтобы он указывал на эту папку в IIS.

  3. установил nodeiis и запустил npm run serve: ssr, который обработает все запросы на веб-сайт и переведет в ssr лучше всего использовать pm2 (npm i pm2)

  4. Я добавил это при запуске VS net core SPA

         app.UseSpa(spa =>
        {
            spa.UseProxyToSpaDevelopmentServer("http://localhost:4000");
    
            spa.Options.SourcePath = "ClientApp";
    
            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    

При локальном тестировании я могу запустить ng serve и изменить localhost на 4200, а затем, когда я запускаю npm, запустите serve: ssr, я могу изменить на 4000, и вы можете обновить sh вашего веб-сайта и посмотреть, как он по-разному

Примечания

Я sh они сделали это легко но после всех этих шагов он работает и веб-сайт загружается мгновенно. Когда я смотрю на заголовок страницы, используя источник просмотра, это указатель заголовка, но Google Webmasters прочитал правильный заголовок на всех страницах.

Альтернативное решение

Есть платный Сервис под названием prerender.io Я собирался их использовать, стоит около 9 евро в месяц и может легко реализовать https://github.com/dingyuliang/prerender-dotnet/wiki/Prerender-Middleware-for-ASP.NET-Core. Я использовал его для проекта angularJS, и он отлично работает.

Надеюсь, что эти шаги кому-то помогут, так как мне потребовались целую вечность, чтобы получить эту работу

0 голосов
/ 14 апреля 2020

Я сомневаюсь, что tsconfig. json file baseUrl - проблема. Вы можете удалить то же самое и попробовать один раз на локальном сервере, а затем на сервере.

...