breakfast 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 55fe92f6b48d4ee747f50fc3a831d0863723e6bd
4
- data.tar.gz: 9a123637c58184758187ee44848f435a027d6910
3
+ metadata.gz: f9efb82f14ced85f239814ee2c1433b33f84cda1
4
+ data.tar.gz: ee25eca42d5a7358d824f7f5b533f6ca755e63b0
5
5
  SHA512:
6
- metadata.gz: d361f652699abef3b4a145ff06370860c08552240830fb338e2fbfe399d769141de8a803c14859c91585cf15084ce92ca80c48ea2a70787a428bcf34e308ed68
7
- data.tar.gz: 901bb0ece81ea661d5871ab62b8d2228fdfc68466faf99e66dbf1ab024f48196e7792a17d0fd1bf390573476b4755776f0be997347e47fd96e790c9f861c2b6d
6
+ metadata.gz: 62cdcdf0e004938f9d672cf8dc1d700f7b2aee6416617283611767e34ae9cbf99d8396e7de82fe75cb2b94c0891c0268c42f03cd58c6ff4c76901d00e9569077
7
+ data.tar.gz: e3ed59e5fc4c426d6c342427c3e6251ff1dba14e735def521dc19c6bb747fdb0bbae596c4670b443a3c041353abb29aa40a93608ecc7ad49f5e7b832b6b10328
@@ -1,9 +1,59 @@
1
1
  # CHANGE LOG
2
2
 
