railpack 1.3.0 → 1.3.1

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
  SHA256:
3
- metadata.gz: 5b714e261e3a676ca82d2ea8b33bb47cdf23de847ab367c50edd500883ce1d5a
4
- data.tar.gz: c12f5f2c37108aba8bc3f565ce80a3441895b2eada01a127f33129f15ec28f4f
3
+ metadata.gz: f0e77f850d344d1b29f2e275c3cd49be7a4a684d0f3d5c880d03146b5cbeed6b
4
+ data.tar.gz: 2d2874defb0fd76f9c2c0ca3d4e746edf9067ce59fba07ef151ff096ffad5016
5
5
  SHA512:
6
- metadata.gz: 364d8756b8fe2139b37fecc94196e44f56e05a238bedfca6618d8485ceb1f0e1bed9bf5ae08dc0f424055f431146a68d2406b34e65ba84e1f88a671507cd6841
7
- data.tar.gz: bd7b094432e4a15707f1878a1c5045187892247ae38a1f41cbf42823a4681b2ff217d220e02fff73528213fcf15d1973f5b3aebfddf6f13d721639be45aa1098
6
+ metadata.gz: e7308ab9513cfbdb703dac82f3534b8382948e9ee705dc39505014ad951141e3e75c7c2277977e20912975236b9f0efbe9acecf0032ad4203723a273f48cb8d9
7
+ data.tar.gz: 652705db3d4555423ea5ddcfbf8aecb6aa3584063a1c594934594052e5d7ec370c8ac44e7804092963a5b550f740fc15b414e86d03cb53811f732a0638b384d6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.1] - 2026-01-26
4
+
5
+ This patch release includes final polish and documentation improvements.
6
+
7
+ ### Changes
8
+
9
+ - **Code style**: Properly indented private methods and removed duplicate `private` keyword
10
+ - **Pre-build validation**: Added `FileUtils.mkdir_p(outdir)` to ensure output directories exist before build
11
+ - **Documentation**: Added comprehensive examples for `analyze_bundle` (gzip output), build hooks (payload details), and manifest delegation
12
+
3
13
  ## [1.3.0] - 2026-01-26
4
14
 
5
15
  ### 🚀 **Major Architecture Refactoring**
data/README.md CHANGED
@@ -43,6 +43,7 @@ default:
43
43
  sourcemap: false
44
44
  entrypoint: "./app/javascript/application.js"
45
45
  outdir: "app/assets/builds"
46
+ analyze_bundle: false # Enable for gzip size reporting
46
47
 
47
48
  # Bundler-specific config
48
49
  bun:
@@ -52,9 +53,11 @@ bun:
52
53
  # Environment overrides
53
54
  development:
54
55
  sourcemap: true
56
+ analyze_bundle: true # Show gzip sizes in dev
55
57
 
56
58
  production:
57
59
  minify: true
60
+ analyze_bundle: true # Production bundle analysis
58
61
  ```
59
62
 
60
63
  ## Usage
@@ -111,6 +114,61 @@ Railpack.on_build_complete do |result|
111
114
  end
112
115
  ```
113
116
 
117
+ ### Advanced Usage
118
+
119
+ #### Bundle Analysis with Gzip
120
+
121
+ Enable `analyze_bundle: true` to see both uncompressed and gzipped bundle sizes:
122
+
123
+ ```yaml
124
+ # config/railpack.yml
125
+ default:
126
+ analyze_bundle: true
127
+ ```
128
+
129
+ Output example:
130
+ ```
131
+ ✅ Build completed successfully in 45.23ms (1.23 MB (0.45 MB gzipped))
132
+ ```
133
+
134
+ #### Build Hooks with Payload Details
135
+
136
+ Hook payloads provide detailed information about build results:
137
+
138
+ ```ruby
139
+ # config/initializers/railpack.rb
140
+ Railpack.on_build_complete do |payload|
141
+ if payload[:success]
142
+ # Success payload: { success: true, config: {...}, duration: 45.23, bundle_size: "1.23 MB" }
143
+ Rails.logger.info "Build succeeded in #{payload[:duration]}ms - #{payload[:bundle_size]}"
144
+ else
145
+ # Error payload: { success: false, error: #<Error>, config: {...}, duration: 12.34 }
146
+ Rails.logger.error "Build failed after #{payload[:duration]}ms: #{payload[:error].message}"
147
+ end
148
+ end
149
+
150
+ Railpack.on_build_start do |config|
151
+ # Config hash contains all current settings
152
+ Rails.logger.info "Starting #{config['bundler']} build for #{Rails.env}"
153
+ end
154
+ ```
155
+
156
+ #### Manifest Generation
157
+
158
+ Railpack automatically detects your asset pipeline and generates appropriate manifests:
159
+
160
+ ```ruby
161
+ # For Propshaft (Rails 7+ default)
162
+ # Generates: app/assets/builds/.manifest.json
163
+ Railpack::Manifest::Propshaft.generate(config)
164
+
165
+ # For Sprockets (Rails < 7)
166
+ # Generates: app/assets/builds/.sprockets-manifest-*.json
167
+ Railpack::Manifest::Sprockets.generate(config)
168
+ ```
169
+
170
+ The manifest generation is handled automatically after each build, but you can trigger it manually if needed.
171
+
114
172
  ## Supported Bundlers
