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