简体   繁体   English

使用RoR Asset Pipeline将样式表添加到Javascript

[英]Adding Stylesheets to Javascript with the RoR Asset Pipeline

I'm developing a third party script. 我正在开发第三方脚本。 I'm adding my own stylesheet to the page where the script is embedded. 我正在将自己的样式表添加到嵌入脚本的页面中。 Currently the style is a long string in JavaScript. 目前,样式是JavaScript中的长字符串。 That's silly, but it's faster than appending a style link and making another http request. 这很愚蠢,但它比追加样式链接和发出另一个http请求更快。

Looking at the facebook SDK we see a php script that does something like this, with JS_FILES and CSS_FILES being arrays of file names: 看看facebook SDK,我们看到一个php脚本做了类似的事情, JS_FILESCSS_FILES是文件名数组:

// all.js
foreach ($JS_FILES as $file) {
  echo file_get_contents($file);
}

$css = '';
foreach ($CSS_FILES as $file) {
  $css .= file_get_contents($file);
}
// css URLs are relative to facebook domains
$css = preg_replace('#url\(/#', 'url(http://static.ak.fbcdn.net/', $css);
echo 'FB.Dom.addCssRules(' . json_encode($css) . ', ["pkg"])';

So the css is converted to JSON and sent to the FB.Dom.addCssRules function which appends the style to the page. 因此,css被转换为JSON并发送到FB.Dom.addCssRules函数,该函数将样式附加到页面。

Writing css in JS strings is stupid. 在JS字符串中编写css是愚蠢的。 I want to utilize SCSS in my style, I want to have syntax highlighting and I want to develop in a reasonable environment. 我希望以我的风格使用SCSS,我希望语法高亮,我想在合理的环境中开发。

What do I need to do, how to I hook into the Asset Pipeline / Sprockets / Tilt to make this thing happen? 我需要做什么,如何挂钩Asset Pipeline / Sprockets / Tilt来实现这个目标?

Code examples are a big plus, as I'm not a crazy good ruby dev. 代码示例是一个很大的优点,因为我不是一个疯狂的好ruby dev。

Edit : I went through the Asset Pipeline docs and didn't see any way to actually hook into it. 编辑 :我浏览了资产管道文档,并没有看到任何实际挂钩的方法。 The only option I see is to create a Tranfsorm class that calls the default transform and then converts the output to a JS string and sends it to a function. 我看到的唯一选择是创建一个调用默认转换的Tranfsorm类,然后将输出转换为JS字符串并将其发送到函数。 I don't really know how to do that. 我真的不知道该怎么做。 I don't know if I can even require a .jscss files without making the pipeline freak out. 我不知道我是否甚至可以在不使管道发生.jscss情况下需要.jscss文件。 Another option (which is quite similar) is to write a gem like Black Coffee , again I don't really have an idea how should I go about implementing this. 另一种选择(非常相似)是写一个像黑咖啡这样的宝石,我真的不知道我该怎么做才能实现这个。

You may not need a new template engine to accomplish this; 您可能不需要新的模板引擎来完成此任务; you can use a few helper methods in your javascript file instead. 您可以在javascript文件中使用一些辅助方法。 You can use #evaluate to render a given CSS file inline, the result of which needs to be javascript escaped. 您可以使用#evaluate内联呈现给定的CSS文件,其结果需要进行javascript转义。 According to sprockets documentation , you can include helpers by hooking into the Sprockets environment context class right in your js template. 根据sprockets文档 ,您可以通过在js模板中挂接到Sprockets环境上下文类来包含帮助程序。 So, assuming you have a css file that compiles to 'inline.css', you can include ActionView::Helpers::JavaScriptHelper and do the following: 因此,假设您有一个编译为'inline.css'的css文件,您可以包含ActionView :: Helpers :: JavaScriptHelper并执行以下操作:

# css_string.js.erb
<% environment.context_class.instance_eval { include ActionView::Helpers::JavaScriptHelper } %>
css_string = "<%= escape_javascript(evaluate('inline.css')) %>";

Sprockets is not ideal for solving this problem. 链轮不是解决这个问题的理想选择。 You'll end up writing code that is ugly and fails randomly (I speak from frustrating personal experience with Rails.application.assets.find_asset() .) 你最终会编写丑陋且随机失败的代码(我用Rails.application.assets.find_asset()来表达令人沮丧的个人经验。)

Instead, look into RequireJS + text plugin for composing Javascript with dependencies that are not JS (like CSS & Mustache/Handlebars templates), and building it all into an optimized single-file for production. 相反,请查看RequireJS +文本插件,用于编写具有非JS依赖项的Javascript(如CSS和Mustache / Handlebars模板),并将其全部构建为优化的单个文件以进行生产。

RequireJS integrates with Rails easily for dev & production using the requires-rails gem/engine. RequireJS使用requires-rails gem / engine轻松地与开发和生产集成Rails。

Just take note that while you can use Sprockets & RequireJS in the same app, that you should never mix the dependency mechanisms //= require ... & define([...], function(...){}) in the same file/dependency chain. 请注意,虽然您可以在同一个应用程序中使用Sprockets和RequireJS,但您绝不应该混合依赖机制//= require ...define([...], function(...){}) in相同的文件/依赖链。

I think @rossta has put you on the right track here. 我认为@rossta已经让你走在正确的轨道上。 I would suggest a couple of modifications, though. 不过,我建议进行一些修改。 First, if you are writing your stylesheets in sass, and would like the compiled css to be inserted in your javascript, the following would be one way to achieve that: 首先,如果你在sass中编写样式表,并希望将编译好的css插入到javascript中,以下是实现这一目的的一种方法:

<%= escape_javascript(Rails.application.assets.find_asset('inline').to_s.chomp) %>

where inline.css.scss is somewhere on the assets search path. 其中inline.css.scss位于资产搜索路径的某个位置。 The method find_asset will compile your sass and return the output as a string. find_asset方法将编译你的sass并将输出作为字符串返回。 One issue is that the javascript in which you include this won't be re-compiled unless the javascript file itself changes, or you explicitly mark inline.css as a dependency. 一个问题是,除非javascript文件本身发生更改,否则不会重新编译包含此内容的javascript,或者将inline.css明确标记为依赖项。 You can do this by including the directive 您可以通过包含该指令来完成此操作

//= depend_on inline.css

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM