turbo-sprockets-rails3 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +32 -8
- data/lib/turbo-sprockets/sprockets_overrides/asset.rb +24 -22
- data/lib/turbo-sprockets/sprockets_overrides/bundled_asset.rb +22 -20
- data/lib/turbo-sprockets/sprockets_overrides/environment.rb +13 -11
- data/lib/turbo-sprockets/sprockets_overrides/index.rb +19 -17
- data/lib/turbo-sprockets/sprockets_overrides/static_compiler.rb +52 -50
- data/lib/turbo-sprockets/version.rb +1 -1
- metadata +1 -1
data/README.md
CHANGED
@@ -6,31 +6,55 @@
|
|
6
6
|
This is a backport of the work I've done for Rails 4.0.0, released as
|
7
7
|
a gem for Rails 3.2.x. (See [sprockets-rails #21](https://github.com/rails/sprockets-rails/pull/21) and [sprockets #367](https://github.com/sstephenson/sprockets/pull/367) for the Rails 4 pull requests.)
|
8
8
|
|
9
|
+
|
9
10
|
### Disclaimer
|
10
11
|
|
11
12
|
Please test this out thoroughly on your local machine before deploying to a production site, and open an issue on GitHub if you have any problems. By using this software you agree to the terms and conditions in the [MIT license](https://github.com/ndbroadbent/turbo-sprockets-rails3/blob/master/MIT-LICENSE).
|
12
13
|
|
13
|
-
|
14
|
+
## Dependencies
|
14
15
|
|
15
16
|
* sprockets `~> 2.1.3`
|
16
17
|
* railties `~> 3.2.0`
|
17
18
|
|
18
|
-
|
19
|
+
## Usage
|
19
20
|
|
20
|
-
Just drop the gem in your `Gemfile
|
21
|
+
Just drop the gem in your `Gemfile`:
|
21
22
|
|
22
23
|
```ruby
|
23
|
-
|
24
|
-
...
|
25
|
-
|
26
|
-
gem 'turbo-sprockets-rails3'
|
27
|
-
end
|
24
|
+
gem 'turbo-sprockets-rails3'
|
28
25
|
```
|
29
26
|
|
30
27
|
Run `bundle`, and you're done!
|
31
28
|
|
29
|
+
|
32
30
|
Test it out by running `rake assets:precompile`. When it's finished, your `public/assets/manifest.yml` file should include a `:source_digests` hash for your assets.
|
33
31
|
|
34
32
|
Go on, run `rake assets:precompile` again, and it should be a whole lot faster than before.
|
35
33
|
|
36
34
|
Enjoy your lightning fast deploys!
|
35
|
+
|
36
|
+
#### Automatic clean up of old assets
|
37
|
+
|
38
|
+
By default, the `assets:precompile` task now deletes out-of-date assets after a new version is compiled. If you don't want to automatically delete old assets, you can turn off this behaviour by setting `config.assets.clean_after_precompile = false` in `config/environments/production.rb`.
|
39
|
+
|
40
|
+
## Deployments
|
41
|
+
|
42
|
+
### Heroku
|
43
|
+
|
44
|
+
You won't be able to do an 'incremental update' on heroku, since your `public/assets`
|
45
|
+
folder will be empty at the start of each push. However, this gem can still cut your
|
46
|
+
precompile time in half, since it only compiles assets once to generate both digest and non-digest assets.
|
47
|
+
|
48
|
+
### Capistrano
|
49
|
+
|
50
|
+
If you are deploying with Capistrano, it's not a good idea to symlink `public/assets` to a shared assets folder, because the asset cleanup task would delete the current assets before the deploy has finished. Keeping a separate copy of `public/assets` for each release also means that you can safely roll back to a previous release.
|
51
|
+
The best approach would be to add a deploy step that copies the `public/assets` folder from your previous release into the current release, before running `assets:precompile`.
|
52
|
+
|
53
|
+
## Debugging
|
54
|
+
|
55
|
+
If you would like to view debugging information in your terminal during the `assets:precompile` task, add the following lines to the bottom of `config/environments/production.rb`:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
config.log_level = :debug
|
59
|
+
config.logger = Logger.new(STDOUT)
|
60
|
+
```
|
@@ -1,29 +1,31 @@
|
|
1
1
|
require 'sprockets/asset'
|
2
2
|
|
3
|
-
Sprockets
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Sprockets
|
4
|
+
Asset.class_eval do
|
5
|
+
# Internal initializer to load `Asset` from serialized `Hash`.
|
6
|
+
def self.from_hash(environment, hash)
|
7
|
+
return unless hash.is_a?(Hash)
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
klass = case hash['class']
|
10
|
+
when 'BundledAsset'
|
11
|
+
BundledAsset
|
12
|
+
when 'ProcessedAsset'
|
13
|
+
ProcessedAsset
|
14
|
+
when 'UnprocessedAsset'
|
15
|
+
UnprocessedAsset
|
16
|
+
when 'StaticAsset'
|
17
|
+
StaticAsset
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
if klass
|
23
|
+
asset = klass.allocate
|
24
|
+
asset.init_with(environment, hash)
|
25
|
+
asset
|
26
|
+
end
|
27
|
+
rescue UnserializeError
|
28
|
+
nil
|
25
29
|
end
|
26
|
-
rescue UnserializeError
|
27
|
-
nil
|
28
30
|
end
|
29
31
|
end
|
@@ -1,31 +1,33 @@
|
|
1
1
|
require 'sprockets/bundled_asset'
|
2
2
|
|
3
|
-
Sprockets
|
3
|
+
module Sprockets
|
4
|
+
BundledAsset.class_eval do
|
4
5
|
|
5
|
-
|
6
|
+
# Adds :process options
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def initialize(environment, logical_path, pathname, options = {})
|
9
|
+
super(environment, logical_path, pathname)
|
10
|
+
@process = options.fetch(:process, true)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
@processed_asset = environment.find_asset(pathname, :bundle => false, :process => @process)
|
13
|
+
@required_assets = @processed_asset.required_assets
|
14
|
+
@dependency_paths = @processed_asset.dependency_paths
|
14
15
|
|
15
|
-
|
16
|
+
@source = ""
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
# Explode Asset into parts and gather the dependency bodies
|
19
|
+
to_a.each { |dependency| @source << dependency.to_s }
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
if @process
|
22
|
+
# Run bundle processors on concatenated source
|
23
|
+
context = environment.context_class.new(environment, logical_path, pathname)
|
24
|
+
@source = context.evaluate(pathname, :data => @source,
|
25
|
+
:processors => environment.bundle_processors(content_type))
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
@mtime = to_a.map(&:mtime).max
|
29
|
+
@length = Rack::Utils.bytesize(source)
|
30
|
+
@digest = environment.digest.update(source).hexdigest
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
require 'sprockets/environment'
|
2
2
|
|
3
|
-
Sprockets
|
3
|
+
module Sprockets
|
4
|
+
Environment.class_eval do
|
4
5
|
|
5
|
-
|
6
|
+
# Adds :process options
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def find_asset(path, options = {})
|
9
|
+
options[:bundle] = true unless options.key?(:bundle)
|
10
|
+
options[:process] = true unless options.key?(:process)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
# Ensure in-memory cached assets are still fresh on every lookup
|
13
|
+
if (asset = @assets[cache_key_for(path, options)]) && asset.fresh?(self)
|
14
|
+
asset
|
15
|
+
elsif asset = index.find_asset(path, options)
|
16
|
+
# Cache is pushed upstream by Index#find_asset
|
17
|
+
asset
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,28 +1,30 @@
|
|
1
1
|
require 'sprockets/index'
|
2
2
|
|
3
|
-
Sprockets
|
3
|
+
module Sprockets
|
4
|
+
Index.class_eval do
|
4
5
|
|
5
|
-
|
6
|
+
# Adds :process options
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def find_asset(path, options = {})
|
9
|
+
options[:bundle] = true unless options.key?(:bundle)
|
10
|
+
options[:process] = true unless options.key?(:process)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
if asset = @assets[cache_key_for(path, options)]
|
13
|
+
asset
|
14
|
+
elsif asset = super
|
15
|
+
logical_path_cache_key = cache_key_for(path, options)
|
16
|
+
full_path_cache_key = cache_key_for(asset.pathname, options)
|
16
17
|
|
17
|
-
|
18
|
-
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
19
|
-
|
20
|
-
# Push cache upstream to Environment
|
21
|
-
@environment.instance_eval do
|
18
|
+
# Cache on Index
|
22
19
|
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
23
|
-
end
|
24
20
|
|
25
|
-
|
21
|
+
# Push cache upstream to Environment
|
22
|
+
@environment.instance_eval do
|
23
|
+
@assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
|
24
|
+
end
|
25
|
+
|
26
|
+
asset
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,68 +1,70 @@
|
|
1
1
|
require 'sprockets/static_compiler'
|
2
2
|
|
3
|
-
Sprockets
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
module Sprockets
|
4
|
+
StaticCompiler.class_eval do
|
5
|
+
def initialize(env, target, paths, options = {})
|
6
|
+
@env = env
|
7
|
+
@target = target
|
8
|
+
@paths = paths
|
9
|
+
@digest = options.fetch(:digest, true)
|
10
|
+
@manifest = options.fetch(:manifest, true)
|
11
|
+
@manifest_path = options.delete(:manifest_path) || target
|
12
|
+
@zip_files = options.delete(:zip_files) || /\.(?:css|html|js|svg|txt|xml)$/
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
@current_source_digests = options.fetch(:source_digests, {})
|
15
|
+
@current_digest_files = options.fetch(:digest_files, {})
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
@digest_files = {}
|
18
|
+
@source_digests = {}
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
def compile
|
22
|
+
start_time = Time.now.to_f
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
env.each_logical_path do |logical_path|
|
25
|
+
if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
|
26
|
+
logical_path.sub!(/\/index\./, '.')
|
27
|
+
end
|
28
|
+
next unless compile_path?(logical_path)
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
# Fetch asset without any processing or compression,
|
31
|
+
# to calculate a digest of the concatenated source files
|
32
|
+
asset = env.find_asset(logical_path, :process => false)
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
# Force digest to UTF-8, otherwise YAML dumps ASCII-8BIT as !binary
|
35
|
+
@source_digests[logical_path] = asset.digest.force_encoding("UTF-8")
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
# Recompile if digest has changed or compiled digest file is missing
|
38
|
+
current_digest_file = @current_digest_files[logical_path]
|
38
39
|
|
39
|
-
|
40
|
-
|
40
|
+
if @source_digests[logical_path] != @current_source_digests[logical_path] ||
|
41
|
+
!(current_digest_file && File.exists?("#{@target}/#{current_digest_file}"))
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
if asset = env.find_asset(logical_path)
|
44
|
+
@digest_files[logical_path] = write_asset(asset)
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
else
|
48
|
+
# Set asset file from manifest.yml
|
49
|
+
digest_file = @current_digest_files[logical_path]
|
50
|
+
@digest_files[logical_path] = digest_file
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
env.logger.debug "Not compiling #{logical_path}, sources digest has not changed " <<
|
53
|
+
"(#{@source_digests[logical_path][0...7]})"
|
54
|
+
end
|
53
55
|
end
|
54
|
-
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
if @manifest
|
58
|
+
write_manifest(source_digests: @source_digests, digest_files: @digest_files)
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
# Store digests in Rails config. (Important if non-digest is run after primary)
|
62
|
+
config = ::Rails.application.config
|
63
|
+
config.assets.digest_files = @digest_files
|
64
|
+
config.assets.source_digests = @source_digests
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
|
67
|
+
env.logger.debug "Processed #{'non-' unless @digest}digest assets in #{elapsed_time}ms"
|
68
|
+
end
|
67
69
|
end
|
68
|
-
end
|
70
|
+
end
|