如何将全局样式添加到 Angular 6/7 库

Posted

技术标签:

【中文标题】如何将全局样式添加到 Angular 6/7 库【英文标题】:How to add global style to angular 6/7 library 【发布时间】:2019-04-21 23:27:25 【问题描述】:

我试图以与 Angular 应用程序相同的方式添加全局样式,但它完全不起作用。

我的库名称是 example-lib,所以我将 styles.css 添加到 /projects/example-lib/。我在 angular.json 主文件中添加了样式:

...
"example-lib": 
  "root": "projects/example-lib",
  "sourceRoot": "projects/example-lib/src",
  "projectType": "library",
  "prefix": "ngx",
  "architect": 
    "build": 
      "builder": "@angular-devkit/build-ng-packagr:build",
      "options": 
        "tsConfig": "projects/example-lib/tsconfig.lib.json",
        "project": "projects/example-lib/ng-package.json",
        "styles": [
          "projects/example-lib/styles.css" <!-- HERE 
        ],
      ,
...

但是当我尝试使用命令构建库时:

ng build example-lib

我收到错误:

  Schema validation failed with the following errors:
  Data path "" should NOT have additional properties(styles)

我猜这是在单独的库中添加全局样式的另一种方法。谁能帮帮我?

【问题讨论】:

看看这里:github.com/angular/angular-cli/issues/10869 路径从src开始,请提供您的项目结构 另外,您可以创建一个SCSS 文件并将其导入到您项目的原始style.scss 中。 您找到解决方案了吗? 【参考方案1】:

正如@codeepic已经指出的,目前有a standard solution。

ng-package.json添加

"assets": ["./styles/**/*.css"]

提供的路径应该是您的文件的路径。同时,它们将是您的 /dist 文件夹中的路径。 在构建时,文件将被复制到 /dist。您的库的用户将能够将它们添加到他们的全局样式中,如下所示。

/* styles.css */
@import url('node_modules/<your-library-name>/styles/<file-name>');

这样您可以复制任何类型的文件。

附:与 CSS 一起使用时,不要忘记您可以创建一个可以像 node_modules/&lt;your-library-name&gt;/styles 一样导入的 index.css 文件。

【讨论】:

【参考方案2】:

来自Compiling css in new Angular 6 libraries:

    在我们的库中安装一些 devDependencies 以捆绑 css:

    ng-packagr scss 包 ts 节点

    创建css-bundle.ts:

    import  relative  from 'path';
    import  Bundler  from 'scss-bundle';
    import  writeFile  from 'fs-extra';
    
    /** Bundles all SCSS files into a single file */
    async function bundleScss() 
      const  found, bundledContent, imports  = await new Bundler()
        .Bundle('./src/_theme.scss', ['./src/**/*.scss']);
    
      if (imports) 
        const cwd = process.cwd();
    
        const filesNotFound = imports
          .filter(x => !x.found)
          .map(x => relative(cwd, x.filePath));
    
        if (filesNotFound.length) 
          console.error(`SCSS imports failed \n\n$filesNotFound.join('\n - ')\n`);
          throw new Error('One or more SCSS imports failed');
        
      
    
      if (found) 
        await writeFile('./dist/_theme.scss', bundledContent);
      
    
    
    bundleScss();
    

    在库的 /src 目录中添加 _theme.scss,该目录实际上包含并导入我们要捆绑的所有 css。

    添加 postbuild npm 脚本以运行 css-bundle.ts

    将它包含在 angular.json 中应用程序的样式标签中

【讨论】:

你能解释一下包括什么吗? > 将其包含在 angular.json 中应用程序的样式标签中 @OPV 打开 angular.json 并转到样式属性(应该在 build > options 属性中)并将其添加为数组项。你可以在这里查看更多信息:truecodex.com/course/angular-6/… css-bundle.ts 链接已失效。 感谢@Episodex 提及这一点。用内容更新了答案。【参考方案3】:

来自this issue solution

cpxscss-bundle 作为开发依赖项安装到您的package.json。然后在你的 package.json “scripts” 属性中添加以下条目:

"scripts": 
  ...
  "build-mylib": "ng build mylib && npm run build-mylib-styles && npm run cp-mylib-assets",
  "build-mylib-styles": "cpx \"./projects/mylib/src/lib/style/**/*\" \"./dist/mylib/style\" && scss-bundle -e ./projects/mylib/src/lib/style/_style.scss -d ./dist/mylib/style/_styles.scss",
  "cp-mylib-assets": "cpx \"./src/assets/**/*\" \"./dist/mylib/assets\"",
  ...

将“mylib”替换为您的真实库名称,然后在您的终端build-mylib 中运行。这会将您的 scss 资产编译到您的 dist 文件夹。

您在实际的 Angular 项目中使用这种全局样式,只需将它们导入到项目设置中的 angular.json 文件中即可:

"styles": [
  "src/styles.scss",
  "dist/my-shiny-library/_theme.scss"
],

(如果您的项目在同一个工作区中,则使用 dist,如果是导入的库,则使用 node_moduled)

【讨论】:

【参考方案4】:

我有一个解决方法。只需在没有视图封装的情况下创建库的根组件,其所有样式都将是全局的。

my-library.component.ts

import  Component, OnInit, ViewEncapsulation  from '@angular/core';

@Component(
  selector: 'lib-my-library',
  templateUrl: './my-library.component.html',
  styleUrls: ['./my-library.component.scss'],
  encapsulation: ViewEncapsulation.None
)
export class MyLibraryComponent implements OnInit 

  constructor()  

  ngOnInit() 
  


my-library.component.html

<!-- html content -->

my-library.component.scss

@import './styles/core.scss';

现在您的 my-library.component.scsscore.scss 是全球性的

styles/core.scss

body 
    background: #333;

core.scss 是可选的,我只是想保持根文件干净。


更新:如果您也想要混入和变量,请关注this answer。

【讨论】:

这应该如何工作?我是否必须将每个库组件包装在 lib-my-library 中? 不,样式是全局的。意思是,它们适用于所有元素,无论它们属于哪个组件。由于encapsulation: ViewEncapsulation.None这一行,样式没有被封装。 感谢@NeilPatrao - 工作就像一个魅力。您知道现在是否有更好的方法,或者您使用空组件的解决方法仍然是最干净的解决方案吗? @codeepic 嗨,查看这个答案***.com/a/57219374/1393400 它正是您正在寻找的解决方案。 @NeilPatrao - 只需检查angular.io/guide/creating-libraries 官方库文档上的信息,看起来从 ng-packagr 版本 9 开始,您可以配置工具以自动复制资产。更多信息:angular.io/guide/…

以上是关于如何将全局样式添加到 Angular 6/7 库的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6 库组件和 SCSS

如何使用 Webpack 和 Angular 将全局 css 样式与 in-js 组件样式一起使用?

NativeScript/Angular - 如何导入全局样式?

Angular 5 Material 如何将下拉菜单添加到多级轮播样式的 SideNav?

将 Angular 2 (click) 属性全局添加到 CSS

如何将自定义样式添加到 Angular Material Table 单元格的一小部分?