Skip to content

Commit

Permalink
Merge pull request #668 from jessecollier/jcollier/add-depend-on-dire…
Browse files Browse the repository at this point in the history
…ctory

Adding directive depends_on_directory
  • Loading branch information
rafaelfranca committed Jun 23, 2022
2 parents fa8a968 + 55957f2 commit 796fb82
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 7 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
## Master

- Fix `Sprockets::Server` to return lower-cased response headers to comply with Rack::Lint 3.0. [#744](https://github.com/rails/sprockets/pull/744)
- Adding new directive `depend_on_directory` [#668](https://github.com/rails/sprockets/pull/668)
- Fix `application/js-sourcemap+json` charset [#669](https://github.com/rails/sprockets/pull/669)
- Fix `CachedEnvironment` caching nil values [#723](https://github.com/rails/sprockets/pull/723)

## 4.0.3

Expand All @@ -13,7 +16,6 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
- Allow assets already fingerprinted to be served through `Sprockets::Server`
- Do not fingerprint files that already contain a valid digest in their name
- Remove remaining support for Ruby < 2.4.[#672](https://github.com/rails/sprockets/pull/672)
- Fix `CachedEnvironment` caching nil values [#723](https://github.com/rails/sprockets/pull/723)

## 4.0.2

Expand All @@ -22,7 +24,6 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprocket
## 4.0.1

- Fix for Ruby 2.7 keyword arguments warning in `base.rb`. [#660](https://github.com/rails/sprockets/pull/660)
- Fix `application/js-sourcemap+json` charset [#669](https://github.com/rails/sprockets/pull/669)
- Fix for when `x_sprockets_linecount` is missing from a source map.
- Fix subresource integrity to match the digest of the asset.

Expand Down
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Here is a list of the available directives:
- [`link_directory`](#link_directory) - Make target directory compile and be publicly available without adding contents to current
- [`link_tree`](#link_tree) - Make target tree compile and be publicly available without adding contents to current
- [`depend_on`](#depend_on) - Recompile current file if target has changed
- [`depend_on_directory`](#depend_on_directory) - Recompile current file if any files in target directory has changed
- [`stub`](#stub) - Ignore target file

You can see what each of these does below.
Expand Down Expand Up @@ -239,7 +240,7 @@ The first time this file is compiled the `application.js` output will be written

So, if `b.js` changes it will get recompiled. However instead of having to recompile the other files from `a.js` to `z.js` since they did not change, we can use the prior intermediary files stored in the cached values . If these files were expensive to generate, then this "partial" asset cache strategy can save a lot of time.

Directives such as `require`, `link`, and `depend_on` tell Sprockets what assets need to be re-compiled when a file changes. Files are considered "fresh" based on their mtime on disk and a combination of cache keys.
Directives such as `require`, `link`, `depend_on`, and `depend_on_directory` tell Sprockets what assets need to be re-compiled when a file changes. Files are considered "fresh" based on their mtime on disk and a combination of cache keys.

On Rails you can force a "clean" install by clearing the `public/assets` and `tmp/cache/assets` directories.

Expand Down Expand Up @@ -453,11 +454,53 @@ you need to tell sprockets that it needs to re-compile the file if `bar.data` ch
var bar = '<%= File.read("bar.data") %>'
```

To depend on an entire directory containing multiple files, use `depend_on_directory`

### depend_on_asset

`depend_on_asset` *path* works like `depend_on`, but operates
recursively reading the file and following the directives found. This is automatically implied if you use `link`, so consider if it just makes sense using `link` instead of `depend_on_asset`.

### depend_on_directory

`depend_on_directory` *path* declares all files in the given *path* without
including them in the bundle. This is useful when you need to expire an
asset's cache in response to a change in multiple files in a single directory.

All paths are relative to your declaration and must begin with `./`

Also, your must include these directories in your [load path](guides/building_an_asset_processing_framework.md#the-load-path).

**Example:**

If we've got a directory called `data` with files `a.data` and `b.data`

```
// ./data/a.data
A
```

```
// ./data/b.data
B
```

```
// ./file.js.erb
//= depend_on_directory ./data
var a = '<% File.read('data/a.data') %>'
var b = '<% File.read('data/b.data') %>'
```

Would produce:

```js
var a = "A";
var b = "B";
```

You can also see [Index files are proxies for folders](#index-files-are-proxies-for-folders) for another method of organizing folders that will give you more control.

### stub

`stub` *path* excludes that asset and its dependencies from the asset bundle.
Expand Down Expand Up @@ -499,9 +542,9 @@ When you modify the `logo.png` on disk, it will force `application.css` to be
recompiled so that the fingerprint will be correct in the generated asset.

You can manually make sprockets depend on any other file that is generated
by sprockets by using the `depend_on` directive. Rails implements the above
feature by auto calling `depend_on` on the original asset when the `asset_url`
is used inside of an asset.
by sprockets by using the `depend_on` or `depend_on_directory` directive. Rails
implements the above feature by auto calling `depend_on` on the original asset
when the `asset_url` is used inside of an asset.

### Styling with Sass and SCSS

Expand Down
20 changes: 19 additions & 1 deletion lib/sprockets/directive_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,24 @@ def process_depend_on_asset_directive(path)
to_load(resolve(path))
end

# Allows you to state a dependency on a relative directory
# without including it.
#
# This is used for caching purposes. Any changes made to
# the dependency directory will invalidate the cache of the
# source file.
#
# This is useful if you are using ERB and File.read to pull
# in contents from multiple files in a directory.
#
# //= depend_on_directory ./data
#
def process_depend_on_directory_directive(path = ".", accept = nil)
path = expand_relative_dirname(:depend_on_directory, path)
accept = expand_accept_shorthand(accept)
resolve_paths(*@environment.stat_directory_with_dependencies(path), accept: accept)
end

# Allows dependency to be excluded from the asset bundle.
#
# The `path` must be a valid asset and may or may not already
Expand Down Expand Up @@ -374,7 +392,7 @@ def resolve_paths(paths, deps, **kargs)
next if subpath == @filename || stat.directory?
uri, deps = @environment.resolve(subpath, **kargs)
@dependencies.merge(deps)
yield uri if uri
yield uri if uri && block_given?
end
end

Expand Down
44 changes: 44 additions & 0 deletions test/test_asset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,50 @@ def self.test(name, &block)
end
end
end

test "modify asset's dependency file in directory" do
main = fixture_path('asset/test-main.js.erb')
dep = fixture_path('asset/data/foo.txt')
begin
::FileUtils.mkdir File.dirname(dep)
sandbox main, dep do
write(main, "//= depend_on_directory ./data\n<%= File.read('#{dep}') %>")
write(dep, "a;")
asset = asset('test-main.js')
old_digest = asset.hexdigest
old_uri = asset.uri
assert_equal "a;\n", asset.to_s

write(dep, "b;")
asset = asset('test-main.js')
refute_equal old_digest, asset.hexdigest
refute_equal old_uri, asset.uri
assert_equal "b;\n", asset.to_s
end
ensure
::FileUtils.rmtree File.dirname(dep)
end
end

test "asset's dependency on directory exists" do
main = fixture_path('asset/test-missing-directory.js.erb')
dep = fixture_path('asset/data/foo.txt')

begin
sandbox main, dep do
::FileUtils.rmtree File.dirname(dep)
write(main, "//= depend_on_directory ./data")
assert_raises(Sprockets::ArgumentError) do
asset('test-missing-directory.js')
end

::FileUtils.mkdir File.dirname(dep)
assert asset('test-missing-directory.js')
end
ensure
::FileUtils.rmtree File.dirname(dep)
end
end
end

class TextStaticAssetTest < Sprockets::TestCase
Expand Down

0 comments on commit 796fb82

Please sign in to comment.