115
173
 
116
174
  ### Bun (Default)
@@ -132,107 +132,107 @@ module Railpack
132
132
 
133
133
  private
134
134
 
135
- def create_bundler
136
- bundler_name = Railpack.config.bundler
137
- bundler_class = BUNDLERS[bundler_name]
135
+ def create_bundler
136
+ bundler_name = Railpack.config.bundler
137
+ bundler_class = BUNDLERS[bundler_name]
138
138
 
139
- unless bundler_class
140
- raise Error, "Unsupported bundler: #{bundler_name}. Available: #{BUNDLERS.keys.join(', ')}"
141
- end
139
+ unless bundler_class
140
+ raise Error, "Unsupported bundler: #{bundler_name}. Available: #{BUNDLERS.keys.join(', ')}"
141
+ end
142
142
 
143
- bundler_class.new(Railpack.config)
144
- end
143
+ bundler_class.new(Railpack.config)
144
+ end
145
145
 
146
- # Calculate human-readable bundle size with optional gzip compression
147
- def calculate_bundle_size(config)
148
- outdir = config['outdir']
149
- return 'unknown' unless outdir && Dir.exist?(outdir)
146
+ # Calculate human-readable bundle size with optional gzip compression
147
+ def calculate_bundle_size(config)
148
+ outdir = config['outdir']
149
+ return 'unknown' unless outdir && Dir.exist?(outdir)
150
150
 
151
- total_size = 0
152
- Dir.glob("#{outdir}/**/*.{js,css,map}").each do |file|
153
- total_size += File.size(file) if File.file?(file)
154
- end
151
+ total_size = 0
152
+ Dir.glob("#{outdir}/**/*.{js,css,map}").each do |file|
153
+ total_size += File.size(file) if File.file?(file)
154
+ end
155
155
 
156
- # Include gzip size if analyze_bundle is enabled
157
- if config['analyze_bundle']
158
- gzip_size = calculate_gzip_size(outdir)
159
- "#{human_size(total_size)} (#{human_size(gzip_size)} gzipped)"
160
- else
161
- human_size(total_size)
156
+ # Include gzip size if analyze_bundle is enabled
157
+ if config['analyze_bundle']
158
+ gzip_size = calculate_gzip_size(outdir)
159
+ "#{human_size(total_size)} (#{human_size(gzip_size)} gzipped)"
160
+ else
161
+ human_size(total_size)
162
+ end
163
+ rescue => error
164
+ Railpack.logger.debug "Bundle size calculation failed: #{error.message}"
165
+ 'unknown'
162
166
  end
163
- rescue => error
164
- Railpack.logger.debug "Bundle size calculation failed: #{error.message}"
165
- 'unknown'
166
- end
167
167
 
168
- # Calculate total gzip-compressed size of assets
169
- def calculate_gzip_size(outdir)
170
- Dir.glob("#{outdir}/**/*.{js,css}").sum do |file|
171
- next 0 unless File.file?(file)
172
- Zlib::Deflate.deflate(File.read(file)).bytesize
168
+ # Calculate total gzip-compressed size of assets
169
+ def calculate_gzip_size(outdir)
170
+ Dir.glob("#{outdir}/**/*.{js,css}").sum do |file|
171
+ next 0 unless File.file?(file)
172
+ Zlib::Deflate.deflate(File.read(file)).bytesize
173
+ end
174
+ rescue => error
175
+ Railpack.logger.debug "Gzip size calculation failed: #{error.message}"
176
+ 0
173
177
  end
174
- rescue => error
175
- Railpack.logger.debug "Gzip size calculation failed: #{error.message}"
176
- 0
177
- end
178
178
 
179
- # Convert bytes to human-readable format (B, KB, MB, GB)
180
- def human_size(bytes)
181
- units = %w[B KB MB GB]
182
- size = bytes.to_f
183
- units.each do |unit|
184
- return "#{(size).round(2)} #{unit}" if size < 1024
185
- size /= 1024
179
+ # Convert bytes to human-readable format (B, KB, MB, GB)
180
+ def human_size(bytes)
181
+ units = %w[B KB MB GB]
182
+ size = bytes.to_f
183
+ units.each do |unit|
184
+ return "#{(size).round(2)} #{unit}" if size < 1024
185
+ size /= 1024
186
+ end
186
187
  end
187
- end
188
188
 
189
- def generate_asset_manifest(config)
190
- outdir = config['outdir']
191
- return unless outdir && Dir.exist?(outdir)
189
+ def generate_asset_manifest(config)
190
+ outdir = config['outdir']
191
+ return unless outdir && Dir.exist?(outdir)
192
192
 
193
- # Detect asset pipeline type and delegate to appropriate manifest generator
194
- pipeline_type = detect_asset_pipeline
195
- manifest_class = Railpack::Manifest.const_get(pipeline_type.capitalize)
193
+ # Detect asset pipeline type and delegate to appropriate manifest generator
194
+ pipeline_type = detect_asset_pipeline
195
+ manifest_class = Railpack::Manifest.const_get(pipeline_type.capitalize)
196
196
 
197
- manifest_class.generate(config)
198
- rescue => error
199
- # Enhanced error logging with context
200
- asset_files = Dir.glob("#{outdir}/**/*.{js,css}").length rescue 0
201
- Railpack.logger.warn "⚠️ Failed to generate #{pipeline_type} asset manifest for #{outdir} (#{asset_files} assets): #{error.message}"
202
- end
197
+ manifest_class.generate(config)
198
+ rescue => error
199
+ # Enhanced error logging with context
200
+ asset_files = Dir.glob("#{outdir}/**/*.{js,css}").length rescue 0
201
+ Railpack.logger.warn "⚠️ Failed to generate #{pipeline_type} asset manifest for #{outdir} (#{asset_files} assets): #{error.message}"
202
+ end
203
203
 
204
- # Validate output directory exists and is writable before build
205
- def validate_output_directory(config)
206
- outdir = config['outdir']
207
- return unless outdir
204
+ # Validate output directory exists and is writable before build
205
+ def validate_output_directory(config)
206
+ outdir = config['outdir']
207
+ return unless outdir
208
208
 
209
- unless Dir.exist?(outdir)
210
- Railpack.logger.warn "⚠️ Output directory #{outdir} does not exist - assets will be created on first build"
209
+ unless Dir.exist?(outdir)
210
+ Railpack.logger.warn "⚠️ Output directory #{outdir} does not exist - assets will be created on first build"
211
+ # Ensure directory exists to prevent early build failures
212
+ FileUtils.mkdir_p(outdir)
213
+ end
211
214
  end
212
- end
213
215
 
214
- def detect_asset_pipeline
215
- # Check Rails.application.config.assets class directly (more reliable)
216
- if defined?(Rails) && Rails.respond_to?(:application) && Rails.application
217
- assets_config = Rails.application.config.assets
218
- if assets_config.is_a?(Propshaft::Assembler) || defined?(Propshaft::Assembler)
216
+ def detect_asset_pipeline
217
+ # Check Rails.application.config.assets class directly (more reliable)
218
+ if defined?(Rails) && Rails.respond_to?(:application) && Rails.application
219
+ assets_config = Rails.application.config.assets
220
+ if assets_config.is_a?(Propshaft::Assembler) || defined?(Propshaft::Assembler)
221
+ :propshaft
222
+ elsif defined?(Sprockets::Manifest)
223
+ :sprockets
224
+ end
225
+ end
226
+
227
+ # Fallback to version-based detection
228
+ if defined?(Rails) && Rails.version.to_f >= 7.0
219
229
  :propshaft
220
- elsif defined?(Sprockets::Manifest)
230
+ elsif defined?(Rails) && Rails.version.to_f < 7.0 && defined?(Sprockets)
221
231
  :sprockets
232
+ else
233
+ # Safe default for modern Rails
234
+ :propshaft
222
235
  end
223
236
  end
224
-
225
- # Fallback to version-based detection
226
- if defined?(Rails) && Rails.version.to_f >= 7.0
227
- :propshaft
228
- elsif defined?(Rails) && Rails.version.to_f < 7.0 && defined?(Sprockets)
229
- :sprockets
230
- else
231
- # Safe default for modern Rails
232
- :propshaft
233
- end
234
- end
235
-
236
-
237
237
  end
238
- end
238
+ end
@@ -1,3 +1,3 @@
1
1
  module Railpack
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - 21tycoons LLC