3
+ ### 0.4.0 - 2016-11-14
4
+ #### Upgrading to `0.4.0` from `0.3.0`
5
+ - Update gem with `bundle update breakfast`
6
+ - Bump the `breakfast-rails` version in `package.json` to `0.4.0`
7
+ - Run `npm install`
8
+
9
+ *Note* Now by default asset fingerprinting will be on by default in production.
10
+ A copy of each with the original filename will be present as well, so any
11
+ hard-coded links to assets will still work correctly.
12
+
13
+ #### Added
14
+ - Asset Digests. Now when deploying assets will have fingerprints added to their
15
+ file names. This allows browsers to aggressively cache your assets.
16
+ - New Option: `breakfast.manifest.digest`. Defaults to false in development /
17
+ test and true everywhere else. When true, enables Rails to serve fingerprinted
18
+ assets.
19
+ - Rake Commands to trigger certain behavior:
20
+ - `breakfast:assets:build`
21
+ Manually run a compilation step.
22
+ - `breakfast:assets:build_production`
23
+ Manually trigger a production build. This will cause assets to get minified.
24
+ - `breakfast:assets:digest`
25
+ Run through your compiled assets and add a fingerprint to each one. Creates
26
+ a copy, leaving a file with the original filename and a duplicate with an
27
+ md5 fingerprint.
28
+ - `breakfast:assets:clean`
29
+ Removes any assets from the output folder that are not specified in the
30
+ manifest file (removes out of date files).
31
+ - `breakfast:assets:nuke`
32
+ Removes manifest and fingerprinted assets from the output folder.
33
+ - New Capistrano Option: `:breakfast_npm_install_command`
34
+ Defaults to just `install`. Can be overridden to redirect output to dev/null.
35
+ Example:
36
+
37
+ ```
38
+ set :breakfast_npm_install_command, "install > /dev/null 2>&1"
39
+ ```
40
+
41
+ #### Changes
42
+ - Fixed small CSS issue if box-sizing is not set border-box globally.
43
+
44
+
45
+ #### Contributors
46
+ Many many thanks to the contributors for this release!
47
+ - [@patkoperwas](https://github.com/patkoperwas)
48
+ - [@mikeastock](https://github.com/mikeastock)
49
+ - [@HParker](https://github.com/HParker)
50
+
51
+
3
52
  ## 0.3.1 - 2016-10-19
4
53
  - Better support for determining if Server is running. Using puma, passneger,
5
54
  etc. instead of the default rails server command now work.
6
55
 
56
+
7
57
  ## 0.3.0 - 2016-09-28
8
58
 
9
59
  ### Upgrading from `0.2.0`
data/README.md CHANGED
@@ -15,46 +15,48 @@ See the official docs at
15
15
 
16
16
  View updates in the [CHANGELOG](https://github.com/devlocker/breakfast/blob/master/CHANGELOG.md)
17
17
 
18
- ### Latest Patch `0.3.1`
19
- - Allows Breakfast to run when Rails is started outside of bin/rails server,
20
- i.e. bundle exec puma, passenger, thin, etc.
21
-
22
- ### Latest Release `0.3.0`
18
+ ### Latest Release `0.4.0`
23
19
  #### Added
24
- - New status bar that allows the user to switch reload strategies on the fly
25
- - Support for Haml & Slim files (without .html extension)
26
- - Reloading on ruby file changes.
27
- - Specify minimum Node & NPM versions when installing (avoid awkward and none
28
- descriptive error messages)
29
- - NPM binary path for Capistrano
20
+ - Asset Digests. Now when deploying assets will have fingerprints added to their
21
+ file names. This allows browsers to aggressively cache your assets.
22
+ - New Option: `breakfast.manifest.digest`. Defaults to false in development /
23
+ test and true everywhere else. When true, enables Rails to serve fingerprinted
24
+ assets.
25
+ - Rake Commands to trigger certain behavior:
26
+ - `breakfast:assets:build`
27
+ Manually run a compilation step.
28
+ - `breakfast:assets:build_production`
29
+ Manually trigger a production build. This will cause assets to get minified.
30
+ - `breakfast:assets:digest`
31
+ Run through your compiled assets and add a fingerprint to each one. Creates
32
+ a copy, leaving a file with the original filename and a duplicate with an
33
+ md5 fingerprint.
34
+ - `breakfast:assets:clean`
35
+ Removes any assets from the output folder that are not specified in the
36
+ manifest file (removes out of date files).
37
+ - `breakfast:assets:nuke`
38
+ Removes manifest and fingerprinted assets from the output folder.
39
+ - New Capistrano Option: `:breakfast_npm_install_command`
40
+ Defaults to just `install`. Can be overridden to redirect output to dev/null.
41
+ Example:
30
42
 
31
- #### Changes
32
- - config.breakfast.view_folders change to config.breakfast.source_code_folders.
33
- Change brought about by need to trigger reloads when Ruby source code changes.
43
+ ```
44
+ set :breakfast_npm_install_command, "install > /dev/null 2>&1"
45
+ ```
34
46
 
35
- #### Removed
36
- - config.breakfast.view_folders is no longer supported. Deprecated in favor of
37
- source_code_folders option.
47
+ #### Changes
48
+ - Fixed small CSS issue if box-sizing is not set border-box globally.
38
49
 
39
50
 
40
51
  ### Upgrading
41
- #### Upgrading to `0.3.0` from `0.2.0`
52
+ #### Upgrading to `0.4.0` from `0.3.0`
42
53
  - Update gem with `bundle update breakfast`
43
- - Bump the `breakfast-rails` version in `package.json` to `0.3.1`
54
+ - Bump the `breakfast-rails` version in `package.json` to `0.4.0`
44
55
  - Run `npm install`
45
- - If you have modified the `config.breakfast.view_folders` option you will need
46
- to replace it. The new option is `config.breakfast.source_code_folders` and it
47
- defaults to `[Rails.root.join("app")]`. If you have view or Ruby files that
48
- you would like to trigger reloads outside of the `app` folder then append
49
- those paths by adding:
50
-
51
- ```
52
- config.breakfast.source_code_folders << Rails.root.join("lib")
53
- ```
54
-
55
- To which ever environment you want `Breakfast` to run in
56
- (probably `config/environments/development.rb`).
57
56
 
57
+ *Note* Now by default asset fingerprinting will be on by default in production.
58
+ A copy of each with the original filename will be present as well, so any
59
+ hard-coded links to assets will still work correctly.
58
60
 
59
61
  ### Contributing
60
62
  Bug reports and pull requests are welcome on GitHub at
@@ -1,13 +1,17 @@
1
1
  require "breakfast/version"
2
+
3
+ require "breakfast/brunch_watcher"
4
+ require "breakfast/compilation_listener"
2
5
  require "breakfast/live_reload_channel"
6
+ require "breakfast/manifest"
3
7
  require "breakfast/status_channel"
4
8
  require "breakfast/view_helper"
5
- require "breakfast/brunch_watcher"
6
- require "breakfast/compilation_listener"
7
9
 
8
10
  module Breakfast
9
11
  STATUS_CHANNEL = "breakfast_status".freeze
10
12
  RELOAD_CHANNEL = "breakfast_live_reload".freeze
13
+ BUILD_COMMAND = "./node_modules/brunch/bin/brunch build".freeze
14
+ PRODUCTION_BUILD_COMMAND = "./node_modules/brunch/bin/brunch build --production".freeze
11
15
  end
12
16
 
13
17
  require "breakfast/railtie" if defined?(Rails)
@@ -1,6 +1,6 @@
1
- require 'capistrano/version'
1
+ require "capistrano/version"
2
2
 
3
- if defined?(Capistrano::VERSION) && Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
3
+ if defined?(Capistrano::VERSION) && Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new("3.0.0")
4
4
  load File.expand_path("../capistrano/tasks/breakfast.rake", __FILE__)
5
5
  else
6
6
  raise "Requires Capistrano V3"
@@ -3,13 +3,28 @@ namespace :breakfast do
3
3
  task :compile do
4
4
  on roles fetch(:breakfast_roles) do |host|
5
5
  within release_path do
6
- execute fetch(:breakfast_npm_path).to_sym, "install"
7
- execute "node_modules/brunch/bin/brunch", "build --production"
6
+ with rails_env: "#{fetch(:rails_env) || fetch(:stage)}" do
7
+ execute fetch(:breakfast_npm_path).to_sym, fetch(:breakfast_npm_install_command)
8
+ execute :rails, "breakfast:assets:build_production"
9
+ execute :rails, "breakfast:assets:digest"
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ desc "Clean out old assets"
16
+ task :clean do
17
+ on roles fetch(:breakfast_roles) do |host|
18
+ within release_path do
19
+ with rails_env: "#{fetch(:rails_env) || fetch(:stage)}" do
20
+ execute :rails, "breakfast:assets:clean"
21
+ end
8
22
  end
9
23
  end
10
24
  end
11
25
 
12
26
  after "deploy:updated", "breakfast:compile"
27
+ after "deploy:published", "breakfast:clean"
13
28
  end
14
29
 
15
30
 
@@ -17,5 +32,6 @@ namespace :load do
17
32
  task :defaults do
18
33
  set :breakfast_roles, -> { :web }
19
34
  set :breakfast_npm_path, "/usr/bin/npm"
35
+ set :breakfast_npm_install_command, "install"
20
36
  end
21
37
  end
@@ -3,9 +3,9 @@ module Breakfast
3
3
  ASSET_EXTENSIONS = ["css", "js"].freeze
4
4
  SOURCE_CODE_EXTENSIONS = ["rb", "html", "haml", "slim"].freeze
5
5
 
6
- def self.start(asset_output_folders:, source_code_folders:)
7
- asset_listener =
8
- ::Listen.to(*asset_output_folders) do |modified, added, removed|
6
+ def self.start(asset_output_folder:, source_code_folders:)
7
+ asset_listener =
8
+ ::Listen.to(asset_output_folder) do |modified, added, removed|
9
9
  files = modified + added + removed
10
10
 
11
11
  ASSET_EXTENSIONS.each do |extension|
@@ -15,7 +15,7 @@ module Breakfast
15
15
  end
16
16
  end
17
17
 
18
- rails_listener =
18
+ rails_listener =
19
19
  ::Listen.to(*source_code_folders) do |modified, added, removed|
20
20
  files = modified + added + removed
21
21
 
@@ -0,0 +1,115 @@
1
+ require "json"
2
+ require "digest"
3
+ require "fileutils"
4
+
5
+ module Breakfast
6
+ class Manifest
7
+ MANIFEST_REGEX = /^\.breakfast-manifest-[0-9a-f]{32}.json$/
8
+ SPROCKETS_MANIFEST_REGEX = /^\.sprockets-manifest-[0-9a-f]{32}.json$/
9
+ FINGERPRINT_REGEX = /-[0-9a-f]{32}./
10
+
11
+ attr_reader :base_dir, :manifest_path, :cache
12
+ def initialize(base_dir:)
13
+ FileUtils.mkdir_p(base_dir)
14
+
15
+ @base_dir = Pathname.new(base_dir)
16
+ @manifest_path = find_manifest_or_create
17
+ @cache = update_cache!
18
+ end
19
+
20
+ def asset(path)
21
+ cache[path]
22
+ end
23
+
24
+ # The #digest! method will run through all of the compiled assets and
25
+ # create a copy of each asset with a digest fingerprint. This fingerprint
26
+ # will change whenever the file contents change. This allows us to use HTTP
27
+ # headers to cache these assets as we will be able to reliably know when
28
+ # they change.
29
+ #
30
+ # These fingerprinted files are copies of the original. The originals are
31
+ # not removed and still available should the need arise to serve a
32
+ # non-fingerprinted asset.
33
+ #
34
+ # Example manifest:
35
+ # {
36
+ # app.js => app-76c6ee161ba431e823301567b175acda.js,
37
+ # images/logo.png => images/logo-869269cdf1773ff0dec91bafb37310ea.png,
38
+ # }
39
+ #
40
+ # Resulting File Structure:
41
+ # - /
42
+ # - app.js
43
+ # - app-76c6ee161ba431e823301567b175acda.js
44
+ # - images/
45
+ # - logo.png
46
+ # - logo-869269cdf1773ff0dec91bafb37310ea.png
47
+ def digest!
48
+ assets = asset_paths.map do |path|
49
+ digest = Digest::MD5.new
50
+ digest.update(File.read("#{base_dir}/#{path}"))
51
+
52
+ digest_path = "#{path.sub_ext('')}-#{digest.hexdigest}#{File.extname(path)}"
53
+
54
+ FileUtils.cp("#{base_dir}/#{path}", "#{base_dir}/#{digest_path}")
55
+
56
+ [path, digest_path]
57
+ end
58
+
59
+ File.open(manifest_path, "w") do |manifest|
60
+ manifest.write(assets.to_h.to_json)
61
+ end
62
+
63
+ update_cache!
64
+ end
65
+
66
+ # Remove any files not directly referenced by the manifest.
67
+ def clean!
68
+ files_to_keep = cache.keys.concat(cache.values)
69
+
70
+ if (sprockets_manifest = Dir.entries("#{base_dir}").detect { |entry| entry =~ SPROCKETS_MANIFEST_REGEX })
71
+ files_to_keep.concat(JSON.parse(File.read("#{base_dir}/#{sprockets_manifest}"))["files"].keys)
72
+ end
73
+
74
+ Dir["#{base_dir}/**/*"].each do |path|
75
+ next if File.directory?(path) || files_to_keep.include?(Pathname(path).relative_path_from(base_dir).to_s)
76
+
77
+ FileUtils.rm(path)
78
+ end
79
+ end
80
+
81
+ # Remove manifest, any fingerprinted files.
82
+ def nuke!
83
+ Dir["#{base_dir}/**/*"]
84
+ .select { |path| path =~ FINGERPRINT_REGEX }
85
+ .each { |file| FileUtils.rm(file) }
86
+
87
+ FileUtils.rm(manifest_path)
88
+ end
89
+
90
+ private
91
+
92
+ def update_cache!
93
+ @cache = JSON.parse(File.read(manifest_path))
94
+ end
95
+
96
+ # Creates a or finds a manifest file in a given directory. The manifest
97
+ # file is is prefixed with a dot ('.') and given a random string to ensure
98
+ # the file is not served or easily discoverable.
99
+ def find_manifest_or_create
100
+ if (manifest = Dir.entries("#{base_dir}").detect { |entry| entry =~ MANIFEST_REGEX })
101
+ "#{base_dir}/#{manifest}"
102
+ else
103
+ manifest = "#{base_dir}/.breakfast-manifest-#{SecureRandom.hex(16)}.json"
104
+ File.open(manifest, "w") { |manifest| manifest.write({}.to_json) }
105
+ manifest
106
+ end
107
+ end
108
+
109
+ def asset_paths
110
+ Dir["#{base_dir}/**/*"]
111
+ .reject { |path| File.directory?(path) || path =~ FINGERPRINT_REGEX }
112
+ .map { |file| Pathname(file).relative_path_from(base_dir) }
113
+ end
114
+ end
115
+ end
@@ -11,10 +11,11 @@ module Breakfast
11
11
  config.breakfast.css_reload_strategy = :hot
12
12
  config.breakfast.ruby_reload_strategy = :off
13
13
 
14
- config.breakfast.asset_output_folders = [Rails.root.join("public")]
14
+ config.breakfast.asset_output_folder = Rails.root.join("public", "assets")
15
15
  config.breakfast.source_code_folders = [Rails.root.join("app")]
16
16
  config.breakfast.environments = %w(development)
17
17
  config.breakfast.status_bar_location = :bottom
18
+ config.breakfast.digest = !(Rails.env.development? || Rails.env.test?)
18
19
  end
19
20
 
20
21
  initializer "breakfast.setup_view_helpers" do |app|
@@ -23,14 +24,22 @@ module Breakfast
23
24
  end
24
25
  end
25
26
 
27
+ rake_tasks do
28
+ load "tasks/breakfast.rake"
29
+ end
30
+
26
31
  config.after_initialize do |app|
32
+ if config.breakfast.digest
33
+ config.breakfast.manifest = Breakfast::Manifest.new(base_dir: config.breakfast.asset_output_folder)
34
+ end
35
+
27
36
  if config.breakfast.environments.include?(Rails.env) && LocalEnvironment.new.running_server?
28
37
  Thread.new do
29
38
  Breakfast::BrunchWatcher.spawn(log: Rails.logger)
30
39
  end
31
40
 
32
41
  Breakfast::CompilationListener.start(
33
- asset_output_folders: config.breakfast.asset_output_folders,
42
+ asset_output_folder: config.breakfast.asset_output_folder,
34
43
  source_code_folders: config.breakfast.source_code_folders
35
44
  )
36
45
  end
@@ -1,3 +1,3 @@
1
1
  module Breakfast
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -19,5 +19,16 @@ module Breakfast
19
19
  end
20
20
  end
21
21
  end
22
+
23
+ include ActionView::Helpers::AssetUrlHelper
24
+ include ActionView::Helpers::AssetTagHelper
25
+
26
+ def compute_asset_path(path, options = {})
27
+ if Rails.configuration.breakfast.digest && Rails.configuration.breakfast.manifest.asset(path)
28
+ path = Rails.configuration.breakfast.manifest.asset(path)
29
+ end
30
+
31
+ super(path, options)
32
+ end
22
33
  end
23
34
  end
@@ -3,9 +3,9 @@ require "rails/generators"
3
3
  module Breakfast
4
4
  module Generators
5
5
  class InstallGenerator < Rails::Generators::Base
6
- source_root File.expand_path('../templates', __FILE__)
7
- NODE_VERSION = 'v4.1.1'
8
- NPM_VERSION = '3.10.6'
6
+ source_root File.expand_path("../templates", __FILE__)
7
+ NODE_VERSION = "v4.1.1"
8
+ NPM_VERSION = "3.10.6"
9
9
 
10
10
  def install
11
11
  if node_prerequisites_installed?
@@ -0,0 +1,61 @@
1
+ require "rake"
2
+ require "breakfast"
3
+
4
+ namespace :breakfast do
5
+ namespace :assets do
6
+ desc "Build assets"
7
+ task :build => :environment do
8
+ exec(Breakfast::BUILD_COMMAND)
9
+ end
10
+
11
+ desc "Build assets for production"
12
+ task :build_production => :environment do
13
+ exec(Breakfast::PRODUCTION_BUILD_COMMAND)
14
+ end
15
+
16
+ desc "Add a digest to non-fingerprinted assets"
17
+ task :digest => :environment do
18
+ if Rails.configuration.breakfast.manifest
19
+ Rails.configuration.breakfast.manifest.digest!
20
+ else
21
+ raise Breakfast::ManifestDisabledError
22
+ end
23
+ end
24
+
25
+ desc "Remove out of date assets"
26
+ task :clean => :environment do
27
+ if Rails.configuration.breakfast.manifest
28
+ Rails.configuration.breakfast.manifest.clean!
29
+ else
30
+ raise Breakfast::ManifestDisabledError
31
+ end
32
+ end
33
+
34
+ desc "Remove manifest and fingerprinted assets"
35
+ task :nuke => :environment do
36
+ if Rails.configuration.breakfast.manifest
37
+ Rails.configuration.breakfast.manifest.nuke!
38
+ else
39
+ raise Breakfast::ManifestDisabledError
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ module Breakfast
46
+ class ManifestDisabledError < StandardError
47
+ def initialize
48
+ super(
49
+ <<~ERROR
50
+ Rails.configuration.breakfast.manifest is set to false.
51
+ Enable it by adding the following in your environment file:
52
+
53
+ config.breakfast.manifest.digest = true
54
+
55
+ *Note* by default digest is set to false in development and test enviornments.
56
+
57
+ ERROR
58
+ )
59
+ end
60
+ end
61
+ end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breakfast-rails",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Assets for the Breakfast Gem",
5
5
  "main": "./lib/breakfast-rails.js",
6
6
  "scripts": {
@@ -211,7 +211,7 @@ class StatusBar {
211
211
  display: flex;
212
212
  flex-grow: 1;
213
213
  height: 30px;
214
- padding: 8px;
214
+ padding: 0 8px;
215
215
  }
216
216
 
217
217
  .breakfast-status-bar .breakfast-message-log-error {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breakfast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Koperwas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-19 00:00:00.000000000 Z
11
+ date: 2016-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -119,6 +119,7 @@ files:
119
119
  - lib/breakfast/capistrano/tasks/breakfast.rake
120
120
  - lib/breakfast/compilation_listener.rb
121
121
  - lib/breakfast/live_reload_channel.rb
122
+ - lib/breakfast/manifest.rb
122
123
  - lib/breakfast/railtie.rb
123
124
  - lib/breakfast/status_channel.rb
124
125
  - lib/breakfast/version.rb
@@ -128,6 +129,7 @@ files:
128
129
  - lib/generators/breakfast/templates/app.scss
129
130
  - lib/generators/breakfast/templates/brunch-config.js
130
131
  - lib/generators/breakfast/templates/package.json
132
+ - lib/tasks/breakfast.rake
131
133
  - node_package/.eslintrc.json
132
134
  - node_package/.npmignore
133
135
  - node_package/package.json