Our layout.js file requires main.css:

... lines 1 - 6
require('../css/main.css');
... lines 8 - 12

That's cool... I guess... if you like using boring old CSS. But I want to be more Hipster, so let's use Sass instead. Well, I could use Stylus to be super hipster... and Encore does support that, but let's use something a bit more familiar.

To start, rename the file to main.scss. Now, we can use a fancier syntax for these pseudo-selectors:

... lines 1 - 16
.btn-login {
... lines 18 - 26
&:hover,&:focus {
color: #fff;
background-color: #53A3CD;
border-color: #53A3CD;
}
}
... lines 33 - 77

OooooOoOooOooo.

Obviously, the build is failing because, in layout.js, that file path is wrong! Change it to main.scss:

... lines 1 - 6
require('../css/main.scss');
... lines 8 - 12

So... does it already work?

Activating Optional Features

No! On the watch tab of our terminal, it failed when loading main.scss. Out-of-the-box, Encore cannot process Sass files. But, it tells you how to fix this! We just need to enable it inside our config & install some extra packages. Remember: Encore is full of features. But to stay light, it doesn't enable everything automatically. Instead, you are in control: enable what you need, and Encore will tell you what to do. It's kinda cool!

Go back to webpack.config.js and add .enableSassLoader():

... lines 1 - 3
Encore
... lines 5 - 23
.enableSassLoader()
;
... lines 26 - 29

Then, back on your terminal, copy the yarn add line, stop Encore with Ctrl+C, and paste!

yarn add sass-loader node-sass --dev

Let it do its thing, then... restart Encore!

yarn run encore dev --watch

No errors! To prove it works, move over to your browser and... refresh! It still looks great! Well, most importantly, on the login page, when we hover of the button, it does have that styling.

Encore Versus Webpack Concepts

There's one thing I want you to notice: the name of this method: enableSassLoader():

... lines 1 - 3
Encore
... lines 5 - 23
.enableSassLoader()
;
... lines 26 - 29

"Loader" is a Webpack concept. Encore tries to make Webpack as easy as possible, but it reuses Webpack's language and terms whenever possible. And that's important! If you ever need to do something custom with Webpack, it's usually pretty easy to figure out how that fits into Encore.

Also, we're requiring bootstrap.css right now:

... lines 1 - 4
require('bootstrap/dist/css/bootstrap.css');
... lines 6 - 12

But, with Sass support, you could instead import Bootstrap's Sass files directly. The advantage is that you can override Bootstrap's Sass variables and take control of colors, sizes and other stuff. To do that with Bootstrap 3, you'll need the bootstrap-sass package. For Bootstrap 4, the Sass files are included in the main package.

Sourcemaps!

Let's fix one more problem quickly: sourcemaps! If you click on a row, we have some console.log() debugging code. But, where does that code come from? Well, if you click on the rep_log.js link, apparently it's coming from line 197. But, that's a lie! Well, sort of. This is the built rep_log.js file, not the source file.

And this highlights a classic problem: when you build many files into one file, debugging gets harder because error messages and other info don't point to the real line number or the original filename.

Let's fix that! Back in webpack.config.js, add .enableSourceMaps() with an argument: !Encore.isProduction():

... lines 1 - 3
Encore
... lines 5 - 24
.enableSourceMaps(!Encore.isProduction())
;
... lines 27 - 30

This enables extra debugging info - called sourcemaps - whenever we are creating a development build.

Because we just updated the Webpack config, restart Encore:

yarn run encore dev --watch

Thanks to this, all of our JavaScript and CSS files now have some extra content at the bottom that hints to our browser where the source content came from. This time, when I click a row, in the console, awesome! It's coming from RepLogApp.js line 104. That is the real spot.

Oh, by the way: if you don't enable sourcemaps, you may still see some sourcemap info at the bottom of your CSS files during development. That's just an internal quirk - it won't be there on production.

Leave a comment!

  • 2018-09-18 weaverryan

    Haha, I don't think we talked about it, but it's a nice feature ;). Try enablePostCssLoader(). The error message will guide you through the rest. This biggest reason this is usually used is with autoprefixer, so you can get vendor prefixes, etc.

    Cheers!

  • 2018-09-17 kribo

    OMG nooooo what's a postcss oboy did I miss something in your tut

  • 2018-09-17 weaverryan

    Hey kribo!

    Ah, cool! It's skeleton for Encore - I love it! If you add a postcss.config.js file, you could also enable the postCss loader, which i really nice :).

    Cheers!

  • 2018-09-16 kribo

    Aha took what I learn't here and built an automated workflow using webpack-encore.
    The project is called QuickStart_basic, with the intension to create different versions for different usages.
    Quickstart_basic is for Html - Scss - Js projects.
    Checkout the link .. And please comment your remarks.
    https://github.com/ScorpioC...

  • 2018-05-16 Diego Aguiar

    Haha, I got you, we all seek for the best but easiest solution. What you could do is to have a few "base" templates, one for your users common sections, another one for your admin area, and so on

  • 2018-05-16 Teo

    Hi, Diego!
    You're right. I can include all assets into every page (make everything shared). Taking into account the modern internet speeds and CPU powers, that, most likely, will not have any negative impact on the end-user expirience (at least in non highload enterprise solutions with millions visitors). It's just... for me that just defeats the whole idea of assets management.

    On the one hand, I'm perfectionist. I want to have the perfect solution (the common flaw of all programmers). On the another hand, I'm a lazy man. I want to find the easiest solution. So I want to have the bare minimum of the required assets per each page, but make that as flexible and easy to manage as possible.

  • 2018-05-15 Diego Aguiar

    Hey Teo

    I'm not sure if this is the best way to do it, but it may work well for you. You can create a "main.js" file that will include all the common imports of your site, so then you can include it on your "base" template

  • 2018-05-14 Teo

    Thanks again! You did answer my question (only a .scss itself can activate the mixin).

    I wanted to know if there is an easy way to control js and scss dependencies from one place (one file). Right now to activate the dropdown feature of Foundation framework, we need to attach the export from "dropdown-menu.js" module to our global Foundation class AND add to the same page's scss:

    @include foundation-dropdown-menu;

    That maybe not much to do/keep in your head, but it can become a problem if you're not so familar with the library or there a lot of them in your project. So it's not quite easy to turn different features on/off.

    And thank you for the sass-resources-loader. It's not quite what I asked, but still very useful.

  • 2018-05-14 weaverryan

    Hey Teo!

    Well, thank you! :)

    About your question... hmmm... In short, Webpack isn't aware of able to work directly with any scss mixins (and, full disclosure, I am NOT an expert on scss mixings specifically, os apologies if I say something dumb :p). Well, to be more specific, Webpack simply knows how to load ".scss" files. So, yes, I think you will need to "import" the corresponding scss file, because only a .scss itself can activate the mixin.

    I don't know if that satisfies your answer or not :). There is this load - https://github.com/shakacod... - I'm not sure if that hits your issue, or if it's something different. It looks just like a shortcut to help not needing the "import" in multiple places.

    Cheers!

  • 2018-05-13 Teo

    Greate course! Could you help me with the following question? I want to dynamicly load some styles depending on the required feature (let's say dropdown menu requires both dropdown.js and additional dropdown styles). Is there a way in the Webpack to ask for predifined scss mixins directly from a js module? Or should I add to the every js module "import" to its corrsponding scss file, which will have only 1 line, like "@include dropdown-styles"?

  • 2018-04-04 weaverryan

    Hey Bertin van den Ham!

    Hmm. I *feel* like I've gotten this error before too, but I can't remember exactly why it happened (though, I think it was because I was upgrading Node or something somewhat significant in the background). I can't explain what happened in this case :/. You'll notice that when you add node-sass (or even if you already have node-sass in package.json, but delete node_nodules and run yarn install again), you will see node-sass compiling a C binary. Actually, I'm not too familiar with this process - I think some operating systems may have binaries available that are quickly downloaded, while other OS's need to recompile. The point is this: whatever node-sass needs to do, *should* be done right after the node-sass library is installed. In your case, that didn't happen, but I'm not sure why.

    So, I'm not sure that helps... but maybe the extra background info is useful :).

    Cheers!

  • 2018-03-30 Bertin van den Ham

    @Diego Aguiar

    I did not changed my os after running this command:
    rebuild node-sass it works again.

  • 2018-03-29 Diego Aguiar

    Hey Bertin van den Ham

    Ohh, interesting. Did you change your OS

    Cheers!

  • 2018-03-29 Bertin van den Ham

    I'm trying to install the sass-loader.
    Added the .enableSassLoader() to webpack.config.js

    After running this command:
    yarn add sass-loader node-sass --dev
    Both packages are installed


    {
    "devDependencies": {
    "@symfony/webpack-encore": "^0.19.0",
    "bootstrap": "^4.0.0",
    "copy-webpack-plugin": "^4.5.1",
    "font-awesome": "^4.7.0",
    "jquery": "^3.3.1",
    "node-sass": "^4.8.3",
    "sass-loader": "^6.0.7",
    "webpack-notifier": "^1.6.0"
    },
    "dependencies": {}
    }

    When i run the command: yarn run encore dev --watch i get the following error


    Webpack is watching the files…

    ERROR Failed to compile with 2 errors 21:47:56

    error in ./assets/css/layout.scss

    Module build failed: Error: Missing binding /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/vendor/darwin-x64-57/binding.node
    Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 8.x

    Found bindings for the following environments:
    - Linux 64-bit with Node.js 8.x

    This usually happens because your environment has changed since running `npm install`.
    Run `npm rebuild node-sass --force` to build the binding for your current environment.
    at module.exports (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/lib/binding.js:15:13)
    at Object.<anonymous> (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/lib/index.js:14:35)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/sass-loader/lib/loader.js:3:14)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:13:17)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at runLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
    at NormalModule.doBuild (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:182:3)
    at NormalModule.build (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:275:15)

    @ ./assets/css/layout.scss 4:14-201
    @ ./assets/js/layout.js

    error in ./assets/css/layout.scss

    Module build failed: ModuleBuildError: Module build failed: Error: Missing binding /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/vendor/darwin-x64-57/binding.node
    Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 8.x

    Found bindings for the following environments:
    - Linux 64-bit with Node.js 8.x

    This usually happens because your environment has changed since running `npm install`.
    Run `npm rebuild node-sass --force` to build the binding for your current environment.
    at module.exports (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/lib/binding.js:15:13)
    at Object.<anonymous> (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/node-sass/lib/index.js:14:35)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/sass-loader/lib/loader.js:3:14)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:13:17)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at runLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
    at NormalModule.doBuild (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:182:3)
    at NormalModule.build (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:275:15)
    at runLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:195:19)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:364:11
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:170:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:27:11)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:165:10)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:173:18
    at loadLoader (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/loadLoader.js:36:3)
    at iteratePitchingLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:169:2)
    at runLoaders (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/loader-runner/lib/LoaderRunner.js:362:2)
    at NormalModule.doBuild (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:182:3)
    at NormalModule.build (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModule.js:275:15)
    at Compilation.buildModule (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/Compilation.js:151:10)
    at moduleFactory.create (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/Compilation.js:454:10)
    at factory (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModuleFactory.js:243:5)
    at applyPluginsAsyncWaterfall (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModuleFactory.js:94:13)
    at /Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/tapable/lib/Tapable.js:268:11
    at NormalModuleFactory.params.normalModuleFactory.plugin (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/CompatibilityPlugin.js:52:5)
    at NormalModuleFactory.applyPluginsAsyncWaterfall (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/tapable/lib/Tapable.js:272:13)
    at resolver (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModuleFactory.js:69:10)
    at process.nextTick (/Users/bertinvandenham/Documents/Development/newwayhoogeveen/node_modules/webpack/lib/NormalModuleFactory.js:196:7)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

    How could i solve this?

    Fixed by running the following command: npm rebuild node-sass