通过 npm 导入 Sass

Importing Sass through npm

目前在我们的 Sass 文件中有如下内容:

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

这很糟糕,因为我们实际上不确定路径:可能是 ../node_modules,也可能是 ../../../../../node_modules,因为 npm 安装东西的方式。

有没有办法在 Sass 中向上搜索直到找到 node_modules?或者甚至是通过 npm 包含 Sass 的正确方法?

您可以使用 Sass importer 函数来执行此操作。比照。 https://github.com/sass/node-sass#importer--v200.

以下示例说明了 node-sass@3.0.0 和 node@0.12.2:

安装 bower 依赖项:

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

Sass 文件:

@import 'sass-mq/mq';

body {
  @include mq($from: mobile) {
    color: red;
  }
  @include mq($until: tablet) {
    color: blue;
  }
}

节点渲染器文件:

'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());
});

这个很简单,不是递归的。 require.resolve 函数可以帮助处理树——或者等到 npm@3.0.0 从平面依赖树中受益。

正如 Oncle Tom 提到的,new version of Sass has this new importer option,您对 Sass 文件所做的每个 "import" 都将首先通过此方法。这意味着您可以修改此方法的实际 url。

我已经使用 require.resolve 找到实际的模块入口文件。
看看我的 gulp 任务,看看它是否对你有帮助:

'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'));
});

现在假设您使用节点安装了 inuit-normalize。您可以简单地 "require" 它在您的 Sass 文件中:

@import "inuit-normalize";

希望对您和其他人有所帮助。因为添加相对路径总是很麻烦:)

您可以在渲染选项中添加另一个 includePaths

简单示例

基于 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());
});

应该可以。您可以使用 @import "my-cool-package/super-grid

包含包中的文件

Webpack 和 scss-loader 示例

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

注意最后一个参数,includePaths 必须是数组。请记住使用 right format

我专门为此制作了sass-npm模块。

npm install sass-npm

在你的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";

我通常使用 gulp-sass(与常规 SASS 具有相同的 'importer' 选项)

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

然后,在您的 .pipe(sass()) 中添加导入程序作为选项:

.pipe(sass({
    paths: ['public/scss'],
    importer: sassNpm.importer,
}))

如果您在 2017 年寻找方便的答案并且正在使用 Webpack,这是我发现的最简单的方法。

假设您的模块路径如下:

node_modules/some-module/sass/app

然后在你的主 scss 文件中你可以使用:

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

Tilde 运算符应将任何导入解析为模块。

对于 dart-sass 和 2022 年的命令行用户,只需使用 --load-path 选项:

$ npx sass --load-path=node_modules

重要提示: 整个 node_modules 文件夹包含这么多,只需将它设置为在手表模式下启动非常慢。你应该只设置你的包路径,例如:

$npx sass -w --load-path=node_modules/foo --load-path=node_modules/bar/scss