Closed mkennedy3000 closed 4 years ago
First of, I love the effort you are putting forward with nx!
Not having support for shared styles (i.e. similar to Angular Material theming support) at the library level is a major roadblock to adopting the current monorepo approach, however.
So far (using other library builders), I always had to opt for building and linking the libraries to ensure style import paths can be resolved, e.g. import "~mylib/styles/theming"
during the development process. Addressing this use case would be most welcome.
I'm a little confused - as I had no issues implementing this across apps from a shared library.
I have all my shared assets (sass, i18n translations, images, etc.) inside libs/theme
. My NX workspace scope is @maestro
.
In my root package.json
, I add a reference to my shared assets lib.
"@maestro/theme": "file:libs/theme",
This will allow you to access SASS imports like so in your apps/
directory:
@import '~@maestro/theme/sass/global/tools/colors';
To get shared non-sass files to work, you need to update the .angular-cli.json
to copy the glob pattern from libs/theme
into your app.
"assets": [
"assets",
"favicon.ico",
{
"glob": "**/*",
"input": "../../../libs/theme",
"output": "./assets/"
}
],
Now everything inside of libs/theme
is available to your Angular projects from /assets
.
@sean-perkins I'll double check my setup, conceivably it was an issue with a particular version of the underlying Angular cli/Angular version. I ran into resolution errors w.r.t. the SASS file imports for the theme.
@mkennedy3000's request is doable with @sean-perkins mentioned approach. Unfortunately the files are locked in your node_module
and will not be updated on changes unless you remove the reference and do fresh install.
We completely extracted styles into a theme library which almost only contains mixins. They can be used in all other libs and apps. We would like to import them either with @import '~@theme-lib/src/sass/mixins/buttons';
or import '~theme-lib/src/sass/mixins/buttons'
.
The reference in package.json feels wrong. Any other ideas?
apps
|-app-1
|- app-using-ui-lib-and-theme-styles
|-app-2
libs
|-ui-lib
|-lib-using-theme-styles
|-api-lib
|-chart-lib
|-another-lib
|-theme-lib
|- src
|-sass
@paesku is spot on - the suggestion from @sean-perkins has me up and running, but it's been much more pain than usual for me to put my 'guess-and-check' styles hat on lately. I'd be happy to spearhead the work and submit a PR, I just don't know where to start other than some ugly pre-start script that copies everything to my app's src/assets and syncs changes back to the lib. Thinking there has to be a better way...
@paesku's request is exactly what I need.
I tried @sean-perkins approach and it seems to work for me (without reinstall), but of course it would be great if there is any way nx could provide a native way for this in future.
Is there any ongoing work or anything I can help with?
I also ran into this challenge - would be great if nx had a solution for this. Maybe we can already collect requirements?
(@import "~@scope/lib-name";)
I've been using webpack to compile LESS into css, separately from Angular libraries
libs
|_ styles
|_ css
|_ less
|_ package.json
|_ webpack.conf.js
In my webpack config
var webpack = require('webpack');
var path = require('path');
var MODULE_BUILD_DIR = path.resolve(__dirname, 'css');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const extractLess = new ExtractTextPlugin({
filename: "output_name.css",
disable: process.env.NODE_ENV === "development"
});
module.exports = {
entry: './libs/styles/less/style.less',
output: {
path: MODULE_BUILD_DIR,
filename: 'output_name.css'
},
module: {
rules: [
{
test: /\.less$/,
use: extractLess.extract({
use: [
{
loader: "css-loader"
},
{
loader: "less-loader",
options:{
sourceMap: true,
}
},
],
fallback: "style-loader"
})
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '../[path][name].[ext]'
}
}
]
}
]
},
plugins: [
extractLess
]
};
When I'm bundling libs using ng-packagr
it copied styles library as well.
Then able to use @import "~@scope/lib-name";
in LESS file when npm package is installed from file directly "@scope/lib-name": "file:libs/lib-name",
Any chance to implement ability for referencing library's scss from apps?
I'd love a solution for this. @sean-perkins your solution didn't work for me. When I type npm install, it doesn't install my local lib. However, if I type npm i @fs/theme it will install a link for the package in node modules, and add new entry in package.json with the name theme only without @fs/ part.
Not a solution obivously, but for now I just have a symbolic link in place ...
mklink /D .\node_modules\@myscope\theme ..\..\libs\theme
At least this gets my project going for now ... And it DOES refresh the dev server when I change something in the theme.
I created a styles.scss
in the root of my lib. Where can I reference it?
I just realised i opened an issue related to that one. So any updates on this?
Is this issue resolved? Can anyone suggest a better way for referencing library's scss from apps?
@paesku, How did you accomplish this, can you help me?
@amrstha it's pity that there is no proper solution for this issue.
I'm still referencing styles within apps or *libs like this @import 'scss-library/src/sass/scss-file';
altough my IDE (webstorm) comlaints about unresolved path, it all works fine.
├── apps
├── app-1
└── app-2
└── libs
├── library-1
├── library-2
└── scss-library
whereas the scss-library
is a normal library setup with nx.
The solution I followed is this.
I have a theme library in libs. In libs/theme/package.json, change the name to:
@fs/theme
in global package.json I added:
"@fs/theme": "file:libs/theme",
npm install
from app's styles.scss file I import the library as this:
@import '~@fs/theme/src/styles/all';
Key component to getting this to work:
Run npm install
after adding your libraries to the package.json
So I've tried this but I'm wondering if anyone can find a problem with:
angular.json
:
"projects": {
"dashboard": {
"architect": {
"build": {
"options": {
"styles": [
"libs/theme/src/lib/styles.scss",
],
I'm including the "theme" scss file from the theme lib.
You do get the application to rebuild when these files are edited and saved.
With the package.json
method above, you have to break the build, npm install, and recompile each time you make changes to the theme scss files when included this way.
🎄
@markgoho how do you use the styles of styles.scss then in your application? I tried your approach, VSCode is able to resolve the styles (see screenshot) but when I run ng serve
, I get an error (just like the mixin or the variable does not exist).
@markgoho seems that I've found the reason: the SCSS style gets completely preprocessed and compiled by the build process when you include it your way. So we do not have a chance to use mixins or variables this way.
Ok guys, this is what works for my so far: I added the folder where I place my global SCSS files to the stylePreprocessorOptions
section of angular.json
(see also https://github.com/angular/angular-cli/wiki/stories-global-styles). This way, everything works as expected (I can use the styles, variables and mixins in SCSS scripts throughout the workspace plus reload on change works).
The only drawback is that VSCode does not recognize this and therefore does not offer any Intellisense-support on global styles. To achieve this, I also added a search pattern to the styles
section in angular.json
- see screenshot for complete config.
I'm not quite sure if this has any side effects, especially for the build process (we try to go towards incremental builds for the whole workspace), but for now it works.
After all: I'd highly appreciate if NRWL came up with a solution/best practice for this use case since many users of NX face it for years.
Hi!
My setup looks like this, maybe this would help somehow:
I have a lib called my-styles
with some scss files under libs/my-styles/src/lib/styles/
:
_variables.scss
_core.scss
At angular.json
I set the stylePreprocessorOptions
like this (as already mentioned) for every app:
"stylePreprocessorOptions": {
"includePaths": ["libs/hmi-styles/src/lib/styles/"]
}
At the styles.scss
of an app I include the styles from the my-styles
lib like this:
@import 'variables';
@import 'core';
When I need a scss variable from the lib at a scss file of a component, I do the following:
@import 'variables';
// you have access to all variables defined at _variables.scss of the lib
So basically you have to import the scss file where you defined the variables to have access to them.
@skydever thanks for sharing - the same works for me. What IDE/Editor are you using? Does it support this approach with Intellisense/Autocompletion?
hi @achimschrepfer! I am using vscode but the intellisense/autocompletion seems not work. Should it work out of the box or is there an extension required for this?
I'm using the SCSS Intellisense extension for VScode. But if I set up as you suggested, Intellisense does not work at all.
As you can see in my last comment above yours, I've managed to get Intellisense support by adding the styles not only to stylePreprocessorOptions
but also to the styles
option in the architect settings.
I see, thx :+1:
Hi @achimschrepfer
So I have the theme lib:
And in the styles.scss I have:
@charset "UTF-8";
@import './scss/normalize';
@import './scss/typography';
@import './scss/color';
@import './scss/spacing';
@import './scss/forms';
:root {
--header-height: 48px;
--nav-width: 256px;
--border-radius: 6px;
--box-shadow: 0 4px 6px 0 hsla(0, 0%, 0%, 0.2);
--border: 1px solid var(--color-neutral-600);
}
... more styles
In my angular.json for the apps that I want to use my theme lib styles:
projects: {
"dashboard": { <---- my app name
"architect": {
"build": {
"options": {
"styles": [
"libs/theme/src/lib/styles.scss",
],
I'm only using CSS Custom Properties (CSS Variables) declared at the root level and thus are accessible anywhere in any component without importing any special files.
So, for example in my _color.scss
file:
:root {
--color-primary-1000: hsl(234, 62%, 26%);
--color-primary-900: hsl(232, 51%, 36%);
--color-primary-800: hsl(230, 49%, 41%);
--color-primary-700: hsl(228, 45%, 45%);
--color-primary-600: hsl(227, 42%, 51%);
--color-primary-500: hsl(227, 50%, 59%);
--color-primary-400: hsl(225, 57%, 67%);
--color-primary-300: hsl(224, 67%, 76%);
--color-primary-200: hsl(221, 78%, 86%);
--color-primary-100: hsl(221, 68%, 93%);
}
and in a component in another lib:
.header-text {
color: var(--color-primary-500);
}
i have found a much easier solution to it with lerna
.
I do a lerna init
in my project root folder to generate me a lerna.json
.
Then i edit my lerna.json
to have
{
"packages": ["libs/*"],
"version": "independent",
"npmClient": "yarn",
"stream": true,
"useWorkspaces": true
}
Add a workspaces
property to my package which looks like this
"private": true,
"workspaces": [
"libs/*"
],
And finally, lerna bootstrap
.
This allows me to import from my theme doing
@import '~@workspace/theme/styles/abstracts/variables';
The trick is lerna bootstrap
command, which creates a symlink in my root node_modules
folder. However, I haven't gotten intensense to work with it.
Wanting to do: https://material.angular.io/guide/theming-your-components
ng g lib layout
ng g c header --project=layout
ng g c footer --project=layout
Creates a tree like:
libs
/layout
/src
/lib
/header
header.component.html
header.component.scss
header.component.spec.ts
header.component.ts
header.theme.scss
/footer
footer.component.html
footer.component.scss
footer.component.spec.ts
footer.component.ts
footer.theme.scss
Now, you can create a file next to index.ts for that lib /libs/layout/src/theming.scss:
@import './lib/header/header.theme.scss';
@import './lib/footer/footer.theme.scss';
and inside your app's styles.scss:
@import 'libs/layout/src/theming';
@include header-theme($theme) { ... }
@include footer-theme($theme) { ... }
It seems to work well IMO. You're whitelisting/exporting only theme files so you don't start duplicating SCSS as you import.
You don't need to update stylePreprocessorOptions.includePaths
.
For sure this would be cool, but it only looks prettier:
@import '~@angular/material/theming';
@import '~@myapp/layout/theming';
How about another use case with monorepos, when you have multiple apps and a common ui components library? And those ui components need to have different colors (and possibly other style properties that differ), depending on which app consumes them.
For example:
apps/
- app1
- app2
libs/
- ui/
- dropdown/
Depending on which app consumes the dropdown, the dropdown needs to have different colors for borders, active items, hovered items, shadow etc. That's the issue I'm facing right now. How can we achieve that? (ie without taking all styles from the ui components library and making them global) since it's impossible to know at the ui component's css level what app consumes the component...
@MrCroft The way I have mine set up is that each component has its included styles in scss file and then its "changeable" values in another wrapped in a mixin/function as above. Much like
libs/
- ui/
- dropdown/
- dropdown.component.scss
- _dropdown.theme.scss
Then you just @import '~@lib/ui/dropdown/dropdown.theme'
file in your app.scss file and @include dropdown-theme($theme);
I created a theme folder in my libs... and inside the styles.scss of my app I imported the global scss...
@import '../../../libs/common-components/src/lib/theme/global.scss';
I found a way to share mixins, variables, and functions between apps and libs. I created a folder in the root styles
and then I imported what I need in any scss files just by adding @import 'styles/variables'
, for example. If you want to share a base style for your components then from there is quite easy. Let me know what do you think.
Hmm…doesn’t there have to be a path or preProcessor config somewhere to inform the builder how to resolve the implied path? When I just created a root folder and dumped styles into it, the imports all had to be relative. scss imports don’t seem to recognize “paths” in tsconfig, and adding preprocessor options in angular.json without a library all failed. If somehow it does work, it’d be interesting if you could run an AOT build on a given app and see if there are any problems.
The way I use after some Nrwl repo chat: create a library, which adds an entry to “paths” in your tsconfig, it’ll look something like ‘@myrepo/somefolder’. This lib now serves as a namespace wrapper that you can use to resolve assets in it. Dump all your scss into the lib directory of that library, then configure the preprocessor options of each project that would use that implied path. Your app builder should now be able to resolve imports in sass files by just using (assuming the file “variables.scss” is in the lib folder) @import ‘variables’;
On Jul 11, 2019, at 5:32 AM, LuisK Ruiz notifications@github.com wrote:
I found a way to share mixins, variables, and functions between apps and libs. I created a folder in the root styles and then I imported what I need in any scss files just by adding @import 'styles/variables', for example. If you want to share a base style for your components then from there is quite easy. Let me know what do you think.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nrwl/nx/issues/54?email_source=notifications&email_token=AAJIGE6HNHFDR4XJNDTBSG3P634ZPA5CNFSM4D65JNS2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZWDZPI#issuecomment-510409917, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJIGE72JYQKEHG5YH3V6ATP634ZPANCNFSM4D65JNSQ.
Folks. I'm going to close this.
We are reimplementing bazel support using the new capabilities provided by the bazel team. We are hoping to release an early beta in January.
Is there any solution from Nx team already? Thx
Any Updates here?
@vsavkin I really dislike closing a ticket for the sake of closing the ticket and saying "something will happen".
As you can already see, two comments months later than your "early January" of wanting updates to this issue.
Is there a solution and why hasn't it been linked to the what I'd consider an open ticket.
@michael-letcher there are a number of workable solutions presented in this thread
There is a ponyfill for css custom properties if you need to support IE.
@markgoho I understand there are community workarounds. But I'm after a response from the developers. As their last comment was an offical solution coming in January.
I'm already using a very close variation of your solution.
If they comeback saying what they were trying failed and to just use the workarounds here. Then so be it. But closing a ticket and not actually resolving it I think is a bad practise.
So... January (of 2021..) is here.. I got a little lost from all the possibilities, what is the recommended way according to NX itself?
@Eladigo I use this method on all new projects. Please let me know if you need assistance understanding this strategy or help getting it set up for your repo.
There should be lib support also for React apps with lerna etc without using css modules. Is this possible? Right now I am just copying the scss file?
Yo, I find out great solution, to provide lib/styles into app. You can look here in the example of nextjs https://github.com/erkobridee/nx-nextjs
@markgoho's approach seems to work pretty well. However, I think that I've run into an edge case.
Here's what we're seeing.
libs/theme/task/_comment.scss
and libs/theme/task/_task.scss
that imports comment
.angular.json
's styles
array, we have libs/theme/task/_task.scss
.ng serve client-app
, we make a change to libs/theme/task/_comment.scss
and the app reloads.libs/theme/task/_comment.scss
to CI and the production build hits the cache and quickly replays the cache result.So most everything works fine, but the Nx build cache doesn't detect this change.
It looks like I'll need to add
"implicitDependencies": {
"libs/theme/**/*.scss": ["client-app"]
},
Hello. Is there already a more elegant solution for this requirement? We would like to create a pure css library that can be imported by an angular, react and vuejs libraries/applications.
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.
Use Case
I have styles and scss variables I want to share across all my applications. I made a styles library and would like to reference it with
import "@myprojectname/mystylelib/styles"
in all applications and other libraries.Proposal
Similar to how Typescript is setup to resolve imports like
@myprojectname/mylib
, it would be nice to include:when creating apps and libs in
.angular-cli.json
. Unfortunately, these won't be namespaced with@myprojectname/...
with the current directory setup provided by Nx.A potential solution would be to change the directory structure of libs to be
libs/@myprojectname/{libraries go here}
. It would make the imports make more sense to the users and allow style focused libraries to be imported in the same manner within css, scss, and less files.If this looks good, I would gladly like to help with the implementation. Thanks again for all your hard work, Nx is awesome!