web-dev-qa-db-de.com

Faul laden Anwendungsstile mit Angular CLI

Ich versuche, die href eines <link /> zu Themenzwecken zu wechseln, und die SCSS-Designs leben in einem Paketordner meines Monorepo, der in node_modules verlinkt ist. Ich muss diese kompilieren und referenzieren können.

Ich bin auf folgendes Problem gestoßen: angle/angle-cli # 3401 und habe versucht, etwas Ähnliches zu implementieren:

"styles": [
    "styles.scss",
    {
        "input": "../node_modules/@org/themes/dark.scss",
        "output": "dark",
        "lazy": true
    }
],

Mein Verständnis (vielleicht falsch) war, dass dies die dark.scss-Datei in dist/dark.bundle.css kompilieren würde und dass ich sie über http: // localhost: 4200/dist/dark.bundle.css laden könnte, aber es funktioniert nicht wie erwartet. Missverstehe ich etwas oder mache das völlig falsch? 

Wie kompiliere ich eine SCSS-Datei aus node_modules, die ich dann in die App laden kann? Gibt es einen anderen/besseren Ansatz, den ich stattdessen ausprobieren könnte?

Zusätzliche Bemerkungen:

  • Verwendung von Angular Version 4.2.4
  • CLI-Version von Angular 1.3.0 verwenden
  • Die Dokumentation für diesen Ansatz
  • Ich arbeite in einer Monorepo, also ist node_modules/@org/themes ein Symlink 
  • Ich habe versucht, die Option ng serve --preserve-symlinks für den Fall zu verwenden, dass dies das Problem war. Es machte keinen Unterschied

Ich habe untersucht, auf welche Weise die Angular -Dokumentations-Website dieses Problem löst und es scheint, als hätten sie ein benutzerdefiniertes Build-Skript, das die SCSS-Dateien in CSS-Dateien im Verzeichnis assets kompiliert, bevor die Anwendung bereitgestellt wird. Ich dachte, dass das Problem mit dem oben genannten Problem die Notwendigkeit für diesen Schritt beseitigte, aber vielleicht nicht. Ist dies die einzige Möglichkeit, dies zu tun?

Gelöst

Danke an @Kuncevic. Mir fehlte die --extract-css-Flagge. 

Arbeitskonfiguration:

"styles": [
    "styles.scss",
    {
        "input": "../node_modules/@org/themes/src/dark.scss",
        "output": "themes/dark",
        "lazy": true
    }
],

Und mit dem folgenden Serving-Skript kann ich über http: // localhost: 4200/themes/dark.bundle.css darauf zugreifen:

ng serve --extract-css --preserve-symlinks

11
jjenzz

Durch die Einstellung von "lazy": true bedeutet, dass es nicht in index.html angezeigt wird, aber es gibt keinen Mechanismus, der dieses Bündel faul laden wird. Überprüfen Sie, ob comment :

Die faule Option faktiert eigentlich nichts. Es verhindert einfach es wird beim Start der Anwendung ausgeführt.

Ich stimme zu, dass "lazy": true zunächst etwas verwirrend ist.

Wenn Sie ng build ausführen, können Sie tatsächlich sehen, was in Ihrem Build ausgegeben wird, und alle von cli erzeugten Dateien analysieren.

Wenn Sie das tun:

{
    "input": "../node_modules/@org/themes/dark.scss",
    "output": "dark",
    "lazy": true
}

Sie sollten in der Lage sein, direkt auf Ihre Datei unter http: // localhost: 4200/dark.bundle.js zuzugreifen - aber sie wird nicht in index.html angezeigt, wenn Sie "lazy": true einstellen.

Wenn Sie dark.bundle.css Bundle anstelle von .__ erhalten möchten. dark.bundle.js Im Dev-Modus können Sie --extract-css-Flag verwenden.

Der Grund, warum cli Stile im js-Bundle im Dev-Modus generiert, ist, weil dieser Weg viel schneller ist. Knospe, wenn Sie Build wie ng buld --prod erzeugen, wird es ohnehin standardmäßig in .css ausgegeben.

9
Kuncevič

Für alle, die globale CSS-Skripts in .angular-cli.json ohne Hash laden möchten, schrieb ich folgendes Skript (z. B. patch-ng-cli.js)

const fs = require('fs');

const stylesFileToPatch = "node_modules/@angular/cli/models/webpack-configs/styles.js";

