CSS modules and rollup - generating separate CSS files ("themes") with same hashes - css

I'm using CSS Modules (Sass) with rollup on a component library project, which is working well. Each component ends up with a dist folder containing a single JS bundle file, and a corresponding CSS file with the scoped CSS classes so consumers of the component don't have to worry about CSS class name conflicts. All they do is include the JS bundle and the CSS file and everything is great. Yay CSS Modules.
The problem I'm now facing is that some components really need separate "themes" - ideally, separate CSS files, one per theme. So consumers can continue as they've been doing: including the JS bundle, but now choosing which CSS file to include to pick a theme.
I'm not sure how to get this going with CSS modules & rollup, and whether this is even the sort of approach others are taking. From what I can see, rollup always handles bundling things together, whereas I want separate CSS files, all of which get their classes renamed identically during the build phase. That way, if within my JS I refer to styles.myclass, if myclass had gotten renamed to scoped-myclass by CSS modules for the original CSS file, for a second CSS file it would also get the same name.
This would keep consumption of the component extremely simple - just a matter of including a different CSS file.
Any suggestions?

Awfully late, but let me answer this 3 years on. So what I ended up doing was totally detaching the CSS generation step from rollup and relying on the Sass CLI to handle that portion of the build process. It felt a bit klutzy, but I remember it wasn't awfully hard to do and solved the problem I outlined above. I don't believe there was a plain rollup solution at the time, nor do I think there's one today.
However... in my case the whole approach was kinda mistaken. This certainly won't be everyone's scenario, but let me spell it all out because hey it may be useful and it definitely wasn't obvious to me at the time.
This was for an in-house shared component library, where each component and its corresponding CSS was a separate npm package stored in our Artifactory. When it grew, plenty of internal references popped up, e.g. multiple components would reference the Button component, and over time they'd reference different versions of the Buttons component - each of which needed its own properly scoped CSS, unique to that package-version.
So what I found was that by doing it this way - having the CSS generated as part of the npm package dist files - I had to write an additional layer for the consumer applications that would parse their node_modules/ folder for our own internal components and combine all the different CSS files, such as the multiple versions of buttons. e.g. the main application would directly import buttons v1.0.0 in its package.json file, but the Dialog component (also included in the package.json) could include buttons 2.0.0 as its own dependency. For every version of the package, there was a uniquely scoped version of the CSS - so the consuming application HAD to include every version otherwise the styling would be borked.
So all in all, it ended up being way more complex that I wanted. I thought I could make it easier & better with the separate generated themed CSS files as part of the package dist, but it didn't end up that way. If I could revisit that project today, I'd re-examine a solution used by Material UI and others which I kinda poo-poo'd at the time: automatic injection of the CSS into the page by the component JS, rather than generating standalone CSS files which required extra work by the consumer applications to gather up and add to the final webpage. Frankly, now I regard it as the "least crap". There are definite downsides to the injection approach (extra work done on every page render for everyone! Yikes!), but there's no doubt in my mind it hugely simplifies the job of the consumer applications. It's a balancing act, but in 20-20 hindsight I'd lean towards the injection approach. With that, scoping & theming is a different and much simpler problem.

If I got you right, consider looking at SCSS plugin: rollup-plugin-scss. It captures all spare .css files imported in the components, and then processes them through underlying node-sass. The catch is, it seems like you can write a custom callback function that'd handle your CSSs differently based on conditions you throw in.
Based on the example from the plugin's page:
import scss from 'rollup-plugin-scss'
...
export default {
input: 'src/index.tsx',
output: [...],
plugins: [
...
output: function (styles, styleNodes) {
// replace this with conditioned outputs as needed:
writeFileSync('bundle1.css', styles)
writeFileSync('bundle2.css', styles)
},
]
}

Related

How to use images in CSS code inside an Angular library

I've built a library that will be used by several Angular applications (multiple teams and no monorepo). This library includes a scss-theme. This theme uses two SVG-files. However, I can't get it to work. The path is always incorrect.
My theme scss:
.test::before {
content: url('/test.svg');
}
I've written a Schematic that can be used by the library consumers to store the images inside a subdirectory of the assets folder of the application (e.g. src/assets/test-path). The Schematic does work as expected.
It does work when I add the following style inside the client's scss:
#import "test-company/test-lib/theme";
.a-client-test::before {
// This is just an example and assumes that the test image is located at this path.
background-image: url('../../assets/test-path/test.svg');
}
But as soon as I remove the line above (that actually uses the image from the assets folder and is not required at all). The path won't work anymore.
I've tested the following paths inside the library: ./test.svg, ~/test.svg, /test.svg. Only the latter does work but only with additional styles like the one above (that wouldn't be used) on app side. That's something I want to avoid as maybe we provide 50 icons on the library-side and it would be tedious to add these classes only to use the assets.
Some additional information:
I've added node_modules to the predecessor options in angular.json.
All other styles are working correctly. Only the image doesn't work.
I know that I can use ccsUrl: "inline" option inside the ng-package.json. However, I think this option only works (as far as I know) on styles that are used by components. But I actually copy the theme styles over after the build process. Additionally, the number of icons that are used inline shouldn't be too big, otherwise, the bundle size will increase and is therefore not an option for me.
I also don't know what is best practice for a scenario like that. I just couldn't figure out a proper way so far. But I assume writing a Schematic that copies over files is also not the best approach. Maybe there is a better way (e.g. a way to reference assets from the library but keep in mind I have the styles inside my library and the path is, therefore, complicated to figure out for all modules).
Just to make it clear again: My library has a scss file that uses an image. That image path is clear at the built time but doesn't work when used by an app. I can copy over the images, but that only helps when those images are used by the app somewhere in the styles. Then the path /image.svg works. The image as well as the scss that makes use of it are provided by my application.
Thanks for your help!

CSS Overriding Differently Between Two Projects?

I've mostly done back-end work in the past, but I'm taking it upon myself to learn how to use Vue, and in addition to being partially color blind, design is not my strong suit. As such, I'm using a template so that I can at least have a base to start learning from.
Weirdly, however, I've noticed many times the way the CSS is loaded on my copy differs from the template, and I cannot seem to figure out why. Simply put, it seems like the SASS I've copied to a new project does not override in the same way.
My Version:
Template project, directly from GitHub:
I can get around this somewhat by finding the CSS in question and adding a "!important" to the end, though this feels like a rather hacky solution to the problem, and I'd be better off finding the real culprit, though perhaps that is the best solution.
The SASS has been directly copied from the template, so I know that nothing there is amiss. My version and the template also use the Vue-CLI that comes with Webpack, so I'm not sure if it can be some variation there, with Webpack choosing that one file cascades the other? I have all the same dependencies in my package.json file, so I know I'm not missing some crucial dependency.
I've labeled the Imgur pictures in the link I provided, but for clarification, I'd like the background to be transparent for the inspection I provided. In the template, the transparent background overrides the white, but when I run the copy of this template, the white overrides the transparent. This happens in a good handful of places I've found, so it is not just one specific part.
Hopefully this question doesn't have so many possibilities that it's impossible to answer. I just don't understand at all what could be amiss.
As you can see, the two CSS rules have the same specificity, so all things equal the rule that comes second will overwrite the first rule. In this project, there are essentially two style imports: Vuetify and the SASS files for the template (found in #/styles/index.scss).
I was able to recreate the issue by moving around the imports of these two style sheets.
In order to get the intended behaviour, you must import the styles provided by vuetify-material-dashboard after the stylesheet provided by Vuetify.
In the template project, Vuetify is imported first in main.js as import './plugins'. The vuetify-material-dashboard stylesheet, which overrides Vuetify styles, is imported in App.vue (a child of main.js).

How to start structuring your own css when not working with a framework like bootstrap/bulma/materialize

I'm starting a new angular project and it has been decided not to use a framework like bootstrap/bulma/materialize/... but write our own sassy component library.
I have done some research but to be honnest I don't realy know where to start (besides a css reset). I'm still a junior, have already worked on some features in a previous existing project. Now I have to start of the front end for new project and would like to build everything as structured and reusable as possible but I'm a little lost where to start.
What's your plan of action when you start writing your?
How do you structure your angular components library?
Have you ever seen a good tutorial about this that I should definitely check out as well?
From my point of view, it is not a simple task. But you can start from using SCSS which will give you a wide access to term reusability. And also you may need to work on flexbox/grid-layout (Not the case if you need to support old browsers like IE 11 and below) to implement a handful of styled components. By the combination of scss and 'flexbox`, I think most of the components can be created simply and reused in the way you want it to be.
I strongly recommend avoiding the usage of libraries and write our own code instead. Because the power we will have at the time is infinite. You will be amazed to have it.
But at the same time, if the project is a long-running project and your requirements are on the way, then I would suggest you to rethink about eliminating libraries like 'bootstrap, materialize. Otherwise, if the requirements change in time and you may need to use a number of libraries to achieve the functionalities you may need. (Experience is the best teacher)
On most of my projects to date I have not used a framework and written my own CSS library and would recommended it. I don't have any experience with Angular, only React. All I can share with you is my current setup.
I use gulp to compile SASS files into a main.css file and BEM methodology (You could also look at SMACSS). Each 'block' (defined by BEM) has a separate file in either Layout or Modules.
I separate my SASS files into the following folder:
Base - Used for - resets /Grids / helpers/ typography/ base (general base styles eg wrap)
Layout - Used for containers - header/footer/sidebar ect
Lib - used for mixins
Modules - used for components - form / button / alert / icon / accordion ect
Settings - color / font / responsive - used to set sass varibles to be used in all other files.
I hope that helps.

EmberJS CSS options

I'm trying to sift through all the CSS options / packages available for EmberJS and am looking for suggestions. I suppose it will help if I list what I need:
SASS syntax (variables, nesting, creating mixins, and extending)
Ability to import other CSS libraries
Pod support (although I'm not positive I'll be using this feature at the moment, but I at least want to be able to have one CSS per route/component)
Autoprefixer
Is there an all-in-one Ember package that will give me all these? Thanks!
SASS syntax (variables, nesting, creating mixins, and extending)
You should think long and hard before taking the blue SASS pill. SASS is a technology trending towards obsolescence, which was designed mainly to support some bad CSS coding practices, as well as overcome some deficiencies in earlier versions of CSS.
Variables are supported by postCSS plugins in a standard way which is compatible with the upcoming CSS variable syntax.
Nesting is an answer in search of a problem. It promotes a bad style of coding involving excessive dependency on HTML structure. Properly constructed systems of CSS classes, orthogonal to HTML, make nesting unnecessary.
With regards to mixins, I have not seen a real-life situation in which mixins or other more advanced SASS features were actually necessary. Using them, you end up learning yet another (weird) programming language, which you have to debug, and make sure all the people on your team know.
When it comes to extending, CSS experts counsel against it. Besides potential issues of performance and code size, they hide the logic of the CSS code, and require jumping back and forth from file to file to maintain and extend and debug. Everything that is accomplished with extending can be handled with properly-designed CSS classes.
SASS is slow, is bifurcated (binary version vs. Ruby version), and can give rise to strange npm installation problems. My advice is to avoid it.
There is an interesting read about SASS vs. postCSS here.
Ability to import other CSS libraries
Ability to import other CSS libraries is not a function of any other decision you make, or what package you choose. You can simply import these.
Pod support (although I'm not positive I'll be using this feature at the moment, but I at least want to be able to have one CSS per route/component)
Indeed. There is at least one new-ish Ember add-on to do this (and probably more), which IMHO is designed extremely poorly and grossly over-engineered. It follows the Ember approach of doing way too much, in an opaque way, in the name of being "helpful" (until it isn't, at which point you're screwed). This is great if you want your CSS to be littered with classes like .my-component-a34fba.
Until there is a better alternative, I'd do this manually, which is quite easy. Simply place your CSS files in the pod, and then import, from your styles/app.css or equivalent file, the CSS files from the pods you want, such as #import '../pods/thingie/; to import its index.css file. Yes, you will have to do some maintenance of these imports yourself, but how many pods do you have?
What I do to avoid a huge styles/app.css that would require constant updating is to place an index.css file in each pod and import that. From there, import a stylesheet for that directory itself and any necessary subdirectories:
/* styles/app.css */
#import '../app/pods/thingie';
/* app/pods/thingie/index.css */
#import `./style`;
#import `./subdir1';
#import `./subdir2';
Autoprefixer
You need look no further than the excellent postcss/autoprefixer.
Is there an all-in-one Ember package that will give me all these?
It would be nice if all our problems could be handled by all-in-one packages. Unfortunately, all-in-one packages are always missing two features we wanted, and we can never figure out how to add them. They always do one thing we didn't want them to do, and we can never figure how to turn it off. They import old versions of their subpackages. They break when there's an Ember upgrade. They stop being maintained. The Ember philosophy itself sadly promotes this pernicious all-in-one mentality--all my problems can be solved by yet another add-on!
You are better off understanding individual technologies, choosing simple, bounded, reliable implementations of them, and weaving them together yourself. Just my two cents.
This might be the closest thing you're looking for:
https://github.com/ebryn/ember-component-css
Which supports using pods layout, and lets you use ember-cli-sass.
To use auto-prefixing, there are plenty of sass libraries out there to help you out, like Bourbon.io, which you can install via npm. Then, it should just be matter of configuring the import paths via the sass options in the ember-cli-build.js
I recommend PostCSS. Last I checked, it doesn't work out-of-the-box with ember-component-css, but you don't need ember-component-css to namespace your styles.
You can modify Ember's Component generator / blueprint to (assuming you're using pods):
Add classNames: ['component-name-here'], to the generated component.js file.
Create a _component-name-here.css file/partial in app/styles/components (or similar), with a class .component-name-here to contain all styles in the partial.
If necessary, #import that new partial in your app.css.
Then all your Component styles will be namespaced.
To handle variables, nesting and Autoprefixer, you just need to set up PostCSS with the right plugins, e.g.:
plugins: [
{
module: require('postcss-partial-import'),
},
{
module: require('postcss-nested'),
},
{
module: require('postcss-custom-media'),
},
{
module: require('postcss-custom-properties'),
},
{
module: require('autoprefixer'),
options: { browsers: ['last 2 versions'] }
},
],
I'm using ember-cli-css-preprocess, which gives you the option to use SASS as well (alongside PostCSS), if you wish.

Using Less with Web Components

As stated by Rob Dodson, style tags are now unavoidable with Web Components. I am trying to find a way to use LESS with this new tecnhology without having to paste the compiled CSS in my HTML document everytime I change something in the LESS file . Is there anyway to achieve that?
I am using Polymer.
Thanks!
Laurent
You can make the client compile the LESS to CSS , you should definitely take a look at this :
http://lesscss.org/#client-side-usage
It is advised to compile it yourself to css in a production environment though !
Doing this client-side hardly seems like the corrent solution, especially at scale. For instance, do you really want 1000 web components in your app all including LessCSS and compiling on the client side?
Just compile server-side and include the compiled version in your html import. Apps like DocPad, make this a lot easier. For instance:
src/documents/components/my-component/my-component.css.less is your source file, and is compiled to out/components/my-component/my-component.css, which is accessible at /compoennt/my-component/my-component.css.
We use this workflow to also make use of javascript pre-processors like coffeescript, as well as post-processors like css auto prefixer, and bundlers like Browserify. See: https://stackoverflow.com/a/23050527/130638 for more info.
Simply compile your less and embed the generated CSS file via good old link tag.
I don't think that rob wanted to say that using style tags is the only way to go. You can still link to external stylesheets as you always did.
Why don´t you compile on server side using php compiler? Have a look here - http://leafo.net/lessphp/ -
To let you know, i´m using this compiler on my projects, on the server side without any kind of problems!!!!!!! :) IMO, it´s better to have the compilation work on the server side. I´m not totally 100% sure, but i think IE8 don´t recognize text/less
The way I have done this before is have individual .less or .scss file for each component and have it compile into the individual .css file which is then called into the respective component file. and finally vulcanize everything into a single file.
Incase you want to use a single CSS file, then use //deep// combinator or ::shadow pseudo elements in the CSS.
If you able to create the custom elements without using ShadowDOM then you can simply have all your less merge into a single CSS.
Honestly speaking I was unable to create a wc without shadowDOM in polymer. There is a long conversation on github on enabling / disabling and hacking a way to create a wc without shadowDOM here https://github.com/Polymer/polymer/issues/222
One solution would be to have the preprocessor translate .less files into .css and then linking them inside Polymer components, like explained in the official documentation: https://www.polymer-project.org/1.0/docs/devguide/styling#external-stylesheets
Unfortunately this is deprecated. So the other way to go could be to have another step that wraps the preprocessor-generated css files with a dom-module: this way you can follow the Polymer way including the style module inside your components, or using the css file compiled from less if you do things outside Polymer components.
I'm using Gulp for my build process and I found this module very useful:
https://github.com/MaKleSoft/gulp-style-modules
It creates, for every .less file I have in my sources, an .html file with a dom-module wrapped around it, ready to be included in the components' styles.

Resources