webpack_rails 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/webpack_rails.rb +8 -0
- data/lib/webpack_rails/engine.rb +12 -0
- data/lib/webpack_rails/processor.rb +24 -0
- data/lib/webpack_rails/sprockets_base_webpack.rb +14 -0
- data/lib/webpack_rails/sprockets_index_webpack.rb +15 -0
- data/lib/webpack_rails/task.rb +86 -0
- data/lib/webpack_rails/webpack-task.js +87 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4eefc65be79a7423acbb4aee442f794dda650b0a
|
4
|
+
data.tar.gz: fc8ff00a8a7ffb4048e783756c0d35041f7c81f7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c12944c42e4f37cf0ad6d559a6389553067ce9034590aa93f25929767656542795ae622657f0cda43c9f3a5217f9440a1feca69dfe68e7ff693e72e8c5f37e85
|
7
|
+
data.tar.gz: b737ff3f47506b20307bc35af43cb94e25bea7e61f3cd15473987fcfa3823873e194b297eaf5b3d0831fc1edddc66a4def50ecfd52e6d1fd6a46f84637c56cc6
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative './processor'
|
2
|
+
|
3
|
+
module WebpackRails
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
initializer :setup_webpack_rails, :after => "sprockets.environment", :group => :all do |app|
|
6
|
+
# where [name].bundle.js files should be
|
7
|
+
app.assets.append_path Rails.root.join('tmp/webpack/bundles')
|
8
|
+
# process
|
9
|
+
app.assets.register_preprocessor('application/javascript', WebpackRails::Processor)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
require_relative './sprockets_index_webpack'
|
4
|
+
require_relative './task'
|
5
|
+
|
6
|
+
module WebpackRails
|
7
|
+
class Processor < Tilt::Template
|
8
|
+
def prepare
|
9
|
+
end
|
10
|
+
|
11
|
+
def evaluate(context, locals)
|
12
|
+
return data unless context.pathname.to_s.include?('.bundle')
|
13
|
+
|
14
|
+
# wait til webpack is done before loading
|
15
|
+
result = WebpackRails::Task.run_webpack
|
16
|
+
|
17
|
+
result[:modules].map{|m| context.depend_on m}
|
18
|
+
|
19
|
+
bundle_contents = context.pathname.open.read
|
20
|
+
# rewrite $asset_paths in strings
|
21
|
+
bundle_contents.gsub(/['"]\$asset_path\/([^'"]+?)['"]/) {|s| "'#{context.asset_path($1)}'" }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require_relative './task'
|
3
|
+
|
4
|
+
# reopen Sprockets::Base and monkeypatch resolve
|
5
|
+
class Sprockets::Base
|
6
|
+
original_resolve = instance_method(:resolve)
|
7
|
+
|
8
|
+
define_method :resolve, ->(logical_path, options = {}, &block) {
|
9
|
+
if logical_path.to_s.include?('.bundle')
|
10
|
+
WebpackRails::Task.run_webpack # ensure output files exist so original_resolve doesn't fail
|
11
|
+
end
|
12
|
+
original_resolve.bind(self).(logical_path, options, &block)
|
13
|
+
}
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require_relative './task'
|
3
|
+
|
4
|
+
# reopen Sprockets::Index and monkeypatch find_asset
|
5
|
+
class Sprockets::Index
|
6
|
+
original_find_asset = instance_method(:find_asset)
|
7
|
+
|
8
|
+
define_method :find_asset, ->(path, options = {}) {
|
9
|
+
unless @_webpack_built
|
10
|
+
WebpackRails::Task.run_webpack # ensure output files exist so original_find_asset doesn't fail
|
11
|
+
@_webpack_built = true
|
12
|
+
end
|
13
|
+
original_find_asset.bind(self).(path, options)
|
14
|
+
}
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'node_task'
|
2
|
+
require 'benchmark'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module WebpackRails
|
6
|
+
class Task < NodeTask
|
7
|
+
# wraps NodeTask::Error
|
8
|
+
class Error < StandardError
|
9
|
+
def initialize(node_task_error)
|
10
|
+
super(node_task_error.to_s)
|
11
|
+
|
12
|
+
# TODO: expose @js_error from NodeTask::Error
|
13
|
+
js_error = node_task_error.instance_variable_get(:@js_error)
|
14
|
+
set_backtrace(js_error[:stack].split('\n')) if js_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def root_dir
|
20
|
+
@root_dir ||= defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
21
|
+
end
|
22
|
+
|
23
|
+
def working_dir
|
24
|
+
@working_dir ||= _make_working_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
def webpack_gem_dir
|
28
|
+
@webpack_gem_dir ||= File.dirname(File.expand_path(__FILE__))
|
29
|
+
end
|
30
|
+
|
31
|
+
def webpack_task_script
|
32
|
+
@webpack_task_script ||= File.join(webpack_gem_dir, 'webpack-task.js')
|
33
|
+
end
|
34
|
+
|
35
|
+
def app_node_path
|
36
|
+
@app_node_path ||= File.join(root_dir, 'node_modules')
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_app_node_path
|
40
|
+
prev_node_path = ENV['NODE_PATH']
|
41
|
+
ENV['NODE_PATH'] = app_node_path
|
42
|
+
return_value = nil
|
43
|
+
Dir.chdir(root_dir) do
|
44
|
+
return_value = yield
|
45
|
+
end
|
46
|
+
ENV['NODE_PATH'] = prev_node_path
|
47
|
+
return_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def run_webpack(opts = nil)
|
51
|
+
result = nil
|
52
|
+
|
53
|
+
task_duration = Benchmark.realtime do
|
54
|
+
result = with_app_node_path do
|
55
|
+
begin
|
56
|
+
task = self.new
|
57
|
+
task.run(opts)
|
58
|
+
rescue NodeTask::Error => e
|
59
|
+
raise self::Error.new(e)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task_duration_ms = task_duration * 1000
|
65
|
+
if defined?(Rails) && task_duration_ms > 10
|
66
|
+
Rails.logger.info("Webpack: #{task_duration_ms.round(0)}ms")
|
67
|
+
end
|
68
|
+
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def _make_working_dir
|
75
|
+
# one node_task daemon will be created per unique working dir
|
76
|
+
wd = File.join(root_dir, 'tmp', 'webpack', 'task')
|
77
|
+
FileUtils.mkpath(wd)
|
78
|
+
wd
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize
|
83
|
+
super(self.class.webpack_task_script)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
var webpack = require('webpack');
|
2
|
+
var fs = require('fs');
|
3
|
+
var path = require('path');
|
4
|
+
|
5
|
+
var logging = true;
|
6
|
+
function log(message) {
|
7
|
+
if (logging) fs.appendFile('log/webpack-task.log', message+'\n');
|
8
|
+
}
|
9
|
+
|
10
|
+
// TODO: add support for multiple builds using multiple webpack configs which
|
11
|
+
// can each be waited upon independently
|
12
|
+
var webpackConfig = require(path.resolve('config/webpack.config.js'));
|
13
|
+
|
14
|
+
// webpack Compiler.Watching instance
|
15
|
+
var watcher = makeWatcher();
|
16
|
+
// callbacks which will be called when next build completes
|
17
|
+
var currentBuildCallbacks = [];
|
18
|
+
// object with property 'stats' for success or 'error' for failure
|
19
|
+
var lastBuildResult = null;
|
20
|
+
|
21
|
+
function buildComplete(buildResult) {
|
22
|
+
lastBuildResult = buildResult;
|
23
|
+
|
24
|
+
currentBuildCallbacks.forEach(function(callback) {
|
25
|
+
log('async completion callback');
|
26
|
+
callback(buildResult);
|
27
|
+
});
|
28
|
+
currentBuildCallbacks = [];
|
29
|
+
|
30
|
+
fs.writeFile('tmp/webpack/webpack-build-result.json', JSON.stringify(buildResult, null, 2));
|
31
|
+
}
|
32
|
+
|
33
|
+
function makeWatcher() {
|
34
|
+
return webpack(webpackConfig).watch({
|
35
|
+
aggregateTimeout: 300, // wait so long for more changes
|
36
|
+
}, function(err, stats) {
|
37
|
+
if (err) {
|
38
|
+
buildComplete({
|
39
|
+
error: err,
|
40
|
+
});
|
41
|
+
} else if (stats.hasErrors()) {
|
42
|
+
var errWithDetails = new Error('Webpack build error');
|
43
|
+
errWithDetails.stack = (
|
44
|
+
'Webpack build error:\n' +
|
45
|
+
stats.toJson({errorDetails: true}).errors.join("\n") + ''
|
46
|
+
// err ? '\nOriginal stacktrace:\n' + (err.stack || err) : ''
|
47
|
+
);
|
48
|
+
|
49
|
+
buildComplete({
|
50
|
+
error: errWithDetails,
|
51
|
+
});
|
52
|
+
} else {
|
53
|
+
var statsData = stats.toJson({
|
54
|
+
hash: true,
|
55
|
+
assets: true,
|
56
|
+
modules: true,
|
57
|
+
chunkOrigins: true,
|
58
|
+
cached: true,
|
59
|
+
});
|
60
|
+
|
61
|
+
var modules = statsData.modules.map(function(moduleStats) {
|
62
|
+
var loadersEnd = moduleStats.identifier.lastIndexOf('!')
|
63
|
+
return moduleStats.identifier.slice(loadersEnd == -1 ? 0 : loadersEnd+1)
|
64
|
+
})
|
65
|
+
|
66
|
+
buildComplete({
|
67
|
+
// stats: statsData,
|
68
|
+
modules: modules,
|
69
|
+
});
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
|
74
|
+
module.exports = function waitForBuild(opts, done) {
|
75
|
+
function sendResults(buildResult) {
|
76
|
+
if (buildResult.error) done(buildResult.error);
|
77
|
+
else done(null, buildResult);
|
78
|
+
}
|
79
|
+
|
80
|
+
log('watcher.running: '+JSON.stringify(watcher.running));
|
81
|
+
|
82
|
+
if (!watcher.running) {
|
83
|
+
sendResults(lastBuildResult);
|
84
|
+
} else {
|
85
|
+
currentBuildCallbacks.push(sendResults);
|
86
|
+
}
|
87
|
+
};
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webpack_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Friend
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: node_task
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.0
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.0
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: tilt
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.1'
|
47
|
+
description: Much longer explanation of the webpack_rails!
|
48
|
+
email: james@jsdf.co
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/webpack_rails.rb
|
54
|
+
- lib/webpack_rails/engine.rb
|
55
|
+
- lib/webpack_rails/processor.rb
|
56
|
+
- lib/webpack_rails/sprockets_base_webpack.rb
|
57
|
+
- lib/webpack_rails/sprockets_index_webpack.rb
|
58
|
+
- lib/webpack_rails/task.rb
|
59
|
+
- lib/webpack_rails/webpack-task.js
|
60
|
+
homepage: https://rubygems.org/gems/webpack_rails
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.2.2
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: This is an webpack_rails!
|
84
|
+
test_files: []
|