css – 在使用Node编译SASS期间注入变量

前端之家收集整理的这篇文章主要介绍了css – 在使用Node编译SASS期间注入变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我正在工作的应用程序中,我必须在客户端渲染之前动态编译SASS(缓存系统即将到来,不用担心)。目前我使用 node-sass,一切都很好。

这是我到目前为止工作的。为简洁起见,删除了其他特定于项目的代码

var sass            = require('node-sass'),autoprefixer    = require('autoprefixer-core'),vars            = require('postcss-simple-vars'),postcss         = require('postcss'),function compileCSS() {
    var result = sass.renderSync({
            file: 'path/to/style.scss'
        });

    return postcss([autoprefixer]).process(result.css.toString()).css;
}

皱纹就是现在我需要从Node传递动态数据,并且像普通的SASS变量一样编译。最初我尝试使用PostCSS,因为我注意到变量注入是something it could do.不幸的是,这没有工作。 PostCSS在编译阶段开始,在这一点上惨败。

接下来,我尝试使用underscore模板尝试使用node-sass’importer()覆盖:

var result = sass.renderSync({
        file: 'path/to/style.scss',importer: function(url,prev,done) {
            var content = fs.readFileSync(partial_path),partial = _.template(content.toString());

            return {
                contents: partial({ test: 'test' })
            };
        }
    });

导致以下错误

Error: error reading values after :

显然SASS不喜欢下划线的变量语法

TL; DR

如何从我的Node应用程序中传递动态变量到SASS?

附加信息

>我的团队和我并没有完全不利地转向像Stylus这样的东西;然而,我们迄今已取得重大进展,这将是一个痛苦。

解决方法

我发现自己处于非常相似的状况。我们现在有很多现有的SASS,现在需要接受动态值/变量(作为变量)。我最初下了写临时目录/文件的路线,并且基本上创建了一个“代理入口点”,它将创建一个proxy_entry.scss和variables.scss,并引用实际的entry.scss和声明的预期SASS变量。这工作正常,并取得了预期的效果,但感觉有点过于复杂…

事实证明,有一个更简单的解决方案,由于node-sass’s options.data选项。这接受“要评估的SASS字符串”。

Type: String Default: null Special: file or data must be specified

A string to pass to libsass to render. It is recommended that you use includePaths in conjunction with this so that libsass can find files when using the @import directive.

这完全消除了编写/管理所有临时目录和文件的需要。

Visual TL; DR

解决方案归结为这样的事情

1.)像往常一样定义sassOptions

var sassOptionsDefaults = {
  includePaths: [
    'some/include/path'
  ],outputStyle:  'compressed'
};

2.)为options.data写入“动态SASS字符串”

var dataString =
  sassGenerator.sassVariables(variables) +
  sassGenerator.sassImport(scssEntry);
var sassOptions = _.assign({},sassOptionsDefaults,{
  data: dataString
});

3.)像往常一样评估SASS

var sass = require('node-sass');
sass.render(sassOptions,function (err,result) {
  return (err)
    ? handleError(err);
    : handleSuccess(result.css.toString());
});

注意:这是假设你的entry.scss导入一些将变量定义为“默认值”的变量.scss。

// variables.scss
$someColor: blue !default;
$someFontSize: 13px !default;

// entry.scss
@import 'variables';
.some-selector { 
  color: $someColor;
  font-size: $someFontSize;
}

以此作为例子

var sass = require('node-sass');

// 1.) Define sassOptions as usual
var sassOptionsDefaults = {
  includePaths: [
    'some/include/path'
  ],outputStyle:  'compressed'
};

function dynamicSass(scssEntry,variables,handleSuccess,handleError) {
  // 2.) Dynamically create "SASS variable declarations"
  // then import the "actual entry.scss file".
  // dataString is just "SASS" to be evaluated before
  // the actual entry.scss is imported.
  var dataString =
    sassGenerator.sassVariables(variables) +
    sassGenerator.sassImport(scssEntry);
  var sassOptions = _.assign({},{
    data: dataString
  });

  // 3.) render sass as usual
  sass.render(sassOptions,result) {
    return (err)
      ? handleError(err);
      : handleSuccess(result.css.toString());
  });
}

// Example usage.
dynamicSass('some/path/entry.scss',{
  'someColor': 'red','someFontSize': '18px'
},someSuccessFn,someErrorFn);

“sassGenerator”功能可能看起来像什么

function sassVariable(name,value) {
  return "$" + name + ": " + value + ";";
}

function sassVariables(variablesObj) {
  return Object.keys(variablesObj).map(function (name) {
    return sassVariable(name,variablesObj[name]);
  }).join('\n')
}

function sassImport(path) {
  return "@import '" + path + "';";
}

这样您就可以像以前一样使用SASS变量来使用SASS变量。它也不会使你陷入任何“特殊的动态sass实现”(即避免在你的.scss文件中使用“undercore / lodash模板”),这也意味着你可以利用IDE功能,linting等…你现在只是回到写正规的SASS,就一样了。

此外,它很好地转换为非节点/ http /编译的实时用法,例如通过Gulp等预先编译entry.scss的多个变体,给出多个值集合

我希望这可以帮助你@ChrisWright(和其他人)出来!我知道我很难找到关于这个主题的信息,我想象这是一个相当常见的用例(想从数据库,配置,HTTP参数等传递动态值到SASS)。

猜你在找的CSS相关文章