Search code examples
cssnpmsassgulp

NPM Gulp > retrieve SCSS import filepaths


So currently in my gulp setup I have many several CSS files that are produced - a general 'core' one, and then template specific stylesheets.

Rather than re-compiling all stylesheets on each change, it only compiles the required ones - but this has led to complex "watch" paths, covering many files which just reflects whats in the primary SCSS files for each template (which consist of @use/@import statements).

Then it occured to me, wouldn't it be nice that rather than writing out all the watch filepaths, that I simply 'crawl' the SCSS file and grab all the filepaths for any @use/@import statements recursively.

So as an example, lets say I have this "blog.scss" file:


    // Variables 
    @import 'variables';
    
    // Tools
    @import './tools';
    
    // Parts
    @import './core/base';
    @import './templates/blog';

Is it possible to grab all of the filepaths for its @import statements, so e.g.:

'local-dev/styles/variables.scss'
'local-dev/styles/tools.scss'
'local-dev/styles/core/base.scss'
'local-dev/styles/templates/blog.scss'

I've considered simply retrieving the file as a string, and using some regex - but that wouldn't take file extensions into consideration (.scss/.css/_partials.scss) and would likely have other issues.

Any ideas?

Thanks in advance.


Solution

  • What you trying to achieve called incremental build system, it means - we compile only those files, that were changed, and don't touch anything else.

    If you wanna dig into details, I really recommend this article -> Incremental SASS Builds with Gulp by Sarthak Batra.


    If you just wanna ready2go solution, here it is:

    1. All code examples are for gulpJS v4, so make sure it's the version you currently have by running console command in your project directory -> gulp -v

    2. Aside from gulpV4 you also need to install gulp-dependents plugin. You can do it by running console command: npm i --save-dev gulp-dependents in your project folder.

    3. In your gulpfile.js you need to add new import statement. For v4 it would look something like: const dependents = require("gulp-dependents")

    4. Lastly, you need to update your gulp styles function, and make sure it would only compile changed files.

    function styles(callMeBack) {
      return gulp
        .src(paths.styles.src, { since: gulp.lastRun(styles) })
        .pipe(dependents())
        .pipe(scss())
        .pipe(gulp.dest(paths.styles.dest))
        .pipe(browserSync.stream())
        .on("end", callMeBack)
    }
    
    • path.styles.src -> path to your styles folder, in my case it looks like "app/static/styles/**/*.scss";
    • since: gulp.lastRun(styles) -> gulpV4 API call, that checks if current blob is the same as on the last function run, and takes into pipeline only changed files;
    • .dependents() -> runs a deep search with regExp and finds files dependent on one current one in pipeline. It's exactly what you were trying to describe in original question;
    • and I think you familiar with what .scss() and gulp.dest are doing. :)
    • End result -> only the styles that were changed will be compiled;
    1. If you have multiple styles functions, I'd recommend to create new one (so you would not break your previous work routine), and test how this new one feels.

    P.S Because we use since.lastRun -> it will work correctly only after first run. So it's like compile everything > wait for changes > check changes > compile only edited ones

    P.P.S If you have any questions, I would be happy to answer them.