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

62

我试图以与 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)

我想这是在一个独立的库中添加全局样式的另一种方式。有人能帮我吗?


请在此处查看:https://github.com/angular/angular-cli/issues/10869 - Jacopo Sciampi
路径从 src 开始,请告诉我们您的项目结构。 - user4676340
另外,您可以创建一个 SCSS 文件并将其导入到项目原始的 style.scss 中。 - user4676340
3
你解决了这个问题吗? - Janier
5个回答

39

我有一个解决方法。只需在你的库的根组件中不使用视图封装,所有样式将变成全局的。

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() {
  }

}

我的图书馆.component.html

<!-- html content -->

我的图书馆.component.scss

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

现在你的my-library.component.scsscore.scss是全局的。

styles/core.scss

body {
    background: #333;
}

core.scss是可选的,我只是喜欢保持根文件的清洁。


更新:如果您还想要自己的混合器和变量,请按照此答案操作。


1
不,样式是全局的。这意味着它们适用于所有元素,无论它们属于哪个组件。由于此行“encapsulation: ViewEncapsulation.None”,样式没有被封装。 - Xpleria
谢谢@NeilPatrao - 运行得很好。你知道现在是否有更好的方法,还是你的空组件解决方案仍然是最干净的解决方案? - codeepic
1
@codeepic 你好,看一下这个答案 https://dev59.com/E1UL5IYBdhLWcg3wSWVu#57219374 它恰好有你正在寻找的解决方案。 - Xpleria
3
@NeilPatrao - 我只是在检查 https://angular.io/guide/creating-libraries 官方库文档的信息,看起来从ng-packagr的9版本开始,您可以配置该工具自动复制资产。更多信息请参见:https://angular.io/guide/creating-libraries#managing-assets-in-a-library - codeepic
这是一个非常出色的解决方案 :) - Datum Geek
显示剩余4条评论

15

正如@codeepic已经指出的那样,目前有一个标准解决方案

ng-package.json中添加

"assets": ["./styles/**/*.css"]
提供的路径应该是你的文件路径。同时,它们也将是你的/dist文件夹内的路径。
构建时,文件将被复制到/dist中。你的库的用户将能够像下面这样将它们添加到他们的全局样式中。
/* styles.css */
@import url('node_modules/<your-library-name>/styles/<file-name>');

通过这种方式,您可以复制任何类型的文件。

附言:当与CSS一起使用时,请记住您可以创建一个 index.css 文件,它可以像 node_modules/<your-library-name>/styles 一样被导入。


还有需要注意的是,您需要创建一个名为“assets”的文件夹,其中包含您的样式。 - Jnr
非常好,对我来说运行良好,在这里工作得很好,感谢您的帮助。 - Hoiama Rodrigues
这种方法对我有点用,但是我在node_modules下找不到我的库文件夹。不过我在dist下找到了它。我应该担心这种方法不可靠吗?现在我的结构看起来像这样:workspace/projects/myLib/src/assets/styles/core.scssworkspace/projects/myApp/src/styles.scss,我从库中导入。 - Guilherme Taffarel Bergamin

4

来自编译新的Angular 6库中的CSS

  1. install some devDependencies in our library in order to bundle the css:

    • ng-packagr
    • scss-bundle
    • ts-node
  2. Create 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();
    
  3. Add _theme.scss inside the /src directory of the library that actually contains and imports all the css that we want to bundle.

  4. Add postbuild npm script to run the css-bundle.ts

  5. Include it in the styles tag in your Application in the angular.json


1
你能解释一下 include 是什么吗?> 在 angular.json 中的 styles 标签中包含它。 - OPV
@OPV 打开 angular.json 文件并转到 styles 属性(应该在 build > options 属性内),将其添加为数组项。您可以在此处查看更多信息:https://www.truecodex.com/course/angular-6/how-to-include-external-css-and-js-file-in-angular-6-angular-7 - yazantahhan
css-bundle.ts 的链接已经失效。 - Episodex
1
感谢@Episodex提到这个问题。已更新答案并添加了内容。 - yazantahhan

3

此问题解决办法中获得。

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

2

1- 确保你将样式放在库内

例如:

projects/your-lib-name/assets/styles.css

2- 然后在 ng-package.json 中添加 assets 规则(当然是在库内)

    {
      "$schema": ...  , 
      "dest": ...   , 
>     "assets": [
>         "./assets/*"
>       ],
      "lib": ...
    }

在您的应用程序中,您可以使用这个资产

  "styles": [
              "../your-lib-name/assets/styles.css"
            ]

this is a tutorial


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接