const regex = /extraPlugins\.Push\(.*\}\)\)\;/;
const patchContent = `
        // PATCHED CONTENT START
        const globalStyles = utils_1.extraEntryParser(appConfig.styles, appRoot, 'styles');
        extraPlugins.Push(new ExtractTextPlugin({ filename: getPath => {
            const generatedFileName = getPath(\`[name]\${hashFormat.extract}.bundle.css\`);
            const name = generatedFileName.split(".")[0];
            const globalAppStylesConfigEntry = globalStyles.find(path => path.output === name);
            if (globalAppStylesConfigEntry && globalAppStylesConfigEntry.lazy){
                console.log(\`\${name} will not be hashed due to lazy loading\`);
                return \`\${name}.bundle.css\`
            }
            console.log(generatedFileName);
            return generatedFileName;
        }}));
        // PATCHED CONTENT END
`;


fs.readFile(stylesFileToPatch, (err, data) => {
    if (err) { throw err; }

    const text = data.toString();

    const isAlreadyPatched = !!text.match("PATCHED CONTENT");

    if (isAlreadyPatched) return console.warn("-- already patched --", stylesFileToPatch);

    console.log('-- Patching ng-cli: ', stylesFileToPatch);
    const patchedContent = text.replace(regex, patchContent);

    const file = fs.openSync(stylesFileToPatch, 'r+');
    fs.writeFile(file, patchedContent, () => console.log("-- Patching -- OK"));
    fs.close(file);
});

Führen Sie dieses Skript dann nach der Installation von npm über die npm-Skripts in package.json aus

"postinstall": "node ./patch-ng-cli.js",
1
riemerio

Da ich die akzeptierte Antwort nicht kommentieren kann, werde ich sie als separate Anmerkung hinzufügen. Bitte verschieben Sie sie dorthin und löschen Sie sie bei Bedarf. Die akzeptierte Antwort basiert also auf einer separaten CSS-Datei. Da Angular 6 Sie können weder --extract-css- noch -ec-Flags in package.json für ng serve und extractCss: true in angular.json für serve config verwenden. Sie können jedoch this verwenden, damit es funktioniert. Dann können Sie Ihren Lazy-Style laden, indem Sie den this -Ansatz mit Promise für APP_INITIALIZER verwenden.

0
Halfist

Ich weiß, dass dies ein alter Beitrag ist, aber ich habe kein vollständiges Beispiel gefunden, nur Fragmente, um Lazy Loading in Angular für CSS-Dateien oder js-Dateien zu implementieren. Dies ist eine Lösung mit Angular 7.1.4-Version und faulem Laden von font-awesome 4.7 und bootstrap 4.

  1. Installiere bootstrap und font-awesome 

    npm install --save font-awesome bootstrap

  2. Bearbeiten Sie Ihre Datei angle.json, um sicherzustellen, dass der Compiler getrennte Dateien im Ordner dist generiert

       "styles": [
          "src/styles.css",
          {
            "input": "./node_modules/font-awesome/css/font-awesome.css",
            "lazy": true,
            "bundleName": "font-awesome"
          },
          {
            "input": "./node_modules/bootstrap/dist/css/bootstrap.min.css",
            "lazy": true,
            "bundleName": "bootstrap"
          }
        ], 
    

Parametererklärungen:

"input": "der Ort, an dem der Befehl aus dem ersten Schritt Bootstrap und font-awesome herunterladen wird" 

"Lazy": "Durch den Wert von true wird sichergestellt, dass der Compiler die Dateien bootstrap.min.css und font-awesome.css nicht in die kompilierten Dateien einbettet Dateien, die an den Browser gesendet werden "

"bundleName": "ist der Name, den Sie im Ordner dist finden."

  1. Gemäß this answer müssen Sie in index.html das folgende script innerhalb des header - Tags unter dem <base href="/"> hinzufügen.

      <script>
         window.onload = function () {
          function loadScript(scriptUrl) {
            const script = document.createElement('script');
            script.src = scriptUrl;
            document.body.appendChild(script);
          }
    
          loadScript('font-awesome.js');
          loadScript('bootstrap.js');
        }
    
     </script>
    

HINWEIS:window.onload = function () wird verwendet, um sicherzustellen, dass die Seite geladen wird (weil sich unsere Dateien im Format dist im Format .js befinden; dies ist der schnelle Weg für Angular) kompilieren)

  1. Führen Sie diesen Befehl aus, um die Anwendung zu kompilieren 

    ng build --extract-css = false --prod

HINWEIS: beim Build verwenden wir --extract-css = false, um .js -Dateien zu generieren

Testen

  • Gehen Sie in den Browser und ändern Sie ihn in dev (F12 oder Rechtsklick und Element untersuchen).
  • Wählen Sie die Registerkarte Netzwerk 
  • Drücken Sie Strg + Umschalttaste + R, um die Seite neu zu laden

Sie müssen in der Lage sein zu sehen, dass die bootstrap.js und font-awesome.js wie im Foto separat geladen werden. Außerdem können Sie die Seite ohne style für einen Moment sehen. => Dies ist der Moment, in dem der Style gut geladen wird nachdem das DOM geladen ist

 enter image description here

0
Rzv Razvan