@extend sass makes web pack compiling so slow

Hi all,

there are other topics on this but I’ve not been able to find a satisfactory solution.

By commenting out the imports in main.scss I’ve found that my _forms.scss and _buttons.scss are adding upwards of 30seconds to the compile time when running yarn start

Both these files make use of @extend .btn which I think is causing the issue, however, its not as if there are hundreds or even tens of selectors being complied. My use of @extend seems neither excessive nor incorrect. I can narrow down the issue to any rule that extends the class .btn - I’m using bootstrap 4.

in _forms.scss I have:

.search-submit,
  button {
    @extend .btn;
    @extend .btn-secondary;

    margin-bottom: 0;
    flex-shrink: 0;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    background-color: $black;
    box-shadow: none;
    border: 1px solid $black;
  }

and in _buttons.scss I have:

.btn,
.button {
  @include skranji;

  border-radius: calculate-rem(2px);
  border: 0;
}

.button,
input[type="button"],
input[type="submit"],
.woocommerce a.button,
.woocommerce a.button.alt,
.woocommerce button.button,
.woocommerce button.button.alt,
.woocommerce button.disabled.button.alt,
.woocommerce #respond input#submit {
  @extend .btn;

  @include stripes-bottom;

  background-color: $black;
  color: $white;
  font-weight: normal;
  line-height: 1;

  &:hover {
    background-color: $black;
    color: $gray;
  }
}

Adding both of these files makes browser sync unusable as it is just so slow.

I must add that working with gulp was so much quicker and I’m not aware of anything that makes yarn any better, at least in a wordpress/sage workflow but I suppose that a discussion for another time.

How can I speed up web pack when using @extend? Thanks in advance!

1 Like

How large are your (source and compiled) stylesheets?

I’m not a Sass-wizard, but I’ve always been under the impression that using @extend will generate more code (i.e. creates more work for the computer):

:point_up: Frontend performance is what he is referring to, but still if you are generating a lot of code I would think that would have some effect on the backend.

I wonder if Stylelint could be causing the slow down too. Perhaps, try disabling it temporarily to test. I could imagine that stack selectors in your _buttons.scss creating a lot of work for it.

gulp is quicker than yarn

One correction here: Yarn isn’t a Gulp replacement. Yarn replaces npm. Yarn still does use NPM’s repository. It’s just has a lot of improvements (npm is slowly catching up). But that’s not the issue you are raising. webpack is what Sage 9 replaces gulp with. It seems like Yarn is the replacement because the command you use is yarn start, but that’s a script alias for the webpack command. As for speed, I personally haven’t found any issue with the speed. Maybe others can attest to slow speeds as well.

Thanks knowler, your explanation of yarn/npm web pack/gulp clears a few things up for me!

Back to the issue - main.css is compelling is labeled as [big] when I run yarn build - it’s 535kb. However, if I comment out my @extend rule in forms.scss and buttons.scss then complied size is 384kb which is a significant reduction. Further more I get complied times int he region of a few seconds compared to 30 when I remove the two rules @extend .btn

There are a significant selectors being produced by extending the class .btn (from bootstrap) but as woocommerce isn’t consistent with the markup of it’s buttons/input submit/a elements I don’t see a way around this without a painstaking copying of bootstraps scss.

Anyone familiar with bootstrap and extending it’s classes?

@extend can lead to over populating your CSS with selectors that you don’t even need. I’d suggest looking through dist/main.css to see the full extent of it.

1 Like

Thanks codepuncher, I was just checking main.scss when I saw your reply.

extending .btn gives about 180 lines of css in main.scss. Its a lot but not overly excessive, that majority of it is selectors for pseudo states such as :focus or :hover. I don’t see any problem with extending the class here or that it is much of an issue. Seems that web pack is very slow when using @extend though. Here are the lines generated by extending bootstraps .btn class so you can see for yourself:

/* line 7, node_modules/bootstrap/scss/_buttons.scss */

.btn,
.button,
input[type="button"],
input[type="submit"],
.woocommerce a.button,
.woocommerce button.button,
.woocommerce #respond input#submit,
.comment-form input[type="submit"],
.woocommerce-product-search button,
.woocommerce-MyAccount-content .edit {
  display: inline-block;
  font-weight: 400;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  border: 1px solid transparent;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  border-radius: 0.25rem;
  -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
  -o-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;
}

