如何在NX模块化联邦工作区将@angular/material样式从自定义库导出到应用
问题描述
我按照官方文档创建了基于动态模块联邦的Angular微前端,执行的创建命令如下:
npx create-nx-workspace demo-app --preset=empty npm install --save-dev @nrwl/angular nx g @nrwl/angular:host host-app --dynamic nx g @nrwl/angular:remote remote-app --host=host-app --port=4201
同时创建了自定义库:
nx generate @nrwl/angular:library custom-lib --directory=libs --buildable --publishable --importPath=@monorepo/my-custom-lib
工作区目录结构如下:
apps/ - host-app/ - src/ - styles.scss - project.json ... - remote-app/ - src/ - styles.scss - project.json ... libs/ - custom-lib/ - src/ - lib/ - components/ - header-component/ - custom-lib.module.ts - index.ts - package.json ... - themes/ - mat-styles.scss package.json nx.json ...
仅在custom-lib中安装了@angular/material,并将其置于libs/custom-lib/package.json的peerDependencies中,创建了使用该库的HeaderComponent,已完成Material模块的导入/导出。
为将@angular/material样式导出复用至宿主或远程应用,执行了以下步骤:
- 在
libs/themes/mat-styles.scss中导入样式:
@import './styles//variables'; @import '~@angular/material/prebuilt-themes/indigo-pink.css'; span { font-weight: 400; font-size: 1.125rem; line-height: 1.75rem; }
- 更新
apps/host-app/project.json的构建配置,添加全局样式路径; - 在
apps/host-app/src/styles.scss中导入mat-styles.scss; - 在
apps/host-app/src/index.html中添加Material Icons链接。
但出现如下错误:
./apps/host-app/src/styles.scss - Error: Module build failed (from ./node_modules/css-loader/dist/cjs.js): Error: Can't resolve '~@angular/material/prebuilt-themes/indigo-pink.css' in '/Users/IAM/Movies/demo-app/apps/host-app/src' ./apps/host-app/src/styles.scss?ngGlobalStyle - Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js): HookWebpackError: Module build failed (from ./node_modules/css-loader/dist/cjs.js): Error: Can't resolve '~@angular/material/prebuilt-themes/indigo-pink.css' in '/Users/IAM/Movies/demo-app/apps/host-app/src'
注:注释掉mat-styles.scss中的Angular Material样式导入后,普通样式可正常导出。需要实现@angular/material样式从自定义库到应用的导出复用。
解决方案
核心原因
错误源于两点:
- 宿主应用未直接安装
@angular/material,scss解析器从宿主应用上下文查找依赖时无法找到该包; - 新版本Angular/CSS Loader已废弃
~前缀解析node_modules资源的方式。
具体解决步骤
修正scss导入路径
修改libs/themes/mat-styles.scss中的Material样式导入语句,移除~前缀:@import '@angular/material/prebuilt-themes/indigo-pink.css';在根依赖中安装@angular/material
由于custom-lib将@angular/material设为peer依赖,宿主及远程应用需显式安装该依赖,执行根目录下的安装命令:npm install @angular/material @angular/cdk安装后该依赖会出现在根
package.json中,Nx的monorepo依赖解析机制能让所有应用正常访问。确认样式配置正确性
检查apps/host-app/project.json的build.options.styles配置,确保主题文件路径正确,示例配置如下:"styles": [ "apps/host-app/src/styles.scss", "libs/themes/mat-styles.scss" ]若保持在
styles.scss中导入mat-styles.scss的方式,需确保导入路径无误。验证应用构建
重启宿主应用验证效果:nx serve host-app此时Material主题样式应能正常加载并应用到宿主及远程应用中。
优化建议
- 将主题样式封装为Nx库而非单独的
libs/themes目录,便于统一管理和跨应用复用; - 远程应用需重复步骤2,安装
@angular/material依赖,确保样式解析正常。
内容的提问来源于stack exchange,提问作者Rocky

