Skip to content

Commit b8e3873

Browse files
authored
Cache test pack compilation (#539)
* Cache test pack compilation Update changelog Fix test Update webpacker Fix wordings Change method name for clarity Update readme Remove webpack-dev-server bit for now Update toc Add tests for new configuration Move configuration to compiler class and make it configurable programmatically Fix readme Only run compiler in test env Add compiler test Change method name Remove Rails.root Use stub Rename to compile and update syntax Update changelog Revert escaping * Update changelog * Setup source path from config file
1 parent 37a616e commit b8e3873

10 files changed

+120
-22
lines changed

CHANGELOG.md

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,32 @@
44
- Update `webpack-dev-server.tt` to respect RAILS_ENV and NODE_ENV values [#502](https://github.com/rails/webpacker/issues/502)
55

66
### Breaking changes
7-
- Add `compile_missing_packs` option to `config/webpacker.yml` for configuring lazy compilation of packs when not found [#503](https://github.com/rails/webpacker/pull/503). To enable expected behavior for defaults and production, update `config/webpacker.yml`:
7+
- Add `compile` option to `config/webpacker.yml` for configuring lazy compilation of packs when a file under tracked paths is changed [#503](https://github.com/rails/webpacker/pull/503). To enable expected behavior, update `config/webpacker.yml`:
88

99
```yaml
1010
default: &default
11-
compile_missing_packs: true
11+
compile: false
1212

13-
production:
14-
compile_missing_packs: false
13+
test:
14+
compile: true
15+
16+
development:
17+
compile: true
18+
```
19+
20+
- Make test compilation cacheable and configurable so that the lazy compilation
21+
only triggers if files are changed under tracked paths.
22+
Following paths are watched by default -
23+
24+
```rb
25+
["app/javascript/**/*", "yarn.lock", "package.json", "config/webpack/**/*"]
26+
```
27+
28+
To add more paths:
29+
30+
```rb
31+
# config/initializers/webpacker.rb or config/application.rb
32+
Webpacker::Compiler.watched_paths << 'bower_components'
1533
```
1634

1735
## [2.0] - 2017-05-24

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
webpacker (1.2)
4+
webpacker (2.0)
55
activesupport (>= 4.2)
66
multi_json (~> 1.2)
77
railties (>= 4.2)

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ in which case you may not even need the asset pipeline. This is mostly relevant
2424
- [React](#react)
2525
- [Angular with TypeScript](#angular-with-typescript)
2626
- [Vue](#vue)
27+
- [Using Rails helpers in .vue files](#using-rails-helpers-in-vue-files)
2728
- [Elm](#elm)
2829
- [Binstubs](#binstubs)
2930
- [Webpack dev server](#webpack-dev-server)
@@ -63,6 +64,8 @@ in which case you may not even need the asset pipeline. This is mostly relevant
6364
- [Deployment](#deployment)
6465
- [Heroku](#heroku)
6566
- [Testing](#testing)
67+
- [Lazy compilation](#lazy-compilation)
68+
- [Caching](#caching)
6669
- [Troubleshooting](#troubleshooting)
6770
- [ENOENT: no such file or directory - node-sass](#enoent-no-such-file-or-directory---node-sass)
6871
- [Can't find hello_react.js in manifest.json](#cant-find-hello_reactjs-in-manifestjson)
@@ -1060,9 +1063,12 @@ git push heroku master
10601063

10611064
## Testing
10621065

1066+
### Lazy compilation
1067+
10631068
Webpacker lazily compiles assets in test env so you can write your tests without any extra
10641069
setup and everything will just work out of the box.
10651070

1071+
10661072
Here is a sample system test case with hello_react example component:
10671073

10681074
```js
@@ -1101,6 +1107,25 @@ class HomesTest < ApplicationSystemTestCase
11011107
end
11021108
```
11031109

1110+
#### Caching
1111+
1112+
By default, the lazy compilation is cached until a file is changed under
1113+
tracked paths. You can configure the paths tracked
1114+
by adding new paths to `watched_paths` array, much like rails `autoload_paths`:
1115+
1116+
```rb
1117+
# config/initializers/webpacker.rb
1118+
# or config/application.rb
1119+
Webpacker::Compiler.watched_paths << 'bower_components'
1120+
```
1121+
1122+
Compiler stores a timestamp under `tmp/webpacker/` directory to keep track of
1123+
changes and you can configure that by overriding compiler `cache_dir`:
1124+
1125+
```rb
1126+
Webpacker::Compiler.cache_dir = "tmp/foo"
1127+
```
1128+
11041129
## Troubleshooting
11051130

11061131
##### ENOENT: no such file or directory - node-sass

lib/install/config/webpacker.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ default: &default
44
source_path: app/javascript
55
source_entry_path: packs
66
public_output_path: packs
7-
compile_missing_packs: true
7+
compile: false
88

99
extensions:
1010
- .coffee
@@ -34,8 +34,8 @@ test:
3434
<<: *default
3535

3636
public_output_path: packs-test
37+
# Compile webpack assets during lookup when running tests
38+
compile: true
3739

3840
production:
3941
<<: *default
40-
41-
compile_missing_packs: false

lib/webpacker/compiler.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,47 @@
33
module Webpacker::Compiler
44
extend self
55

6+
# Additional paths that test compiler needs to watch
7+
# Webpacker::Compiler.watched_paths << 'bower_components'
8+
mattr_accessor(:watched_paths) { [] }
9+
10+
# Compiler cache directory
11+
# Webpacker::Compiler.cache_dir = 'tmp/cache'
12+
mattr_accessor(:cache_dir) { "tmp/webpacker" }
13+
614
def compile
15+
return unless compile?
16+
cache_source_timestamp
717
compile_task.invoke
818
compile_task.reenable
919
end
1020

21+
def compile?
22+
return true unless File.exist?(cached_timestamp_path)
23+
return true unless File.exist?(Webpacker::Configuration.output_path)
24+
25+
File.read(cached_timestamp_path) != current_source_timestamp
26+
end
27+
28+
def default_watched_paths
29+
["#{Webpacker::Configuration.source}/**/*", "yarn.lock", "package.json", "config/webpack/**/*"].freeze
30+
end
31+
1132
private
33+
def current_source_timestamp
34+
files = Dir[*default_watched_paths, *watched_paths].reject { |f| File.directory?(f) }
35+
files.map { |f| File.mtime(f).utc.to_i }.max.to_s
36+
end
37+
38+
def cache_source_timestamp
39+
File.write(cached_timestamp_path, current_source_timestamp)
40+
end
41+
42+
def cached_timestamp_path
43+
FileUtils.mkdir_p(cache_dir) unless File.directory?(cache_dir)
44+
Rails.root.join(cache_dir, ".compiler-timestamp")
45+
end
46+
1247
def compile_task
1348
@compile_task ||= load_rake_task("webpacker:compile")
1449
end

lib/webpacker/configuration.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ def source
3636
fetch(:source_path)
3737
end
3838

39-
def compile_missing_packs?
40-
fetch(:compile_missing_packs)
39+
def compile?
40+
fetch(:compile)
4141
end
4242

4343
def fetch(key)
@@ -51,7 +51,7 @@ def data
5151
end
5252

5353
def defaults
54-
@defaults ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)["default"])
54+
@defaults ||= HashWithIndifferentAccess.new(YAML.load(default_file_path.read)[Webpacker.env])
5555
end
5656
end
5757

lib/webpacker/manifest.rb

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ def file_path
1414
end
1515

1616
def lookup(name)
17-
load if Webpacker.env.development?
18-
19-
if Webpacker::Configuration.compile_missing_packs?
20-
find(name) || compile_and_find!(name)
17+
if Webpacker::Configuration.compile?
18+
compile_and_find!(name)
2119
else
2220
find!(name)
2321
end
@@ -28,10 +26,6 @@ def lookup_path(name)
2826
end
2927

3028
private
31-
def find(name)
32-
instance.data[name.to_s] if instance
33-
end
34-
3529
def find!(name)
3630
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Manifest.load must be called first") unless instance
3731
instance.data[name.to_s] || raise(Webpacker::FileLoader::NotFoundError.new("Can't find #{name} in #{file_path}. Is webpack still compiling?"))

test/compiler_test.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require "webpacker_test"
2+
3+
class CompilerTest < Minitest::Test
4+
def test_default_watched_paths
5+
assert_equal Webpacker::Compiler.default_watched_paths, ["app/javascript/**/*", "yarn.lock", "package.json", "config/webpack/**/*"]
6+
end
7+
8+
def test_empty_watched_paths
9+
assert_equal Webpacker::Compiler.watched_paths, []
10+
end
11+
12+
def test_watched_paths
13+
Webpacker::Compiler.stub :watched_paths, ["Gemfile"] do
14+
assert_equal Webpacker::Compiler.watched_paths, ["Gemfile"]
15+
end
16+
end
17+
18+
def test_cache_dir
19+
assert_equal Webpacker::Compiler.cache_dir, "tmp/webpacker"
20+
end
21+
22+
def test_compile?
23+
assert Webpacker::Compiler.compile?
24+
end
25+
end

test/configuration_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_source_path
3030
assert_equal Webpacker::Configuration.source_path.to_s, source_path
3131
end
3232

33-
def test_compile_missing_packs
34-
assert Webpacker::Configuration.compile_missing_packs?
33+
def test_compile?
34+
refute Webpacker::Configuration.compile?
3535
end
3636
end

test/manifest_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ def test_lookup_exception
1010
manifest_path = File.join(File.dirname(__FILE__), "test_app/public/packs", "manifest.json").to_s
1111
asset_file = "calendar.js"
1212

13-
Webpacker::Configuration.stub :compile_missing_packs?, false do
13+
Webpacker::Configuration.stub :compile?, false do
1414
error = assert_raises Webpacker::FileLoader::NotFoundError do
1515
Webpacker::Manifest.lookup(asset_file)
1616
end
17+
1718
assert_equal error.message, "Can't find #{asset_file} in #{manifest_path}. Is webpack still compiling?"
1819
end
1920
end

0 commit comments

Comments
 (0)