Это ошибка в документации.
Код их документации:
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');
Однако это не правильно или, по крайней мере, не очень ясно.
Пункт 1: Вам не следует создавать рабочий режим.
Хотя вы видите в одной строке документации, что они хотят, чтобы вы включили в раздел сценариев вашего package.json такую строку, как
ng run my-project:server:production
Вы не должны этого делать по двум причинам: во-первых, их инструкция по изменению angular.json не включает в себя производственную сборку.Во-вторых, производственная сборка (если вы только что скопировали с производства вашего фактического несерверного приложения) выполняется таким образом, чтобы включить хэш в имя файла, что приводит к файлу с именем, например main.a220df2.js
.Это, конечно, не идеально, так как это означает, что вы должны постоянно менять свой server.ts.
Итак, либо отключите хеширование "outputHashing": "none"
, либо просто не производите производственную сборку, вызвав ng run my-project:server
(просто удалите :production
).
Пункт 2: используйте правильный require
Фактический вызов require () должен указывать на ваш встроенный main.server.ts
, который является ссылками в вашем angular.json
в разделе projects:PROJECTNAME:architect:server
.Документация определила outputPath как "outputPath": "dist/my-project-server",
, что означает, что у нас есть файл в dist/my-project-server/main.js
, лежащий вокруг (сначала позаботьтесь о пункте 1 и отключите outputHashing или вообще не создавайте в рабочем режиме).Именно этот файл должен быть require
d в вашем server.ts
.
Так что, в вашем случае, это файл ./dist/reduza-ui/main.js
, который вы должны включить, как только вы отключили outputHasing или прекратили сборку в производственном режиме.
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/reduza-ui/main');
Дополнительный совет: в самом верху документации вы видите ссылку на полный код всей статьи: https://angular.io/generated/zips/universal/universal.zip. Там вы можете увидеть, как должен выглядеть настоящий кодкак.
Два последних совета, чтобы он полностью заработал:
Первый
Документация говорит в server.ts что-то вроде:
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
browser
- это актуальная версия вашего приложения по умолчанию, поэтому ваша обычная сборка.Если вы сделаете ng build
, у вас будет папка в dist/
, которая является вашим текущим приложением по умолчанию.Это приложение имеет в виду browser
.В вашем случае вы назвали версию своего сервера reduza-ui
, так что, возможно, ваше реальное приложение называется reduza-ui-default
в dist.В server.ts должен быть 'reduza-ui-default'
вместо 'browser'
в нескольких местах.
Second
В этот момент, когда вы скомпилировали сервер, запустили его и запросили первую страницув вашем браузере вы получаете в консоли:
StaticInjectorError(Platform: core)[InjectionToken Application Initializer -> InjectionToken DocumentToken]:
Right-hand side of 'instanceof' is not an object
Это потому, что webpack минимизирует ваш server.ts.Отключите использование
optimization: {
minimize: false
},
в webpack.server.config.js
.