Chr*_*ght 25 css sass node.js express 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;
}
Run Code Online (Sandbox Code Playgroud)
皱纹是现在我需要从Node传递动态数据并将其编译为普通的SASS变量.最初我尝试使用PostCSS,因为我注意到它可以做变量注入.不幸的是,这不起作用.PostCSS在编译阶段开始,在这一点上惨败.
接下来,我尝试使用下划线模板尝试使用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' })
};
}
});
Run Code Online (Sandbox Code Playgroud)
这导致以下错误:
Error: error reading values after :
Run Code Online (Sandbox Code Playgroud)
显然,SASS不喜欢下划线的变量语法.
如何从我的Node应用程序中将动态变量传递给SASS?
Eri*_*bar 61
我发现自己情况非常相似.我们有很多现有的SASS,现在需要接受要在整个过程中使用的动态值/变量(作为变量).我最初去了书面的临时目录/文件,基本上造就了"代理入口点",这将创造一个途径proxy_entry.scss,并variables.scss和引导的实际entry.scss与预期的声明社科院变量.这很好,并取得了预期的效果,但感觉有点过于复杂......
事实证明,由于node-sass的options.data选项,有一个更简单的解决方案.这接受"要评估的SASS字符串".
类型:字符串默认值:null特殊:必须指定文件或数据
要传递给libsass以进行渲染的字符串.建议您将includePaths与此结合使用,以便libsass在使用@import指令时可以查找文件.
这完全消除了编写/管理所有临时目录和文件的需要.
解决方案归结为类似的东西
var sassOptionsDefaults = {
includePaths: [
'some/include/path'
],
outputStyle: 'compressed'
};
Run Code Online (Sandbox Code Playgroud)
options.datavar dataString =
sassGenerator.sassVariables(variables) +
sassGenerator.sassImport(scssEntry);
var sassOptions = _.assign({}, sassOptionsDefaults, {
data: dataString
});
Run Code Online (Sandbox Code Playgroud)
var sass = require('node-sass');
sass.render(sassOptions, function (err, result) {
return (err)
? handleError(err);
: handleSuccess(result.css.toString());
});
Run Code Online (Sandbox Code Playgroud)
注意: 这是假设您的entry.scss导入variables.scss将变量定义为"默认值".
// variables.scss
$someColor: blue !default;
$someFontSize: 13px !default;
// entry.scss
@import 'variables';
.some-selector {
color: $someColor;
font-size: $someFontSize;
}
Run Code Online (Sandbox Code Playgroud)
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({}, sassOptionsDefaults, {
data: dataString
});
// 3.) render sass as usual
sass.render(sassOptions, function (err, result) {
return (err)
? handleError(err);
: handleSuccess(result.css.toString());
});
}
// Example usage.
dynamicSass('some/path/entry.scss', {
'someColor': 'red',
'someFontSize': '18px'
}, someSuccessFn, someErrorFn);
Run Code Online (Sandbox Code Playgroud)
"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 + "';";
}
Run Code Online (Sandbox Code Playgroud)
这使您能够像以前一样使用SASS变量编写SASS,并在任何需要的位置使用SASS变量.它也没有把你绑定到任何"特殊的动态sass实现"(即这避免在你的.scss文件中使用"下划线/ lodash模板" .)这也意味着你可以利用IDE功能,linting等...只是因为你现在回到正常的SASS写作.
此外,它很好地转换为非节点/ http /即时编译用法,例如entry.scss通过Gulp等预先编译给定多个值集的多个变体...
我希望这能帮助你@ChrisWright(以及其他人)!我知道我很难找到关于这个主题的信息,我想这是一个相当常见的用例(想要从数据库,配置,HTTP参数等将动态值传递给SASS).
在我研究了 node-sass 的方法后,我能够解决这个问题importer()。我的解决方案涉及下划线模板并在文件进入时手动读取文件。这不是最优雅或最有效的解决方案,但每个生成的页面仅运行一次。之后,文件将被缩小并缓存以供将来的请求。
// Other none-sass render parameters omitted for brevity
importer: function (url, prev, done) {
// Manually read each partial file as it's encountered
fs.readFile(url, function (err, result) {
if (err) {
// If there is an error reading the file, call done() with
// no content to avoid a crash
return done({
contents: ''
});
}
// Create an underscore template out of the partial
var partial = _.template(result.toString());
// Compile template and return its contents to node-sass for
// compilation with the rest of the SCSS partials
done({
contents: partial({ data: YOUR_DATA_OBJECT })
});
});
}
Run Code Online (Sandbox Code Playgroud)
使用这个解决方案,我们可以在 SCSS 部分中引用正常的下划线变量语法。举个例子:
body {
color: <%= data.colour %>;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12843 次 |
| 最近记录: |