Node-sass won't work when using the --watch flag

Viewed 4670

I am having a problem when using the "--watch" or "-w" flag when running node-sass. I've installed node-sass as a devDependency and specified a script for me to run node-sass. The thing is that when I run the script without any flags everything works fine and the SCSS code is compiled, but when I add the "--watch" flag, it won't even compile the initial code, nor will it detect any file changes. I've done a lot of research and found nothing. I'll leave the scripts down below and I'll be glad to provide any other information that may help with solving this issue.

Inside package.json:

"scripts": {
    "compile:sass": "node-sass sass/main.scss css/style.css"
 }

This works fine when I run npm run compile:sass and I get this output:

natours@1.0.0 compile:sass /Users/lucabarcelos/WebstormProjects/AdvancedCSS/Natours
node-sass sass/main.scss css/style.css

Rendering Complete, saving .css file...
Wrote CSS to /Users/lucabarcelos/WebstormProjects/AdvancedCSS/Natours/css/style.css

But when I change the script to this:

"scripts": {
    "compile:sass": "node-sass sass/main.scss css/style.css -w"
}

I get this output:

natours@1.0.0 compile:sass /Users/lucabarcelos/WebstormProjects/AdvancedCSS/Natours
node-sass sass/main.scss css/style.css -w

And it keeps waiting for file changes but when I actually change something nothing happens at all.

3 Answers

I faced the exact same issue(also while doing the natours project:)), and none of the above solutions worked for me. I also tried onchange file watcher and had no luck with that either. In case someone else has the same problem with watching .scss files, I post my solution here. What finally did the trick was a combination of chokidar and node-sass(node-sass-chokidar). I followed this tutorial, which has a step-by-step guide on how to do the setup, and finally, it works! The only things I did differently was that I used the -D flag, in order to save it as devDependency, and also didn't use the -o flag because the ouput destination file already existed.

I used:

npm i node-sass-chokidar -D

then

npm i autoprefixer chokidar-cli npm-run-all postcss-cli -D

My scripts

"scripts": {
    "build-task:scss-compile": "node-sass-chokidar --source-map true sass/main.scss  css/style.css",
    "build-task:autoprefixer": "postcss css/*.css --use autoprefixer -d css",
    "sass:build": "npm-run-all -p build-task:*",
    "sass:watch": "chokidar 'sass/**/*.scss' -c 'npm run sass:build'",
    "dev": "npm-run-all -p sass:*"
  }

You can then run npm run dev or npm run sass:watch.

Here's my solution:

  1. Install gaze from npm npm install gaze -D
  2. Create a new JavaScript file and use gaze to watch the sass files for changes and execute the commands you want with exec method from child_process library that comes with nodejs.

I added a script to the scripts property in the package.json file.

"sass:compile": "node-sass [your-input-src] [your-output-dest]"

watch.js file:

const gaze = require("gaze");
const { exec } = require("child_process");

// Command to run in terminal
const COMMAND = "npm run sass:compile";

// takes the command and uses 'exec' to execute it in
// a terminal (shell)
function cmd(command) {
  exec(command, (err, stdout, stderr) => {
    if (err) {
      console.log("error: ", err);
      return;
    }
    if (stderr) {
      console.log("stderr: ", stderr);
      return;
    }
    console.log("stdout: ", stdout);
  });
}

gaze("sass/*.scss", (err, watcher) => {
  if (err) {
    console.log(err);
    return;
  }

  // Watched files
  const files = watcher.watched();
  console.log("Watching these files: ", files);
  
  // Gaze emits four events (changed, added, deleted, all)
  // listen to the ones you want
  watcher.on("changed", (filePath) => {
    console.log(filePath, "file changed.");
    cmd(COMMAND);
  });

  watcher.on("added", (filePath) => {
    console.log("File: ", filePath, "was added.");
  });

  watcher.on("deleted", (filePath) => {
    console.log(filePath, "was deleted.");
  });

  watcher.on("all", (event, filePath) => {
    console.log("All: ", filePath, " was ", event);
  });
});

Checkout the gaze library docs for more info on it. https://github.com/shama/gaze

Related