Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Smarter Sass/Less Builds with Webpack (MelbJS Edition)

Smarter Sass/Less Builds with Webpack (MelbJS Edition)

A talk I gave at MelbJS on 13/5/2015

Ben Smithett

May 13, 2015
Tweet

More Decks by Ben Smithett

Other Decks in Technology

Transcript

  1. SMARTER CSS BUILDS WITH WEBPACK
    @bensmithett

    View Slide

  2. SMARTER CSS BUILDS WITH WEBPACK
    @bensmithett
    Sass/Less

    View Slide

  3. Nobody writes plain old CSS in one big file any more

    View Slide

  4. Use a preprocessor!
    Modularize all the things!

    View Slide

  5. config/
    colors.scss
    media_queries.scss
    mixins/
    breakpoint.scss
    modules/
    btn.scss
    dropdown.scss
    header.scss

    View Slide

  6. How do you turn that into a single
    bundle.css
    to send down to users?

    View Slide

  7. Sass or Less @import ?

    View Slide

  8. @import "config/colors";
    @import "config/media_queries";
    @import "mixins/breakpoint";
    @import "modules/btn";
    @import "modules/dropdown";
    @import "modules/header";

    View Slide

  9. Shared global scope

    View Slide

  10. $red: #f00
    @import "config/colors";
    @import "config/media_queries";
    @import "mixins/breakpoint";
    @import "modules/btn";
    @import "modules/dropdown";
    @import "modules/header";

    View Slide

  11. background: $red
    @import "config/colors";
    @import "config/media_queries";
    @import "mixins/breakpoint";
    @import "modules/btn";
    @import "modules/dropdown";
    @import "modules/header";
    $red: #f00

    View Slide

  12. Does that remind you of anything?

    View Slide






  13. View Slide






  14. defines $

    View Slide






  15. defines $
    uses $

    View Slide






  16. window.$
    window.Backbone
    window._
    window.MyApp
    $.fn.outrageousSliderPlugin

    View Slide

  17. We don’t do that in JS any more.
    Instead we write small, self-contained modules that import their
    dependencies into their own local scope.

    View Slide

  18. components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss

    View Slide

  19. import React from “react”;
    import Dropdown from “./dropdown”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });
    components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss

    View Slide

  20. import React from “react”;
    import Dropdown from “./dropdown”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });
    components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss

    View Slide

  21. import React from “react”;
    import Dropdown from “./dropdown”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });
    components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss

    View Slide

  22. We can do that with Sass & Less too, if…
    - we execute (compile to CSS) each file its own scope

    - we explicitly import each file’s dependencies

    View Slide

  23. Use @import to import the Sass/Less dependencies

    that each module uses
    (e.g. variables, mixins & functions)

    View Slide

  24. // modules/header.scss
    @import "config/colors";
    .header {
    background: $red;
    }

    View Slide

  25. Don’t use @import to concatenate

    View Slide

  26. @import "config/colors";
    @import "config/media_queries";
    @import "mixins/breakpoint";
    @import "modules/btn";
    @import "modules/dropdown";
    @import "modules/header";
    Noooope

    View Slide

  27. gulp.task('styles', function () {
    gulp.src('styles/modules/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('./tmp'))
    .pipe(concat('bundle.css'))
    .pipe(gulp.dest('./build'));
    });
    Yay!

    View Slide

  28. Every Sass/Less file runs in its own private scope!
    Impossible to clobber variables across files
    Doesn’t depend on a specific, fragile order

    View Slide

  29. components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss
    import React from “react”;
    import Dropdown from “./dropdown”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });

    View Slide

  30. One of this component’s dependencies is in your head,

    not explicit in code!

    View Slide

  31. UI components have non-JS dependencies
    CSS, fonts, images, etc…

    View Slide

  32. View Slide

  33. Webpack supercharges require()

    (or import if you’re writing ES6)

    to let you require all of a component’s dependencies
    Including the non-JS ones!

    View Slide

  34. components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss
    import React from “react”;
    import Dropdown from “./dropdown”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });

    View Slide

  35. components/
    dropdown.js
    header.js
    css/
    btn.scss
    dropdown.scss
    header.scss
    import React from “react”;
    import Dropdown from “./dropdown”;
    import “css/header”;
    export default React.createClass({
    render () {
    return (



    );
    }
    });

    View Slide

  36. Automatically build a single bundle.css

    based on explicitly declared dependencies

    in components your app actually uses
    $ webpack

    View Slide

  37. STOP! DEMOTIME!

    View Slide

  38. THIS IS AWESOME!
    • No manually maintained CSS manifest
    • bundle.css only contains CSS that your app actually uses
    • Great for building multiple apps from a common set of UI components
    • Or multiple entrypoints into one app - if user visits /profile, don’t
    send down CSS for components specific to /timeline or 

    /settings yet

    View Slide

  39. • http://bensmithett.com/smarter-css-builds-with-webpack/
    • https://github.com/bensmithett/webpack-css-example
    • https://github.com/webpack/css-loader/blob/master/
    README.md#local-scope
    • https://github.com/markdalgleish/postcss-local-scope

    View Slide

  40. OUR TEAM IS HIRING!
    envato.com/careers or @bensmithett
    ✨ Building a very cool brand new product - help us shape it! ✨
    ✨ React/Flux/Immutable, Webpack, Babel, Sass & Rails ✨
    ✨ Tiny, independent, remote-friendly team inside Envato ✨
    (don’t worry, the Rails asset pipeline is a distant memory )

    View Slide

  41. THANKS!
    @bensmithett

    View Slide