This repository was archived by the owner on Mar 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 199
/
Copy pathrequirejs-rails_tasks.rake
230 lines (191 loc) · 7.92 KB
/
requirejs-rails_tasks.rake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
require "fileutils"
require "pathname"
require "tempfile"
require "active_support/ordered_options"
require "sprockets"
require "requirejs/rails/builder"
require "requirejs/rails/config"
namespace :requirejs do
# This method was backported from an earlier version of Sprockets.
def ruby_rake_task(task, force = true)
env = ENV["RAILS_ENV"] || "production"
groups = ENV["RAILS_GROUPS"] || "assets"
args = [$0, task, "RAILS_ENV=#{env}", "RAILS_GROUPS=#{groups}"]
args << "--trace" if Rake.application.options.trace
ruby *args
end
# From Rails 3 assets.rake; we have the same problem:
#
# We are currently running with no explicit bundler group
# and/or no explicit environment - we have to reinvoke rake to
# execute this task.
def invoke_or_reboot_rake_task(task)
if ENV['RAILS_GROUPS'].to_s.empty? || ENV['RAILS_ENV'].to_s.empty?
ruby_rake_task task
else
Rake::Task[task].invoke
end
end
requirejs = ActiveSupport::OrderedOptions.new
path_extension_pattern = Regexp.new("\\.(\\w+)\\z")
task clean: ["requirejs:setup"] do
FileUtils.remove_entry_secure(requirejs.config.source_dir, true)
FileUtils.remove_entry_secure(requirejs.driver_path, true)
end
task setup: ["assets:environment"] do
unless defined?(::Sprockets)
warn "Cannot precompile assets if sprockets is disabled. Please set config.assets.enabled to true"
exit
end
# Ensure that action view is loaded and the appropriate
# sprockets hooks get executed
_ = ActionView::Base
requirejs.env = Rails.application.config.assets
requirejs.sprockets = Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)
# Preserve the original asset paths, as we'll be manipulating them later
requirejs.env_paths = requirejs.env.paths.dup
requirejs.config = Rails.application.config.requirejs
requirejs.builder = Requirejs::Rails::Builder.new(requirejs.config)
requirejs.manifest = {}
end
task :test_node do
begin
`node -v`
rescue Errno::ENOENT
STDERR.puts <<-EOM
Unable to find 'node' on the current path, required for precompilation
using the requirejs-ruby gem. To install node.js, see http://nodejs.org/
OS X Homebrew users can use 'brew install node'.
EOM
exit 1
end
end
namespace :precompile do
task all: ["requirejs:precompile:digestify_and_compress"]
# Invoke another ruby process if we're called from inside
# assets:precompile so we don't clobber the environment
#
# We depend on test_node here so we'll fail early and hard if node
# isn't available.
task :external do
ruby_rake_task "requirejs:precompile:all"
end
# Copy all assets to the temporary staging directory.
task prepare_source: ["requirejs:setup",
"requirejs:clean"] do
requirejs.config.source_dir.mkpath
# Save the original JS compressor and cache, which will be restored later.
original_js_compressor = requirejs.env.js_compressor
requirejs.env.js_compressor = false
original_cache = requirejs.env.cache
requirejs.env.cache = nil
if ::Sprockets::VERSION.split(".").first.to_i < 3
# Sprockets 2.x
requirejs.env.each_logical_path(requirejs.config.logical_path_patterns) do |logical_path|
m = ::Requirejs::Rails::Config::BOWER_PATH_PATTERN.match(logical_path)
if !m
asset = requirejs.env.find_asset(logical_path)
if asset
file = requirejs.config.source_dir.join(asset.logical_path)
file.dirname.mkpath
asset.write_to(file)
end
else
bower_logical_path = "#{Pathname.new(logical_path).dirname.to_s}.js"
asset = requirejs.env.find_asset(bower_logical_path)
if asset
file = requirejs.config.source_dir.join(bower_logical_path)
file.dirname.mkpath
asset.write_to(file)
end
end
end
else
# Sprockets 3.x
requirejs.sprockets.each_file do |file|
begin
asset_uri, deps = requirejs.sprockets.resolve! file
asset = requirejs.sprockets.load asset_uri
asset_logical_path = asset.logical_path
if requirejs.config.logical_path_patterns.any? { |pattern| pattern.match asset_logical_path }
m = ::Requirejs::Rails::Config::BOWER_PATH_PATTERN.match(asset_logical_path)
if !m
target_file = requirejs.config.source_dir.join(asset_logical_path)
asset.write_to(target_file)
else
raise "Not supported yet"
end
end
rescue
# Ignore if precompiled assets fail.
# This happens for example if we stumble on a scss file that has
# a variable defined elsewhere.
end
end
end
# Restore the original JS compressor and cache.
requirejs.env.js_compressor = original_js_compressor
requirejs.env.cache = original_cache
end
task generate_rjs_driver: ["requirejs:setup"] do
requirejs.builder.generate_rjs_driver
end
task run_rjs: ["requirejs:setup",
"requirejs:test_node",
"requirejs:precompile:prepare_source",
"requirejs:precompile:generate_rjs_driver"] do
requirejs.config.build_dir.mkpath
requirejs.config.target_dir.mkpath
requirejs.config.driver_path.dirname.mkpath
result = `node "#{requirejs.config.driver_path}"`
unless $?.success?
raise RuntimeError, "Asset compilation with node failed with error:\n\n#{result}\n"
end
end
# Copy each built asset, identified by a named module in the
# build config, to its Sprockets digestified name.
task digestify_and_compress: ["requirejs:precompile:run_rjs"] do
requirejs.config.build_config["modules"].each do |m|
module_name = requirejs.config.module_name_for(m)
paths = requirejs.config.build_config["paths"] || {}
module_script_name = "#{module_name}.js"
# Is there a `paths` entry for the module?
if !paths[module_name]
asset_name = module_script_name
else
asset_name = "#{paths[module_name]}.js"
end
# old Sprockets 2
#asset = requirejs.env.find_asset(asset_name)
asset = requirejs.sprockets.find_asset(asset_name)
built_asset_path = requirejs.config.build_dir.join(asset_name)
# Compute the digest based on the contents of the compiled file, *not* on the contents of the RequireJS module.
# Old Sprockets 2
#file_digest = ::Rails.application.assets.file_digest(built_asset_path.to_s)
#hex_digest = file_digest.unpack("H*").first
hex_digest = requirejs.sprockets.pack_hexdigest(requirejs.sprockets.digest_class.digest(built_asset_path.to_s))
digest_name = asset.logical_path.gsub(path_extension_pattern) { |ext| "-#{hex_digest}#{ext}" }
digest_asset_path = requirejs.config.target_dir + digest_name
# Ensure that the parent directory `a/b` for modules with names like `a/b/c` exist.
digest_asset_path.dirname.mkpath
requirejs.manifest[module_script_name] = digest_name
FileUtils.cp built_asset_path, digest_asset_path
# Create the compressed versions
File.open("#{built_asset_path}.gz", 'wb') do |f|
zgw = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
zgw.write built_asset_path.read
zgw.close
end
FileUtils.cp "#{built_asset_path}.gz", "#{digest_asset_path}.gz"
requirejs.config.manifest_path.open('wb') do |f|
YAML.dump(requirejs.manifest, f)
end
end
end
end
desc "Precompile RequireJS-managed assets"
task :precompile do
invoke_or_reboot_rake_task "requirejs:precompile:all"
end
end
task "assets:precompile" => ["requirejs:precompile:external"]