Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 06c868a

Browse files
committed
Merge pull request zweilove#35 from Umofomia/bundle-processor
Convert splitter engine to be a Sprockets bundle processor
2 parents e259f13 + e4d0fa6 commit 06c868a

17 files changed

+112
-62
lines changed

README.md

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ CssSplitter integrates with the Rails 3.1+ Asset Pipeline to generate additional
2525

2626
The first step is identifying the stylesheets that have more than 4095 selectors and therefore need to be split for IE.
2727

28-
Once you know which stylesheets need to be split, you need to create a second "container file" for those stylesheets with the file extension `.split2`, that will contain the styles beyond the 4095 selector limit.
28+
Once you know which stylesheets need to be split, you need to create a second "container file" for those stylesheets with the `_split2` suffix appended to the base filename that will contain the styles beyond the 4095 selector limit. The extension of this file should be just `.css` without any additional preprocessor extensions.
2929

30-
For example, if you want to split `too_big_stylesheet.css`, you need to create a new file `too_big_stylesheet_split2.css.split2` in the same directory. The only content of that container, will be an include of the original file, e.g.:
30+
For example, if you want to split `too_big_stylesheet.css.scss`, you need to create a new file `too_big_stylesheet_split2.css` in the same directory. The only content of that container, will contain a `require` directive to the name of the original asset, e.g.:
3131

32-
# app/assets/stylesheets/too_big_stylesheet_split2.css.split2
32+
# app/assets/stylesheets/too_big_stylesheet_split2.css
3333

34-
//= include 'too_big_stylesheet.css'
34+
/*
35+
*= require 'too_big_stylesheet'
36+
*/
37+
38+
If your stylesheet is big enough to need splitting into more than two more files, simply create additional `_split3`, `_split4`, etc. files, the contents of which should be identical to the `_split2` file.
3539

3640
You also need to remember to add those new files to the asset pipeline, so they will be compiled. For example:
3741

@@ -43,12 +47,10 @@ You also need to remember to add those new files to the asset pipeline, so they
4347

4448
Here is a checklist of requirements for your split stylesheet:
4549

46-
1. It needs to have different filename than orginal, e.g. `original_stylesheet_split2` or `application_split2`
47-
2. It needs to have `.split2` as a file extension, e.g. `.css.split2`, `.css.sass.split2`, or `.css.split2.erb`
48-
3. It needs to include the content of the orginal stylesheet, e.g. through `//= include 'application'` or `<%= environment.find_asset('application') %>`
49-
4. It needs to be added to list of precompiled assets
50-
51-
50+
1. It needs to have the `_splitN` suffix appended to the original asset name, e.g. `original_stylesheet_split2` or `application_split2`
51+
2. It needs to have `.css` as a file extension.
52+
3. It needs to require the orginal stylesheet.
53+
4. It needs to be added to list of precompiled assets.
5254

5355
### 2. Including your split stylesheets
5456

@@ -60,51 +62,28 @@ You can just use our `split_stylesheet_link_tag` helper, which would look someth
6062
<%= split_stylesheet_link_tag "too_big_stylesheet", :media => "all" %>
6163

6264
# output
63-
<link href="/stylesheets/too_big_stylesheet.css" media="screen" rel="stylesheet" type="text/css" />
65+
<link href="/stylesheets/too_big_stylesheet.css" media="all" rel="stylesheet" type="text/css" />
6466
<!--[if lte IE 9]>
65-
<link href="/stylesheets/too_big_stylesheet_split2.css" media="screen" rel="stylesheet" type="text/css" />
67+
<link href="/stylesheets/too_big_stylesheet_split2.css" media="all" rel="stylesheet" type="text/css" />
6668
<![endif]-->
6769

70+
If your stylesheet is split into more than two files, add the `split_count` option to specify the total number of files.
71+
72+
<%= split_stylesheet_link_tag "too_big_stylesheet", :split_count => 3 %>
73+
6874
Or you can just create similar HTML as in the above example yourself. If you want to use the `split_stylesheet_link_tag` helper you need to make sure the gem is loaded in production, so you can't put it in the `:assets` group in your Gemfile.
6975

7076
## How it works
7177

72-
Basically, CssSplitter is registering a new `Sprockets::Engine` for the `.split2` file extension, that will fill those files with all the selectors beyond the 4095th. Unfortunately, those `.split2` files need to be created manually, because we haven't figured out a way for a `Sprockets::Engine` to output multiple files. They need to present before the compile step.
78+
Basically, CssSplitter is registering a new Sprockets bundle processor that looks for CSS assets named with the `_splitN` suffix and will fill those files with all the selectors beyond the 4095th. Unfortunately, those `_splitN` files need to be created manually, because we haven't figured out a way for a `Sprockets::Engine` to output multiple files. They need to present before the compile step.
7379

7480
If you have more questions about how it works, look at the code or contact us.
7581

7682
## Gotchas
7783

78-
#### Having a JS asset with the same name as the the split stylesheet
79-
80-
If you want to split a style (e.g. `assets/stylesheets/application.*`) and have a JS asset with the same name (`assets/javascripts/application.*`) in your asset load_path (as is the default in Rails), you need to include the stylesheet along with the file extension `// = include 'application.css'` because otherwise it will try to include the JS asset of the same name instead. Sprocket's `= include` directive doesn't seem to differentiate between different types/folders and just takes the first asset it can find for any given name (see #10).
81-
82-
#### Don't use Sprocket's `= require_tree .` or `= require_self` for stylesheets
83-
It's recommended that you **always use Sass's `@import`** for all your stylesheets in favor of Sprocket's `= require` directives, just as the official `sass-rails` gem says: https://github.com/rails/sass-rails#important-note
84-
85-
If you have a `.split2` stylesheet in your tree that in turn includes the base stylesheet like shown below, you will end up with a nasty `Sprockets::CircularDependencyError`!
86-
87-
/* assets/stylesheets/application.css */
88-
/* = require_tree .
89-
90-
/* assets/stylesheets/application_split2.css.split2 */
91-
/* = include 'application.css' */
92-
93-
If you have `require_self` in the stylesheet that you're splitting, as shown below, the `.split2` will end up having **both** the original stylesheet and the split contents. You'll end up with an even bigger stylesheet.
94-
95-
/* assets/stylesheets/application.css */
96-
/* = require_self
97-
98-
/* assets/stylesheets/application_split2.css.split2 */
99-
/* = include 'application.css' */
100-
101-
102-
## Limitations & Known Issues
103-
104-
**More than 8190 selectors**
105-
106-
Currently the gem only supports stylesheets that need to be split into 2 files. It could theoretically create more splits (e.g. if you should have more than 8190 selectors), but in that case you should probably refactor your stylesheets anyway. Contact us, if you have this requirement.
84+
#### Differences from previous versions
10785

86+
Note that if you used the 0.x.x versions of this gem, the naming and contents of the split files have changed. Split files no longer need to have the `.split2` extension and now use the `require` directive rather than the `include` directive. The previous prohibition against using `require_tree .` and `require_self` directives also no longer applies.
10887

10988
## Credits & License
11089

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
module CssSplitter
22
module ApplicationHelper
33
def split_stylesheet_link_tag(*sources)
4-
original_sources = sources.dup
4+
options = sources.extract_options!
5+
split_count = options.delete(:split_count) || 2
56

6-
options = sources.extract_options!
7-
sources.collect!{ |source| "#{source}_split2" }
8-
sources << options
7+
sources.map do |source|
8+
split_sources = (2..split_count).map { |index| "#{source}_split#{index}" }
9+
split_sources << options
910

10-
[
11-
stylesheet_link_tag(*original_sources),
12-
"<!--[if lte IE 9]>",
13-
stylesheet_link_tag(*sources),
14-
"<![endif]-->"
15-
].join("\n").html_safe
11+
[
12+
stylesheet_link_tag(source, options),
13+
"<!--[if lte IE 9]>",
14+
stylesheet_link_tag(*split_sources),
15+
"<![endif]-->"
16+
]
17+
end.flatten.join("\n").html_safe
1618
end
1719
end
1820
end

lib/css_splitter/engine.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class Engine < ::Rails::Engine
33
isolate_namespace CssSplitter
44

55
initializer 'css_splitter.sprockets_engine', after: 'sprockets.environment', group: :all do |app|
6-
app.assets.register_engine '.split2', CssSplitter::SprocketsEngine
6+
app.assets.register_bundle_processor 'text/css', CssSplitter::SprocketsEngine
77
end
88

99
initializer 'css_splitter.action_controller' do |app|

lib/css_splitter/sprockets_engine.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ def prepare
1111
end
1212

1313
def evaluate(scope, locals, &block)
14-
# determine which is the current split (e.g. split2, split3)
15-
split = if scope.pathname.extname =~ /(\d+)$/; $1
16-
elsif scope.pathname.basename.to_s =~ /_split(\d+)\.css/; $1
17-
else 2
18-
end
19-
CssSplitter::Splitter.split_string(data, split.to_i)
14+
# Evaluate the split if the asset is named with a trailing _split2, _split3, etc.
15+
if scope.logical_path =~ /_split(\d+)$/
16+
CssSplitter::Splitter.split_string(data, $1.to_i)
17+
else
18+
data
19+
end
2020
end
2121
end
2222

test/css_splitter_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,41 @@
11
require 'test_helper'
22

33
class CssSplitterTest < ActiveSupport::TestCase
4+
5+
setup :clear_assets_cache
6+
47
test "truth" do
58
assert_kind_of Module, CssSplitter
69
end
10+
11+
test "asset pipeline stylesheet splitting" do
12+
part1 = "#test{background-color:red}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
13+
part2 = "#test{background-color:green}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
14+
part3 = "#test{background-color:blue}"
15+
16+
assert_equal "#{part1}#{part2}#{part3}\n", assets["erb_stylesheet"].to_s
17+
assert_equal "#{part2}\n", assets["erb_stylesheet_split2"].to_s
18+
assert_equal "#{part3}\n", assets["erb_stylesheet_split3"].to_s
19+
end
20+
21+
test "asset pipeline stylesheet splitting on stylesheet combined using requires" do
22+
red = "#test{background-color:red}" * 100
23+
green = "#test{background-color:green}" * CssSplitter::Splitter::MAX_SELECTORS_DEFAULT
24+
blue = "#test{background-color:blue}"
25+
26+
assert_equal "#{red}#{green}#{blue}\n", assets["combined"].to_s
27+
assert_equal "#{"#test{background-color:green}" * 100}#{blue}\n", assets["combined_split2"].to_s
28+
end
29+
30+
private
31+
32+
def clear_assets_cache
33+
assets_cache = Rails.root.join("tmp/cache/assets")
34+
assets_cache.rmtree if assets_cache.exist?
35+
end
36+
37+
def assets
38+
Rails.application.assets
39+
end
40+
741
end
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//= require 'red_100'
2+
//= require 'green_max'
3+
4+
#test { background-color: blue; }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
*= require 'combined'
3+
*/
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<% CssSplitter::Splitter::MAX_SELECTORS_DEFAULT.times do %>
2+
#test { background-color: red; }
3+
<% end %>
4+
<% CssSplitter::Splitter::MAX_SELECTORS_DEFAULT.times do %>
5+
#test { background-color: green; }
6+
<% end %>
7+
#test { background-color: blue; }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
*= require 'erb_stylesheet.css'
3+
*/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*
2+
*= require 'erb_stylesheet.css'
3+
*/

0 commit comments

Comments
 (0)