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

D8de178c08fe406eceeba711709ed3da?s=128

Ben Smithett

May 13, 2015
Tweet

Transcript

  1. SMARTER CSS BUILDS WITH WEBPACK @bensmithett

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

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

    more
  4. Use a preprocessor! Modularize all the things!

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

  6. How do you turn that into a single bundle.css to

    send down to users?
  7. Sass or Less @import ?

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

    @import "modules/header";
  9. Shared global scope

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

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

    @import "modules/dropdown"; @import "modules/header"; $red: #f00
  12. Does that remind you of anything?

  13. <script src="jquery.js"></script> <script src="outrageous_slider_plugin.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script> <script src="my_app.js"></script>

  14. <script src="jquery.js"></script> <script src="outrageous_slider_plugin.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script> <script src="my_app.js"></script>

    defines $
  15. <script src="jquery.js"></script> <script src="outrageous_slider_plugin.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script> <script src="my_app.js"></script>

    defines $ uses $
  16. <script src="jquery.js"></script> <script src="outrageous_slider_plugin.js"></script> <script src="underscore.js"></script> <script src="backbone.js"></script> <script src="my_app.js"></script>

    window.$ window.Backbone window._ window.MyApp $.fn.outrageousSliderPlugin
  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.
  18. components/ dropdown.js header.js css/ btn.scss dropdown.scss header.scss

  19. import React from “react”; import Dropdown from “./dropdown”; export default

    React.createClass({ render () { return ( <div className=“header”> <Dropdown /> </div> ); } }); components/ dropdown.js header.js css/ btn.scss dropdown.scss header.scss
  20. import React from “react”; import Dropdown from “./dropdown”; export default

    React.createClass({ render () { return ( <div className=“header”> <Dropdown /> </div> ); } }); components/ dropdown.js header.js css/ btn.scss dropdown.scss header.scss
  21. import React from “react”; import Dropdown from “./dropdown”; export default

    React.createClass({ render () { return ( <div className=“header”> <Dropdown /> </div> ); } }); components/ dropdown.js header.js css/ btn.scss dropdown.scss header.scss
  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
  23. Use @import to import the Sass/Less dependencies
 that each module

    uses (e.g. variables, mixins & functions)
  24. // modules/header.scss @import "config/colors"; .header { background: $red; }

  25. Don’t use @import to concatenate

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

    @import "modules/header"; Noooope
  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!
  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
  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 ( <div className=“header”> <Dropdown /> </div> ); } });
  30. One of this component’s dependencies is in your head,
 not

    explicit in code!
  31. UI components have non-JS dependencies CSS, fonts, images, etc…

  32. None
  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!
  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 ( <div className=“header”> <Dropdown /> </div> ); } });
  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 ( <div className=“header”> <Dropdown /> </div> ); } });
  36. Automatically build a single bundle.css
 based on explicitly declared dependencies


    in components your app actually uses $ webpack
  37. STOP! DEMOTIME!

  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
  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

  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 )
  41. THANKS! @bensmithett