Angular 6图书馆共享样式表

31
如何设置一个 index.scss 并导入全局样式表以供 Angular 6 库使用?Angular CLI 生成带有根组件和组件 scss 的库,但是添加或导入到根组件的样式对子组件不可用。这默认情况下是有道理的,但我找不到任何关于如何设置它的信息或示例。在 angular.json 中使用 "projectType": "library" 似乎无法使用 "styles": [...] 路径,该路径可以用于具有 "projectType": "application" 的项目类型。感谢您提前的帮助!
更新:我的项目是使用 Angular CLI v6.0.5 初始化的,遵循这个指南:https://medium.com/@tomsu/how-to-build-a-library-for-angular-apps-4f9b38b0ed11 简述:指南介绍了如何为 Angular 应用程序构建库。
ng new my-app --style=scss
ng generate library my-library --prefix ml

这是Angular 6生成的文件结构:

    my-app
      projects/
        my-library/
          src/
            lib/
              shared/..
              widgets/..
              my-library.component.ts
              my-library.module.ts
            sass/
              _variables.scss
              styles.scss // <<< This is where I want to `@import 'variables';`, and for it to be available in all the components of the "my-library" project.
            public_api.ts
      src/
        app/
          app.module.ts // << imports projects/my-library/lib/my-library.module as "my-library".
        main.ts
        index.scss
        index.html
      README.md

软件包版本:

    Angular CLI: 6.0.5
    Node: 10.2.1
    OS: darwin x64
    Angular: 6.0.3
    ... animations, common, compiler, compiler-cli, core, forms
    ... http, language-service, platform-browser
    ... platform-browser-dynamic, router

    Package                            Version
    ------------------------------------------------------------
    @angular-devkit/architect          0.6.5
    @angular-devkit/build-angular      0.6.5
    @angular-devkit/build-ng-packagr   0.6.5
    @angular-devkit/build-optimizer    0.6.5
    @angular-devkit/core               0.6.5
    @angular-devkit/schematics         0.6.5
    @angular/cli                       6.0.5
    @ngtools/json-schema               1.1.0
    @ngtools/webpack                   6.0.5
    @schematics/angular                0.6.5
    @schematics/update                 0.6.5
    ng-packagr                         3.0.0
    rxjs                               6.2.0
    typescript                         2.7.2
    webpack                            4.8.3

看起来你没有使用 @angular/cli 创建你的项目,如果这是一个新项目,我强烈建议你使用它。 - Ploppy
@Ploppy 我已经这样做了,我使用这个指南启动了项目:https://medium.com/@tomsu/how-to-build-a-library-for-angular-apps-4f9b38b0ed11 - xaunlopez
我也遇到了完全相同的问题。你找到解决方法了吗? - Bram W.
@BramW。不,我没有,我只是在我想要使用commons的每个文件中添加了导入。 - xaunlopez
2
https://github.com/angular/angular-cli/issues/10927 表明这是 ng-packagr 的限制,而 https://github.com/angular/angular-cli/issues/10869 则指定了一种使用 gulp 的解决方法。不太喜欢引入 gulp,因此我尝试并考虑的另一个(非理想的)选项是使用 Angular CLI 创建的“root”库组件来保存库的全局样式。它将具有一个空模板,但带有 encapsulation: ViewEncapsulation.None,这将导致其样式添加到全局样式中。然后在应用程序中的某个位置包含(空)模板标记。 - Jim Barrett
将变量导入到每个组件的 SCSS 中不是您的选择吗? - JayChase
4个回答

16

对于全局样式,我在这个问题中已经回答了。

更新

对于ng-packgr 9.x及以上版本

现在可以直接支持将资源复制到输出文件夹,具体请参见此页面

{
  "$schema": "./node_modules/ng-packagr/package.schema.json",
  "name": "@my/library",
  "version": "1.0.0",
  "ngPackage": {
    "assets": [
      "CHANGELOG.md",
      "./styles/**/*.theme.scss"
    ],
    "lib": {
      ...
    }
  }
}

因此,在您的项目中,您可以通过以下方式从库中导入文件来使用样式:

@import '@my/library/path-to-file/file-name.scss'

或者使用显式相对路径(确保根据需要使用尽可能多的../)。
@import '../node_modules/@my/library/path-to-file/file-name.scss'

旧答案

  1. 在您的库的根文件夹中创建一个index.scss文件。如果您按照Angular的这个指南,那么您的路径将是my-project/projects/my-library/index.scss。这也是您的package.json所在的文件夹。

因此,index.scss将是包含您的变量和mixin的文件。

$grey: #222;
@mixin mymixin {
    background: #222;
}
  1. 使用import将此内容包含在你的库scss文件中
@import '../../index.scss';

