DEV Community

loading...

Discussion on: Processing sass with 11ty

koitaki profile image
Chris Adams

Mathieu,

Here's a mysterious issue I encountered, but which somehow resolved itself.

I began getting a weird 'EISDIR, open' error.
ie. it seemed to be trying to open a directory, which it thought was non-existant but which did indeed exist, seemingly with adequate permissions.

[Error: EISDIR: illegal operation on a directory, open 'C:\Users\Owner\Projects\football\website\src\assets\css']

Also, it was pointing to the old, source, path that I originally had.

So I checked my paths to make sure I was now pointing to the output CSS folder under _site. Yup, that was definitely the case.

eleventy.js

const sass = require('./utils/sass-process');
sass('./src/assets/sass/main.scss', './_site/assets/css/main.css');

I restarted eleventy process a few times to see if that would get the right path to be read, and clear the error. But the problem persisted.

So, here's what 'seemed' to fix it. I added a console.log statement to the sass-process.js file in order to check the path of the CSS file being read in. No idea what it did, but to my neophyte eyes the change 'seemed to refresh' some cache, and thereafter the correct path was picked up.

config/sass-process.js

  : code, code, code
  :
    //Watch for changes to scssPath directory...
    fs.watch(path.dirname(scssPath), () => {
        console.log(`Watching ${path.dirname(scssPath)}...`);
        //Encapsulate rendered css from scssPath into watchResult variable
        const watchResult = sass.renderSync({file: scssPath});
        console.log("FILE TO WRITE TO: " + cssPath)  // <== ADDED THIS
  :
  : rest of code

Posted for what its worth...in case anyone else has a better explanation, or encounters this issue and it helps them solve it.

Cheers again!

Thread Thread
mathieuhuot profile image
Mathieu Huot Author • Edited

Hi Chris, happy to hear that you solve the problem! When I have time, I like to investigate on errors I'm getting even when I fix things. It helps me to refine my understanding. I had never heard of such error so I search a bit and I found this thread on Stack Overflow. Here's the essential part:

EISDIR stands for "Error, Is Directory". This means that NPM is trying to do something to a file but it is a directory.

In your case, It could have been a cache problem and by updating sass-process.js you invalidate the cache. Hard to say, for what I know. I think it's unlikely that logging to the console would fix this error directly, more as a side effect, I would say.

Thanks for sharing!

Have a good day! 🤗

Thread Thread
koitaki profile image
Chris Adams

I take your point Mathieu, that it worked after a console.log was a bit wierd.

Here's another FWIW post, in case someone of my level comes along with the same issue.

I host on Netlify, and I noticed my site no longer deployed. Eventually guessed that Netlify being a static site host, the sass-process call for modifying files might be the problem.

Seemed a simple fix: creating a local ELEVENTY_ENV variable + one on Netlify, and adding an environments toggle. Eg.

eleventy.js

const env = process.env.ELEVENTY_ENV;
  if (env == "development") {
    sass('./src/assets/sass/main.scss', './_site/assets/css/main.css');
  }

That worked, so all good again 🙂

Thread Thread
mathieuhuot profile image
Mathieu Huot Author

Hi Chris, I happen to host my sites on Netlify too! I think I know why you encountered problems with deployment. The sass-process script contains a watch method which is a never ending process (it will watch for changes in target files forever or until you shutdown the script or it encounters an error). Netlify deploy process will build your site with the provided command exactly like you would on your local machine. If your build process never ends (which is the case if it includes a script with a watch method) it will timeout Netlify deploy process. So you'r right, the watch method contained in the sass-process script has to be remove from production (and kept for development only 🙂). Here's how I do it on my project:

sass-process.js

[...]
//If cssPath directory doesn't exist or ELEVENTY_ENV environment variable is set to prod... 
if(!fs.existsSync(path.dirname(cssPath)) || process.env.ELEVENTY_ENV === 'prod') {
    //Create cssPath directory recursively
    fs.mkdir(path.dirname(cssPath), {recursive: true})
    //The .then method will return a promise with the result 
    .then(() => processSass(scssPath, cssPath))
    //Then write result css string to cssPath file
    .then(result => fs.writeFile(cssPath, result.css.toString()))
    .catch(error => console.error(error));
}
//In development environment (default)
if(process.env.ELEVENTY_ENV === 'dev') {
    //Watch for changes to scssPath directory...
    fs.watch(path.dirname(scssPath), () => {
        //Return css as buffer from scssPath file...
        processSass(scssPath, cssPath)
        //Then turn css buffer to string and write result to cssPath file
        .then(result => fs.writeFile(cssPath, result.css.toString()))
        .catch(error => console.error(error));
    });
}

So here, if ELEVENTY_ENV is set to 'production' (or 'prod' in my case) the script will process sass and write the result to the target file, but it will skip the watch part! In this case, I would still be able to run the script in .eleventy.js without any conditions and it wouldn't prevent Netlify deploy from completing (with the minor difference that it would process sass on deploy). I'm only guessing here, but the fact that not calling your sass() function at all during deployment still produced a 'styled' site means that you probably include your output directory (_site) in your git repo or the result would be a site with no css. Anyhow, it's working for you and your project and really that's the only thing that matters in the end. Here's a small open source project I'm working on right now. It contains the sass-process script (in the config folder) and it's hosted on Netlify.