web-dev-qa-db-fra.com

Styles de thème d'application charge paresseux avec Angular CLI

J'essaie de permuter la href d'un <link /> à des fins de thématisation et les thèmes SCSS résident dans un dossier de packages de mon monopo qui est lié symboliquement dans node_modules. Je dois pouvoir les compiler et les référencer.

Je suis tombé sur le problème fixe suivant: angular/angular-cli # 3401 et j'ai essayé d'implémenter quelque chose de similaire:

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

Ma compréhension (peut-être incorrecte) est que cela compilerait le fichier dark.scss en dist/dark.bundle.css et que je pourrais le charger via http: // localhost: 4200/dist/dark.bundle.css mais cela ne fonctionne pas comme prévu. Est-ce que je comprends mal quelque chose ou que je le fais complètement de travers? 

Comment compiler un fichier SCSS à partir de node_modules que je peux ensuite charger paresseux dans l'application? Existe-t-il une autre/meilleure approche que je pourrais essayer à la place?

Notes complémentaires:

  • Utilisation de Angular version 4.2.4
  • Utilisation de Angular Version CLI 1.3.0
  • La documentation pour cette approche
  • Je travaille dans un monorepo alors node_modules/@org/themes est un lien symbolique 
  • J'ai essayé d'utiliser l'option ng serve --preserve-symlinks au cas où le problème ci-dessus était en cause. Cela n'a fait aucune différence

J'ai examiné la manière dont le site Web Angular Material docs aborde ce problème et il semble qu'ils disposent d'un script de génération personnalisé qui compile les fichiers SCSS en fichiers CSS dans le répertoire assets avant de servir l'application. Je pensais que le problème résolu ci-dessus supprimait la nécessité de cette étape, mais peut-être pas. Est-ce la seule façon de le faire?

Résolu

Merci à @Kuncevic. Il me manquait le drapeau --extract-css

Config de travail:

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

Et avec le script serve suivant, je peux y accéder via http: // localhost: 4200/themes/dark.bundle.css :

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

11
jjenzz

Définir "lazy": true signifie qu'il n'apparaîtra pas dans index.html, mais qu'aucun mécanisme ne permet de charger paresseux ce paquet pour vous. Vérifiez que comment :

L'option paresseux ne charge pas réellement paresseux. Cela empêche juste d'être exécuté au démarrage de l'application.

Je conviens que "lazy": true est un peu déroutant au début.

Si vous exécutez ng build, vous pouvez réellement voir ce qui est généré dans votre construction et analyser tous les fichiers produits par cli.

Quand tu fais:

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

Vous devriez pouvoir accéder à votre fichier directement à l’emplacement http: // localhost: 4200/dark.bundle.js mais il n’apparaîtra pas dans index.html tant que vous aurez défini "lazy": true.

Si vous voulez obtenir dark.bundle.css bundle au lieu de dark.bundle.js en mode dev, vous pouvez utiliser le drapeau --extract-css.

La raison pour laquelle cli génère des styles dans le paquet js en mode dev est parce que cette méthode est beaucoup plus rapide. Bud lorsque vous produisez une compilation telle que ng buld --prod, elle sera quand même générée dans .css par défaut.

9
Kuncevič

Pour tous ceux qui souhaitent utiliser des scannements CSS globaux dans .angular-cli.json chargé sans hachage, j’ai écrit le script suivant (par exemple, 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);
});

Puis exécutez ce script après l’installation de npm via des scripts npm dans package.json

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

Étant donné que je ne peux pas commenter la réponse acceptée, je lui fournirai une note importante séparément. S'il vous plaît déplacez-le là et supprimez d'ici si nécessaire. Ainsi, la réponse acceptée est basée sur un fichier CSS séparé. Depuis Angular 6, vous ne pouvez pas n'utilisez ni drapeaux --extract-css ni -ec dans package.json pour ng serve, ni extractCss: true dans angular.json pour la section serve config. Cependant, vous pouvez utiliser this pour le faire fonctionner. Ensuite, vous pouvez charger votre style paresseux en utilisant this avec une promesse sur APP_INITIALIZER.

0
Halfist

Je sais que ceci est un ancien message, mais je n'ai pas trouvé d'exemple complet, mais uniquement des fragments pour implémenter le chargement différé dans Angular pour fichiers CSS ou fichiers js. Ceci est une solution avec Angular - Version 7.1.4 et chargement paresseux de font-awesome 4.7 et bootstrap 4

  1. Installez bootstrap et font-awesome 

    npm install --save font-awesome bootstrap

  2. Editez votre fichier angular.json pour vous assurer que le compilateur générera des fichiers séparés dans le dossier dist.

       "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"
          }
        ], 
    

Explication des paramètres:

"input": "l'emplacement où la commande de la 1ère étape téléchargera bootstrap et font-awesome" 

"lazy" _: "la valeur de true garantira que le compilateur n'incorporera pas le bootstrap.min.css et font-awesome.css fichiers dans les fichiers compilés qui sont envoyés au navigateur "

"bundleName": "est le nom que vous trouverez dans le dossier dist"

  1. Selon this answer, vous devez ajouter dans index.html le script suivant dans la balise header sous le <base href="/">

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

NOTE:window.onload = function () s'assurait que la page était chargée (ceci parce que nos fichiers dans le dist sont au format .js; c'est le moyen rapide pour Angular compiler)

  1. Exécutez cette commande pour compiler l'application 

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

NOTE: lors de la construction, nous utilisons --extract-css = false pour générer les fichiers .js

Test

  • Allez dans le navigateur et changez-le en dev (F12 ou clic droit et inspecter un élément)
  • Sélectionnez l'onglet Réseau 
  • Appuyez sur Ctrl + Maj + R pour un rechargement dur

Vous devez être capable de voir que les fichiers bootstrap.js et font-awesome.js sont chargés séparément, comme sur la photo. Vous pouvez également voir pendant un moment la page sans style => c'est le moment où le style est bien chargé. après le chargement du DOM

 enter image description here

0
Rzv Razvan