@media screen and (prefers-reduced-motion: reduce) {
  /* line 7, node_modules/bootstrap/scss/_buttons.scss */

  .btn,
  .button,
  input[type="button"],
  input[type="submit"],
  .woocommerce a.button,
  .woocommerce button.button,
  .woocommerce #respond input#submit,
  .comment-form input[type="submit"],
  .woocommerce-product-search button,
  .woocommerce-MyAccount-content .edit {
    -webkit-transition: none;
    -o-transition: none;
    transition: none;
  }
}

/* line 17, node_modules/bootstrap/scss/mixins/_hover.scss */

.btn:hover,
.button:hover,
input:hover[type="button"],
input:hover[type="submit"],
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce #respond input#submit:hover,
.woocommerce-product-search button:hover,
.woocommerce-MyAccount-content .edit:hover,
.btn:focus,
.button:focus,
input:focus[type="button"],
input:focus[type="submit"],
.woocommerce a.button:focus,
.woocommerce button.button:focus,
.woocommerce #respond input#submit:focus,
.woocommerce-product-search button:focus,
.woocommerce-MyAccount-content .edit:focus {
  text-decoration: none;
}

/* line 23, node_modules/bootstrap/scss/_buttons.scss */

.btn:focus,
.button:focus,
input:focus[type="button"],
input:focus[type="submit"],
.woocommerce a.button:focus,
.woocommerce button.button:focus,
.woocommerce #respond input#submit:focus,
.woocommerce-product-search button:focus,
.woocommerce-MyAccount-content .edit:focus,
.btn.focus,
.focus.button,
input.focus[type="button"],
input.focus[type="submit"],
.woocommerce a.focus.button,
.woocommerce button.focus.button,
.woocommerce #respond input.focus#submit,
.woocommerce-product-search button.focus,
.woocommerce-MyAccount-content .focus.edit {
  outline: 0;
  -webkit-box-shadow: 0 0 0 0.2rem rgba(82, 93, 220, 0.25);
          box-shadow: 0 0 0 0.2rem rgba(82, 93, 220, 0.25);
}

/* line 30, node_modules/bootstrap/scss/_buttons.scss */

.btn.disabled,
.disabled.button,
input.disabled[type="button"],
input.disabled[type="submit"],
.woocommerce a.disabled.button,
.woocommerce button.disabled.button,
.woocommerce #respond input.disabled#submit,
.woocommerce-product-search button.disabled,
.woocommerce-MyAccount-content .disabled.edit,
.btn:disabled,
.button:disabled,
input:disabled[type="button"],
input:disabled[type="submit"],
.woocommerce a.button:disabled,
.woocommerce button.button:disabled,
.woocommerce #respond input#submit:disabled,
.woocommerce-product-search button:disabled,
.woocommerce-MyAccount-content .edit:disabled {
  opacity: 0.65;
}

/* line 37, node_modules/bootstrap/scss/_buttons.scss */

.btn:not(:disabled):not(.disabled),
.button:not(:disabled):not(.disabled),
input:not(:disabled):not(.disabled)[type="button"],
input:not(:disabled):not(.disabled)[type="submit"],
.woocommerce #respond input#submit:not(:disabled):not(.disabled),
.woocommerce-product-search button:not(:disabled):not(.disabled),
.woocommerce-MyAccount-content .edit:not(:disabled):not(.disabled) {
  cursor: pointer;
}

/* line 52, node_modules/bootstrap/scss/_buttons.scss */

a.btn.disabled,
a.disabled.button,
.woocommerce-MyAccount-content a.disabled.edit,
fieldset:disabled a.btn,
fieldset:disabled a.button,
fieldset:disabled .woocommerce-MyAccount-content a.edit,
.woocommerce-MyAccount-content fieldset:disabled a.edit {
  pointer-events: none;
}

Instead of using @extend, you could try using the button-variant mixin that bootstrap uses to compile buttons itself. It’s not a silver bullet, but it will cut down on the cruft. If you want to keep the colors the same as the theme colors you could use the theme-color mixin as well.

Here’s how bootstrap4 builds its buttons:

And here’s the mixin itself: