Угловой универсальный с Nrwl Nx

Загрузка рабочего пространства Nrwl Nx с помощью Angular-Universal

Angular Universal - это проект для Angular, позволяющий выполнять рендеринг на стороне сервера, ускоряя загрузку и улучшая SEO.
Nx - это проект Nrwl, компании бывших инженеров Google, пытающейся поделиться некоторыми из разработок Google. лучшие практики с нами, плебс. Самым большим преимуществом Nx является его инструментальная и начальная поддержка для монорепозиториев. Монорепозиторий - это просто способ управления несколькими приложениями с разделяемыми библиотеками в одной рабочей области.
Однако загрузка приложения Angular со схемами Nx пока не так хорошо работает с Angular Universal. Этот учебник поможет в этом ❤️.

1. Создайте приложение.

Начнем с нуля, загрузим Angular-CLI и NX глобально:

npm install -g @angular/cli
npm install -g @nrwl/schematics

Теперь давайте создадим новое рабочее пространство под названием «рабочая область» и новое приложение под названием «блог»:

create-nx-workspace blog
Prompt CSS => Choose SCSS
Prompt npm-scope => type “workspace” for aliases like “@workspace”
Prompt framework => Choose “none” for now
cd workspace
ng g app blog
Prompt framework => choose Angular
Prompt directory => press enter (default)
Prompts unit-tester => choose Jest (❤️)
e2e-tester => choose Cypress (❤️❤️)
tags => write “app, blog-app” (or whatever you want)

Теперь у вас должно быть рабочее пространство с такой структурой:

Давайте воспользуемся встроенной схемой Angular-CLI, чтобы попытаться внедрить Angular Universal в проект:

ng add @nguniversal/express-engine --clientProject blog

Схема сгенерирует все файлы, которые нам нужны, но некоторые из них будут размещены не в том месте (для монорепо), и они не будут правильно связаны.

2. Загрузите все

Наши цели в оставшейся части учебника будут заключаться в том, чтобы

  1. Чтобы поместить server.ts и webpack.server.config.js в apps / blog
  2. Чтобы Angular генерировал выходные данные сервера и браузера в dist / apps / blog / server / и dist / apps / blog / browser /, соответственно

Но давайте начнем постепенно. Если мы попытаемся выполнить только что сгенерированные package.json-commands

npm run build:ssr && npm run serve:ssr

… Мы получим сообщение об ошибке, что файл (для замены рабочего файла) по пути /workspace/src/environments/environment.prod.ts не найден. В angular.json измените server-fileReplacements, чтобы он имел префикс apps / blog:

"server": {
  ...
  "configurations": {
    "production": {
      "fileReplacements": [
        {
          "replace": "apps/blog/src/environments/environment.ts",
          "with": "apps/blog/src/environments/environment.prod.ts"
        }
      ]
    }
  }
}

Если вы выполните команды сейчас, вы можете получить несколько сбивающих с толку ошибок, связанных с Cypress. Но не волнуйтесь, как только мы исправим структуру нашего проекта, они исчезнут.

Итак, переместим server.ts и webpack.server.config.js в apps / blog. server.ts выдаст несколько ошибок компиляции машинописного текста (невозможно найти «require», «path» и т. д.), потому что tsconfig.app.json содержит строку:

"types": []

… Переопределение «узловых» -типов из tsconfig.json корневого уровня; удалить эту строку ☠️

Остальные файлы, созданные для Angular Universal внутри приложений / блога, в порядке, и нам не нужно трогать их до конца урока.

Теперь давайте настроим два пути в server.ts в соответствии с желаемой структурой папки dist:

const DIST_FOLDER = join(process.cwd(), 'dist', 'apps', 'blog', 'browser');

const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('../../dist/apps/blog/server/main');

И в webpack.server.config.js сделайте ссылку на перемещенный файл server.ts, а также настройте выходной каталог:

server: './apps/blog/server.ts'
output: {
    path: path.join(__dirname, '../../dist/apps/blog/server'),
    filename: '[name].js'
  },

Теперь внутри package.json свяжите compile: server-command с перемещенным webpack.server.config.js и свяжите serve: ssr-command с новым выходным каталогом:

"compile:server": "webpack --config apps/blog/webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/apps/blog/server/server",

Теперь, когда мы ожидаем, что наш результат будет в dist / apps / blog, позвольте нам использовать Angular, чтобы поместить его туда. В angular.json измените пути для браузера и вывода сервера:

"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "outputPath": "dist/apps/blog/browser",
"server": {
  "builder": "@angular-devkit/build-angular:server",
  "options": {
    "outputPath": "dist/apps/blog/server",

Пока вы находитесь в angular.json, вы также можете добавить следующее в server.configurations:

"sourceMap": false,
"optimization": true

Это удалит исходные карты и оптимизирует / минимизирует вывод сервера. В противном случае в конце вы получите такую ​​исходную карту для вашего main.js:

3. Прибыль!

Вы можете убедиться, что все сделали правильно, снова выполнив эту команду:

npm run build:ssr && npm run serve:ssr

На http: // localhost: 4000 теперь вы должны увидеть серверное приложение:

Вы можете сказать, что это предварительный рендеринг, потому что тег ‹body› содержит не только пустой корневой тег, но и настоящие HTML-теги, такие как ‹div›, ‹h1› и т. Д. Внутри него. Вы также можете использовать приложение на стороне браузера как обычно, чтобы увидеть разницу.

4. Резюме

Вы можете найти код из этого руководства здесь:



Если вы нашли этот урок полезным, пожалуйста, 👏 один или несколько раз! Также большое спасибо Стефану Карлссону за помощь в Stackoverflow!