Importing Sass through npm

后端 未结 5 1354
闹比i
闹比i 2020-12-13 17:18

Currently in our Sass files we have something like the following:

@import \"../../node_modules/some-module/sass/app\";

This is bad, because

相关标签:
5条回答
  • 2020-12-13 18:07

    You can use a Sass importer function to do so. Cf. https://github.com/sass/node-sass#importer--v200.

    The following example illustrates node-sass@3.0.0 with node@0.12.2:

    Install the bower dependency:

    $ bower install sass-mq
    $ npm install sass/node-sass#3.0.0-pre
    

    The Sass file:

    @import 'sass-mq/mq';
    
    body {
      @include mq($from: mobile) {
        color: red;
      }
      @include mq($until: tablet) {
        color: blue;
      }
    }
    

    The node renderer file:

    'use strict';
    
    var sass = require('node-sass');
    var path = require('path');
    var fs = require('fs');
    
    var options = {
      file: './sample.scss',
      importer: function bowerModule(url, file, done){
        var bowerComponent = url.split(path.sep)[0];
    
        if (bowerComponent !== url) {
          fs.access(path.join(__dirname, 'bower_components', bowerComponent), fs.R_OK, function(err){
            if (err) {
              return done({ file: url });
            }
    
            var newUrl = path.join(__dirname, 'bower_components', url);
    
            done({ file: newUrl });
          })
        }
        else {
          done({ file: url });
        }
      }
    };
    
    sass.render(options, function(err, result){
      if (err) {
        console.error(err);
        return;
      }
    
      console.log(result.css.toString());
    });
    

    This one is simple and not recursive. The require.resolve function could help to deal with the tree – or wait until npm@3.0.0 to benefit from the flat dependency tree.

    0 讨论(0)
  • 2020-12-13 18:11

    As Oncle Tom mentioned, the new version of Sass has this new importer option, where every "import" you do on your Sass file will go first through this method. That means that you can then modify the actual url of this method.

    I've used require.resolve to locate the actual module entry file.
    Have a look at my gulp task and see if it helps you:

    'use strict';
    
    var path       = require('path'),
        gulp       = require('gulp'),
        sass       = require('gulp-sass');
    
    var aliases = {};
    
    /**
     * Will look for .scss|sass files inside the node_modules folder
     */
    function npmModule(url, file, done) {
      // check if the path was already found and cached
      if(aliases[url]) {
        return done({ file:aliases[url] });
      }
    
      // look for modules installed through npm
      try {
        var newPath = path.relative('./css', require.resolve(url));
        aliases[url] = newPath; // cache this request
        return done({ file:newPath });
      } catch(e) {
        // if your module could not be found, just return the original url
        aliases[url] = url;
        return done({ file:url });
      }
    }
    
    gulp.task("style", function() {
      return gulp.src('./css/app.scss')
        .pipe(sass({ importer:npmModule }))
        .pipe(gulp.dest('./css'));
    });
    

    Now let's say you installed inuit-normalize using node. You can simply "require" it on your Sass file:

    @import "inuit-normalize";
    

    I hope that helps you and others. Because adding relative paths is always a pain in the ass :)

    0 讨论(0)
  • 2020-12-13 18:16

    If you are looking for a handy answer in 2017 and are using Webpack, this was the easiest I found.

    Suppose your module path is like:

    node_modules/some-module/sass/app
    

    Then in your main scss file you can use:

    @import "~some-module/sass/app";
    

    Tilde operator shall resolve any import as a module.

    0 讨论(0)
  • 2020-12-13 18:17

    I made the sass-npm module specifically for this.

    npm install sass-npm
    

    In your SASS:

    // Since node_modules/npm-module-name/style.scss exists, this will be imported.
    @import "npm-module-name";
    
    // Since just-a-sass-file isn't an installed npm module, it will be imported as a regular SCSS file.
    @import "just-a-sass-file";
    

    I normally use gulp-sass (which has the same 'importer' option as regular SASS)

    var gulp = require('gulp'),
        sass = require('gulp-sass'),
        sassNpm = require('sass-npm')();
    

    Then, in your .pipe(sass()), add the importer as an option:

    .pipe(sass({
        paths: ['public/scss'],
        importer: sassNpm.importer,
    }))
    
    0 讨论(0)
  • 2020-12-13 18:23

    You can add another includePaths to your render options.

    Plain example

    Snippet based on example from Oncle Tom.

    var options = {
      file: './sample.scss',
      includePaths: [
        path.join(__dirname, 'bower_components'), // bower
        path.join(__dirname, 'node_modules') // npm
      ]
    };
    
    sass.render(options, function(err, result){
      console.log(result.css.toString());
    });

    That should do. You can include the files from package using @import "my-cool-package/super-grid

    Webpack and scss-loader example

    {
      test: /\.scss$/, 
      loader: 'style!css!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true&includePaths[]=./node_modules' 
    },

    Notice the last argument, includePaths has to be array. Keep in mind to use right format

    0 讨论(0)
提交回复
热议问题