Как исправить ошибки скрипта 404 (неверный путь) в проекте Angular, представленном с помощью Ng Universal - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть различные маршруты в веб-приложении angular, например «/ about», «/ contact» и т. Д. c.

После запуска build: ssr я запускаю ng run myproject:prerender

Это завершает и создает папки в /dist/myproject/browser/*. Разная папка для каждого маршрута.

В каждой папке есть индексный файл. html, представляющий собой обработанный маршрут HTML. Пока все хорошо.

Однако в каждом индексе. html отрендеренных файлов первая строка выглядит следующим образом:

<html lang="en"><head><script src="runtime-es2015.c9afb3256f2870e161de.js" type="module"></script><script src="runtime-es5.c9afb3256f2870e161de.js" nomodule="" defer=""></script><script src="polyfills-es5.2878b91c9d9c0a1ee890.js" nomodule="" defer=""></script><script src="polyfills-es2015.4cfd8e3e2fd9d10b9e9e.js" type="module"></script><script src="vendor-es2015.429669b901f4df42a057.js" type="module"></script><script src="vendor-es5.429669b901f4df42a057.js" nomodule="" defer=""></script><script src="main-es2015.a676e1a4bb3cc6e8a80c.js" type="module"></script><script src="main-es5.a676e1a4bb3cc6e8a80c.js" nomodule="" defer=""></script>

Это будет выглядеть прекрасно, пока вы не поймете, что скрипт sr c является относительным.

Таким образом, при развертывании, скажем, https://myproject.com/about загрузит обработанный индекс. html из папки / about /. Однако при загрузке сценариев, поскольку sr c является относительным, пути сценариев становятся следующими: https://myproject.com/about/runtim-es2015....js.

Это возвращает 404 и приводит к сбою приложения, поскольку сценарии не существуют в этой папке. Эти сценарии находятся в каталоге root.

Имеет ли это смысл?

Я создал временное исправление, написав и включив следующий сценарий в свой конвейер развертывания, который добавляет forward sla sh к пути sr c:

const { readdirSync } = require('fs')
const fs = require('fs')

const getDirectories = source =>
    readdirSync(source, { withFileTypes: true })
        .filter(dirent => dirent.isDirectory())
        .map(dirent => dirent.name)

const loop = function (DirectoryString) {

    const Dirs = getDirectories(DirectoryString);

    if (Dirs.length) {

        Dirs.forEach(folderName => {

            const DirectoryStr = './dist/myproject/browser/' + folderName + '/';

            if (fs.existsSync(DirectoryStr)) {

                console.log(DirectoryStr + 'index.html Fixed');

                loop(DirectoryStr);

                fs.readdir(DirectoryStr, (err, files) => {
                    files.forEach(file => {
                        if (file === "index.html") {

                            const fileName = `${DirectoryStr}index.html`;

                            try {
                                fs.readFile(fileName, 'utf8', function (err, data) {
                                    if (err) {
                                        return console.log(err);
                                    } else {
                                        var result = data.replace(/script src\=\"(?!http)([a-zA-Z])/g, 'script src="/$1');
                                        fs.writeFile(fileName, result, 'utf8', function (err) {
                                            if (err) return console.log(err);
                                        });
                                    }
                                });
                            } catch (e) {
                                console.log(e);
                            }
                        }
                    });
                });

            }

        });

    }

}

loop('./dist/myproject/browser/');

Пока это работает, но я бы хотел исправить это в Angular. Я не мог найти кого-то еще с этой же проблемой. Любые предложения?

ОБНОВЛЕНИЕ

Эта проблема также иногда возникает в разработке localhost. Это происходит, если маршрут имеет глубину более одного пути, так сказать.

Таким образом, сервер ng выполняет автоматическую c перезагрузку localhost: 4200 / order / step2 (запускается при обновлении кода), приложение не загружается, и я получаю сообщение об ошибке

GET http://localhost:4200/order/step2/runtime.js net::ERR_ABORTED 404 (Not Found)

Это довольно раздражает для разработки. Проект никогда не привык к этому, только недавно начался: (

ОБНОВЛЕНИЕ 2

Кроме того, при просмотре источника страницы, отображаемой на localhost, я наблюдаю, что скрипт помечает теги добавляются за пределы документа.

Сверху, это визуализированный источник документа:

<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="styles.js" type="module"></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script><!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">

С какой стати Angular сделал бы это?

ОБНОВЛЕНИЕ 3

У меня есть <base href="/"> в моей голове документа, но я подозреваю, что, поскольку теги сценария добавляются до объявления базы и вне документа, база не применяется.

ОБНОВЛЕНИЕ 4

Вот репозиторий Github, который воспроизводит проблему:

https://github.com/EmanH/angular-bug-SO-61358153

1 Ответ

1 голос
/ 30 апреля 2020

Index.html в вашем репо не имеет закрывающего тега </body>. Давайте рассмотрим источники angular-cli, чтобы понять, как Angular добавляет <script> теги.

// Determine script insertion point
let scriptInsertionPoint;
if (bodyElement.__location && bodyElement.__location.endTag) {
  scriptInsertionPoint = bodyElement.__location.endTag.startOffset;
} else {
  // Less accurate fallback
  // parse5 4.x does not provide locations if malformed html is present
  scriptInsertionPoint = params.inputContent.indexOf('</body>');
}

indexSource.insert(scriptInsertionPoint, scriptElements);

Он ищет позицию закрывающего тега </body>! В вашем случае скрипты вставляются в позицию -1.

СТАРЫЙ ОТВЕТ

Пожалуйста, проверьте этот простой репо https://github.com/dnmakarov/angular-universal-guide. У него настроен SSR, поэтому убедитесь, что предварительный рендеринг работает нормально. Я проверил - у меня работает нормально.

Основная проблема - это место, где теги <script> размещаются внутри index.html. Я проверил Angular источников и похоже, что эта логика c не менялась месяцами. Поэтому, пожалуйста, убедитесь, что вы используете последние версии пакетов angular-cli, @nguniversal/* и @angular/*.

Если проблема все еще существует после этого, пожалуйста, предоставьте хотя бы минимальное хранилище, где я могу воспроизвести его. Я много работал с Angular Universal и вижу такую ​​проблему впервые. Спасибо.

...