或者是你组件scss文件的相对路径。

  1. 现在为了让这个文件在你的应用项目中,将它复制到构建后的dist目录中。为了做到这一点,请编辑你的angular库项目的package.json文件(不是库的文件)。
{
    "name": "my-project",
    "version": "1.0.0",
    "scripts": {
        "ng": "ng",
        "start": "ng serve",
        "build": "ng build && npm run copyScss",
        "test": "ng test",
        "lint": "ng lint",
        "e2e": "ng e2e",
        "copyScss": "xcopy \"projects\my-library\index.scss\" \"dist\\my-library\\\""
    },

    ...
}
  1. 非常重要:不要使用 ng build 命令构建你的库,而是使用 npm run build。这将自动执行复制命令。现在,index.scss 文件将随着你的库一起导出到 my-project/dist 文件夹中。

  2. 在你的应用程序项目的 scss 文件中引入 index.scss 文件。

// ~ stands for the node_modules folder
@import '~my-library/index.scss';

现在你已经在安装了你的库的所有项目中拥有了所有的库mixin。
干杯!
PS:变通方法并不是最优雅的解决方案,但当没有其他办法时,它们可以解决问题!

如果您想在当前项目之外公开库,例如通过 npm link 或发布到 npm 模块,您该如何让 lib-mixin 可供消费者应用程序使用? - Mozgor
1
@Mozgor 这个问题已经得到解决。请看第三点。index.scss会被复制到dist文件夹中,并随库一起发布。当你执行npm link时,包括index.scss在内的dist文件夹中的所有内容都会被复制到node_modules文件夹下的库文件夹中。然后,按照第五点所述,在使用者应用程序中简单地导入index.scss即可。附言:不要跳过第四点,否则它将无法正常工作。 - Xpleria
确实,我误读了并认为副本是在消费者应用程序中完成的。感谢您指出这一点! 您能否解释为什么index.scss应该是lib-root-level,并且如果库只有一个组件是否需要它?在这种情况下,我宁愿只公开主题文件,但我可能是错的。 - Mozgor
1
@Xpleria:好的。在“lib”文件夹内,我添加了一行代码“entryFile”: “src/public-api.ts”,并运行了命令ng build <library-project-name> --prod。这将在库项目内创建dist文件夹,而不是像以前一样在“projects”文件夹级别上创建。我该如何确保dist文件夹在“projects”文件夹级别上创建? - suvenk
1
@Sofia,你可以使用@import '@my/library/path-to-file/file-name.scss'。我也更新了我的回答。干杯 :) - Xpleria
显示剩余6条评论

1

您是否尝试将组件的封装级别设置为 "none",作为组件元数据的一部分?像这样:

@Component({
  selector: 'app-component',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  encapsulation: ViewEncapsulation.None
})

ViewEncapsulation级别如下:

  • ViewEncapsulation.Emulated:默认情况下,Angular模拟Shadow DOM。
  • ViewEncapsulation.Native:使用浏览器自己的Shadow DOM。
  • ViewEncapsulation.None:样式是全局的。

请查看关于ViewEncapsulation的Angular文档和我写的博客文章


@JeffyHouiser,你怎么从库中引入主题到项目中呢? - hackp0int
@IamStalker,很抱歉,我不理解你的问题。 - JeffryHouser
4
不应使用ViewEncapsulation.None,因为它仅在使用它的组件初始化后添加全局样式。这可能会导致一些奇怪的情况,在你切换到应用程序中的其他随机部分之后才会破坏某些其他随机部分。 - Dr. Hilarius

-1

我认为人们可能忽略了一个事实,即尽管存在封装选项,全局样式仍然会在样式标签中输出,并且可以在整个项目中级联。

这是我的设置:

enter image description here

  1. 我的全局样式:styles.scss以style标签的形式输出。规则针对所有匹配的类和元素,如预期的那样。即使在组件内部也是如此。

  2. 组件样式是封装的。这是它们的价值所在。它们覆盖全局样式,并将组件特定的样式与组件族保持一致。

  3. 需要时,在任何组件的.scss文件顶部明确包含诸如variables.scss、mixins.scss等的@includes。

@import '../../../../scss/includes/variables';

还需要什么?


全局的styles.scss文件适用于Angular应用程序,但似乎不适用于Angular库,这就是OP试图定义全局样式的情况。不幸的是,似乎只有一些变通方法可以解决这个问题。 - The Once-ler

-1
在项目中运行ng init,这样它将初始化项目成为一个Angular CLI项目。 编辑: 我的错,看起来他们从CLI中删除了init。你可以尝试ng new --src 这可能会覆盖一些文件,所以请在项目的副本上尝试。

"The specified command ("init") is invalid. For a list of available options, run "ng help"." - xaunlopez
我的错,看起来他们从cli中删除了init命令。你可以尝试使用“ng new --src”命令。这可能会覆盖一些文件,所以请在项目的副本上尝试此操作。 - Arno4Jackie

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