簡體   English   中英

使用 Angular CLI 延遲加載應用程序主題樣式

[英]Lazy load application theme styles with Angular CLI

我正在嘗試切換<link />href以進行主題化,並且 SCSS 主題位於我的 monorepo 的包文件夾中,這些文件夾在 node_modules 中進行了node_modules 我需要能夠編譯和引用這些。

我遇到了以下固定問題: angular/angular-cli#3401並且一直在嘗試實現類似的東西:

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

我的理解(可能不正確)是這會將dark.scss文件編譯為dist/dark.bundle.css並且我可以通過http://localhost:4200/dist/dark.bundle.css加載它但是它沒有按預期工作。 我是誤解了什么還是這樣做完全錯誤?

如何從node_modules編譯一個 SCSS 文件,然后我可以在應用程序中延遲加載? 我可以嘗試另一種/更好的方法嗎?

附加說明:

  • 使用 Angular 版本4.2.4
  • 使用 Angular CLI 1.3.0
  • 這種方法文檔
  • 我在 monorepo 工作,所以node_modules/@org/themes是一個符號鏈接
  • 我曾嘗試使用ng serve --preserve-symlinks選項以防上述問題。 它沒有任何區別

我已經研究了Angular Material 文檔網站解決這個問題的方式,似乎他們有一個自定義構建腳本,可以在為應用程序提供服務之前將 SCSS 文件編譯為assets目錄中的 CSS 文件。 我認為上面的固定問題消除了這一步的需要,但也許不是。 這是唯一可以做到的方法嗎?

已解決

感謝@Kuncevic。 我錯過了--extract-css標志。

工作配置:

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

使用以下服務腳本,我可以通過http://localhost:4200/themes/dark.bundle.css訪問它:

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

通過設置"lazy": true意味着它不會出現在index.html但沒有機制可以為您延遲加載該包,請檢查該評論

lazy 選項實際上不會延遲加載任何東西。 它只是阻止它在應用程序啟動時執行。

我同意"lazy": true起初有點令人困惑。

如果您運行ng build您實際上可以看到構建中輸出的內容並分析 cli 生成的所有文件。

當你這樣做時:

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

您應該能夠直接在http://localhost:4200/dark.bundle.js上訪問您的文件,但是當您設置"lazy": true它不會出現在index.html"lazy": true

如果你想在開發模式下獲得dark.bundle.css包而不是dark.bundle.js ,你可以使用--extract-css標志。

cli 之所以在 dev 模式下將樣式生成到js bundle 中,是因為這種方式要快得多。 Bud 當你像ng buld --prod那樣做 prod 構建時,它會默認輸出到.css

我知道這是一篇舊帖子,但我還沒有找到一個完整的例子,只是片段來在 Angular 中為CSS 文件js 文件實現延遲加載。 這是 Angular 7.1.4 版本和font-awesome 4.7bootstrap 4延遲加載的解決方案

  1. 安裝 bootstrap 和 font-awesome
    npm install --save font-awesome bootstrap
  1. 編輯angular.json文件以確保編譯器將生成分離的文件到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" } ],

    參數說明:

"input" : "第一步中的命令將下載引導程序和字體的位置"

"lazy" : " true的值將確保編譯器不會將bootstrap.min.cssfont-awesome.css文件嵌入到發送到瀏覽器的編譯文件中"

"bundleName" : "是您將在dist文件夾中找到的名稱"

  1. 根據答案,您必須在<base href="/">下的標頭標記內添加以下腳本index.html
          <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>

注意: window.onload = function ()用於確保頁面被加載(這是因為我們進入dist的文件是.js格式;這是Angular編譯的快捷方式)

  1. 運行此命令,編譯應用程序
    ng build --extract-css=false --prod

注意:在構建時我們使用--extract-css=false來生成.js文件

測試

  • 進入瀏覽器並將其更改為 dev(F12 或右鍵單擊並檢查元素)
  • 選擇網絡選項卡
  • 按 Ctrl+Shift+R 進行硬重新加載

您必須能夠看到 bootstrap.js 和 font-awesome.js 像照片中一樣分別加載,並且您還可以看到沒有樣式的頁面=> 這是樣式加載良好的時刻DOM 加載后

在此處輸入圖片說明

由於我無法評論已接受的答案,因此我將為其單獨提供一個重要說明。 如果需要,請將其移至此處並從此處刪除。 因此,接受的答案基於單獨的 CSS 文件。 從 Angular 6 開始,你不能package.jsonng serve extractCss: true --extract-css-ec標志,也不能在angular.jsonserve配置部分使用extractCss: true 不過,您可以使用這種方法使其工作。 然后你可以通過在APP_INITIALIZER上使用這種方法來加載你的懶惰風格。

對於任何想要在 .angular-cli.json 延遲加載而沒有哈希的情況下使用全局 css scipts 的人,我編寫了以下腳本(例如 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);
});

然后在 npm install 之后通過 package.json 中的 npm 腳本運行這個腳本

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM