It would be nice if, for version 5, Bootstrap could be āmodularisedā.
One of the criticisms of Bootstrap is that is contains everything but the kitchen sink; this would mitigate that criticism and allow discerning and conscientious developers to be able to pull in only the components they needed and keep their bundle sizes low.
The way I can envisage this working is, the individual components split into separate NPM packages, i.e. @bootstrap/alert
, @bootstrap/badge
, @bootstrap/breadcrumb
, etc. Variables and mixins could be put in a @bootstrap/core
or similar package.
The existing bootstrap
package could function exactly as it does now (pulls everything in and gives you a Bootstrap build with every component), but developers (like me) could craft bundles with just the components we need, i.e.
@import "my-app-custom-variables";
@import "~@bootstrap/navbar";
@import "~@bootstrap/card";
Based on the above, it looks like each @bootstrap/*
package would need to add the @bootstrap/core
(or whatever itās named) package as a dependency.
Of course, developers wanting to get something up and running quickly can still do the same as they have done:
@import "~bootstrap/scss/bootstrap";
I remember CSS wizard Harry Roberts did something similar for his āInuitā CSS framework where the framework was broken into individual components that could be installed on an ad hoc basis. It would be nice if Bootstrap followed a similar approach so unnecessary components can be excluded from bundles and builds.
The issue with this is that for example the cards depend on the variables, functions, mixins and reboot. If we're going to use the @import
approach you mentioned above we'll probably end up with including the variables & mixins too much.
We might have a look at using the $enable-
variables more. For example we now have a $enable-grid-classes
variable to switch on/off the grid classes.
The issue with this is that for example the cards depend on the variables, functions, mixins and reboot.
@MartijnCuppens I foresaw that. Could each individual component not @import
a ābaseā component before its styles? Or will Sass literally pull in the same styles for every component that imports the base component?
For example:
// components/card.scss
@import "~@bootstrap/base";
// Card styles...
```scss
// components/carousel.scss
@import "~@bootstrap/base";
// Carousel styles...
```scss
@import "my-apps-custom-variables";
// Will this approach pull in the base component multiple times? Or just once?
@import "~@bootstrap/components/card";
@import "~@bootstrap/components/carousel";
If the individual components approach isnāt feasible and it _would_ import the base styles multiple times, then maybe offer an $enabled-components
list or something? By default, every componentās included, but can be overridden by developers to specify only the components they need:
// Enable only the card and carousel components on top of base styles
$enabled-components: (
"card",
"carousel"
);
Each component could then check if itās included in the $enabled-components
list.
Or will Sass literally pull in the same styles for every component that imports the base component?
Yup, you can follow the discussion about a more modular approach here: https://github.com/sass/sass/issues/1094
Each component could then check if itās included in the $enabled-components list.
I haven't double-checked this yet, but this doesn't seem to be supported either:
https://github.com/sass/sass/issues/451
I haven't double-checked this yet, but this doesn't seem to be supported either:
sass/sass#451
@MartijnCuppens I was more thinking that a componentās body could be wrapped in the $if
statement?
I know this is about the idea and not a specific direction, but one thing to not is that there are definitely tools out there for publishing to multiple packages. We did this for Primer and have since opted to go back to the mono-package approach for simplicityās sake, for both maintainers and developers.
I would love to maintain the simplicity of a single mono repo package with the best customization options.
I would love to maintain the simplicity of a single mono repo package with the best customization options.
Definitely.
@MartijnCuppens I was more thinking that a componentās body could be wrapped in the
$if
statement?
This would indent all our scss. Not really a fan of that, it would also make cherry picking changes from master
to v4
imposible.
@mdo @MartijnCuppens Do you chaps have any suggestions, then? It would be nice if, as a developer, I could only import the component styles that I need in my applications, rather than Bootstrap being āall or nothingā.
@martinbean you can have a look at our getting started section which describes how to partially include Bootstrap.
@MartijnCuppens Thatās what Iām currently doing, but itās a bit of a pain to copy-and-paste @import
statements. I was just exploring the possibility of a more friendlier approach.
I feel your pain, I don't really like it either but I'm afraid we're limited by the possibilities Sass provides right now.
What about an imperfect solution: divide .scss files into "something else depends on this" and "nothing else depends on this", and provide a "base.scss"
which imports all of the former.
To be clear, such a division wouldn't just be core files (e.g. "bootstrap/functions"
) vs components. It would also include e.g. "bootstrap/buttons"
, assuming that "bootstrap/button-group"
depends on it. (I don't know if it actually does, which is a large part of the difficulty, currently.)
This way the user can import "base.scss"
, and then have have a coarse-grain way of tuning the rest of the output file size.
Update: Sass is going to move to a module system, which could solve this issue:
http://sass.logdown.com/posts/502818-request-for-comments-module-system-proposal
@MartijnCuppens It seems the Sass team even used Bootstrap as an example of how it could be used š
https://github.com/sass/sass/blob/master/accepted/module-system.md
There are approaches that would work without needing to migrate to the sass module system.
Specifically instead of using partials for components wrap them in a mixin:
@mixin CreateButton() {
...button styles as normal
}
then they can be conditionally included:
// bootstrap.scss
@if $enable_button {
@include CreateButton();
}
We do something similar in react-widgets, accepting a list of widgets you want included, then topographically sort them passed on dependencies and include them: https://github.com/jquense/react-widgets/blob/react-widgets%405.0.0-beta.20/packages/react-widgets/src/scss/react-widgets.scss
Most helpful comment
Update: Sass is going to move to a module system, which could solve this issue:
http://sass.logdown.com/posts/502818-request-for-comments-module-system-proposal