shakapacker 9.0.0.beta.0 → 9.0.0.beta.3
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 +4 -4
- data/.github/workflows/claude-code-review.yml +54 -0
- data/.github/workflows/claude.yml +50 -0
- data/.github/workflows/dummy.yml +3 -3
- data/.github/workflows/test-bundlers.yml +152 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +15 -3
- data/CLAUDE.md +29 -0
- data/Gemfile.lock +1 -1
- data/README.md +42 -1
- data/Rakefile +39 -4
- data/TODO.md +51 -0
- data/TODO_v9.md +84 -0
- data/conductor-setup.sh +58 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/css-modules-export-mode.md +216 -86
- data/docs/deployment.md +10 -1
- data/docs/rspack.md +7 -7
- data/docs/rspack_migration_guide.md +202 -0
- data/docs/using_esbuild_loader.md +3 -3
- data/docs/using_swc_loader.md +5 -3
- data/docs/v6_upgrade.md +10 -0
- data/docs/v9_upgrade.md +185 -0
- data/lib/install/bin/shakapacker +3 -17
- data/lib/install/config/shakapacker.yml +9 -4
- data/lib/shakapacker/configuration.rb +75 -3
- data/lib/shakapacker/dev_server_runner.rb +19 -9
- data/lib/shakapacker/manifest.rb +4 -3
- data/lib/shakapacker/rspack_runner.rb +4 -42
- data/lib/shakapacker/runner.rb +105 -11
- data/lib/shakapacker/utils/manager.rb +2 -0
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +1 -1
- data/lib/shakapacker/webpack_runner.rb +4 -42
- data/lib/tasks/shakapacker/install.rake +6 -2
- data/package/config.js +24 -0
- data/package/environments/base.js +12 -2
- data/package/environments/development.js +52 -12
- data/package/environments/production.js +8 -3
- data/package/environments/test.js +5 -3
- data/package/index.d.ts +69 -30
- data/package/index.js +1 -1
- data/package/optimization/rspack.js +9 -5
- data/package/plugins/rspack.js +12 -28
- data/package/rspack/index.js +57 -0
- data/package/rules/babel.js +2 -2
- data/package/rules/esbuild.js +2 -2
- data/package/rules/raw.js +5 -5
- data/package/rules/rspack.js +77 -7
- data/package/rules/swc.js +2 -2
- data/package/utils/debug.js +49 -0
- data/package/utils/getStyleRule.js +19 -10
- data/package/utils/requireOrError.js +1 -1
- data/package/utils/validateCssModulesConfig.js +91 -0
- data/package/utils/validateDependencies.js +61 -0
- data/package/webpackDevServerConfig.js +2 -0
- data/package-lock.json +11966 -0
- data/package.json +9 -2
- data/test/package/rules/esbuild.test.js +1 -1
- data/test/package/rules/swc.test.js +1 -1
- data/tools/README.md +124 -0
- data/tools/css-modules-v9-codemod.js +179 -0
- data/yarn.lock +199 -81
- metadata +20 -3
- data/lib/install/bin/shakapacker-rspack +0 -13
data/conductor-setup.sh
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
|
4
|
+
echo "🔧 Setting up Shakapacker workspace..."
|
5
|
+
|
6
|
+
# Set up Ruby version if asdf is available
|
7
|
+
if command -v asdf &> /dev/null; then
|
8
|
+
echo "📝 Using asdf Ruby version management..."
|
9
|
+
# Ensure we have the right Ruby version file
|
10
|
+
echo "ruby 3.3.4" > .tool-versions
|
11
|
+
# Use asdf exec to run commands with the right Ruby version
|
12
|
+
BUNDLE_CMD="asdf exec bundle"
|
13
|
+
else
|
14
|
+
BUNDLE_CMD="bundle"
|
15
|
+
fi
|
16
|
+
|
17
|
+
# Check for required tools
|
18
|
+
if ! $BUNDLE_CMD --version &> /dev/null; then
|
19
|
+
echo "❌ Error: Ruby bundler is not installed"
|
20
|
+
echo "Please install bundler first: gem install bundler"
|
21
|
+
exit 1
|
22
|
+
fi
|
23
|
+
|
24
|
+
if ! command -v yarn &> /dev/null; then
|
25
|
+
echo "❌ Error: Yarn is not installed"
|
26
|
+
echo "Please install yarn first"
|
27
|
+
exit 1
|
28
|
+
fi
|
29
|
+
|
30
|
+
# Install Ruby dependencies
|
31
|
+
echo "📦 Installing Ruby dependencies..."
|
32
|
+
$BUNDLE_CMD install
|
33
|
+
|
34
|
+
# Install JavaScript dependencies
|
35
|
+
echo "📦 Installing JavaScript dependencies..."
|
36
|
+
yarn install
|
37
|
+
|
38
|
+
# Copy environment files if they exist in root
|
39
|
+
if [ -n "${CONDUCTOR_ROOT_PATH:-}" ]; then
|
40
|
+
if [ -f "$CONDUCTOR_ROOT_PATH/.env" ]; then
|
41
|
+
echo "📋 Copying .env file from root..."
|
42
|
+
cp "$CONDUCTOR_ROOT_PATH/.env" .env
|
43
|
+
fi
|
44
|
+
|
45
|
+
if [ -f "$CONDUCTOR_ROOT_PATH/.env.local" ]; then
|
46
|
+
echo "📋 Copying .env.local file from root..."
|
47
|
+
cp "$CONDUCTOR_ROOT_PATH/.env.local" .env.local
|
48
|
+
fi
|
49
|
+
fi
|
50
|
+
|
51
|
+
echo "✅ Workspace setup complete!"
|
52
|
+
echo ""
|
53
|
+
echo "Available commands:"
|
54
|
+
echo " - Run tests: bundle exec rspec"
|
55
|
+
echo " - Run specific test suites: bundle exec rake run_spec:gem"
|
56
|
+
echo " - Run JavaScript tests: yarn test"
|
57
|
+
echo " - Lint JavaScript: yarn lint"
|
58
|
+
echo " - Lint Ruby: bundle exec rubocop"
|
data/conductor.json
ADDED
data/docs/cdn_setup.md
ADDED
@@ -0,0 +1,379 @@
|
|
1
|
+
# CDN Setup Guide for Shakapacker
|
2
|
+
|
3
|
+
This guide explains how to configure Shakapacker to serve your JavaScript bundles and other assets from a Content Delivery Network (CDN) like CloudFlare, CloudFront, or Fastly.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Overview](#overview)
|
8
|
+
- [Configuration Methods](#configuration-methods)
|
9
|
+
- [Step-by-Step Setup](#step-by-step-setup)
|
10
|
+
- [CloudFlare Specific Setup](#cloudflare-specific-setup)
|
11
|
+
- [Verification](#verification)
|
12
|
+
- [Troubleshooting](#troubleshooting)
|
13
|
+
- [Advanced Configuration](#advanced-configuration)
|
14
|
+
|
15
|
+
## Overview
|
16
|
+
|
17
|
+
When using a CDN with Shakapacker, your compiled JavaScript bundles and other assets will be served from the CDN's edge servers instead of your application server. This provides:
|
18
|
+
|
19
|
+
- **Reduced latency** for users around the world
|
20
|
+
- **Decreased load** on your application servers
|
21
|
+
- **Better caching** and faster asset delivery
|
22
|
+
- **Improved scalability** for high-traffic applications
|
23
|
+
|
24
|
+
## Configuration Methods
|
25
|
+
|
26
|
+
Shakapacker supports CDN configuration through three methods (in order of precedence):
|
27
|
+
|
28
|
+
1. **Environment Variable** (highest priority): `SHAKAPACKER_ASSET_HOST`
|
29
|
+
2. **Shakapacker Configuration File**: `asset_host` setting in `config/shakapacker.yml`
|
30
|
+
3. **Rails Configuration**: `Rails.application.config.asset_host`
|
31
|
+
|
32
|
+
## Step-by-Step Setup
|
33
|
+
|
34
|
+
### 1. Configure Your CDN
|
35
|
+
|
36
|
+
First, set up your CDN to pull assets from your application's `/packs` directory. The exact steps depend on your CDN provider, but generally you'll need to:
|
37
|
+
|
38
|
+
1. Create a CDN distribution/zone
|
39
|
+
2. Set your application's domain as the origin server
|
40
|
+
3. Configure the CDN to cache files from `/packs/*` path
|
41
|
+
4. Note your CDN URL (e.g., `https://cdn.example.com` or `https://d1234567890.cloudfront.net`)
|
42
|
+
|
43
|
+
### 2. Configure Shakapacker Asset Host
|
44
|
+
|
45
|
+
Choose one of the following methods:
|
46
|
+
|
47
|
+
#### Option A: Using Environment Variable (Recommended for Production)
|
48
|
+
|
49
|
+
Set the `SHAKAPACKER_ASSET_HOST` environment variable:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
# For production deployment
|
53
|
+
export SHAKAPACKER_ASSET_HOST=https://cdn.example.com
|
54
|
+
|
55
|
+
# Or in your .env file
|
56
|
+
SHAKAPACKER_ASSET_HOST=https://cdn.example.com
|
57
|
+
```
|
58
|
+
|
59
|
+
#### Option B: Using shakapacker.yml
|
60
|
+
|
61
|
+
Add the `asset_host` setting to your `config/shakapacker.yml`:
|
62
|
+
|
63
|
+
```yaml
|
64
|
+
production:
|
65
|
+
# ... other settings ...
|
66
|
+
asset_host: https://cdn.example.com
|
67
|
+
|
68
|
+
# You can also set different CDN hosts per environment
|
69
|
+
staging:
|
70
|
+
asset_host: https://staging-cdn.example.com
|
71
|
+
```
|
72
|
+
|
73
|
+
#### Option C: Using Rails Configuration
|
74
|
+
|
75
|
+
Configure in your Rails environment file (e.g., `config/environments/production.rb`):
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Rails.application.configure do
|
79
|
+
# ... other settings ...
|
80
|
+
|
81
|
+
# This will be used by Shakapacker if SHAKAPACKER_ASSET_HOST
|
82
|
+
# and asset_host in shakapacker.yml are not set
|
83
|
+
config.action_controller.asset_host = 'https://cdn.example.com'
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
### 3. Compile Assets
|
88
|
+
|
89
|
+
During deployment, compile your assets as usual:
|
90
|
+
|
91
|
+
```bash
|
92
|
+
# The SHAKAPACKER_ASSET_HOST will be used during compilation
|
93
|
+
# to set the webpack publicPath
|
94
|
+
RAILS_ENV=production bundle exec rails assets:precompile
|
95
|
+
```
|
96
|
+
|
97
|
+
This ensures that:
|
98
|
+
- Webpack's `publicPath` is set to your CDN URL
|
99
|
+
- Dynamic imports and code-split chunks load from the CDN
|
100
|
+
- Asset manifest references use CDN URLs
|
101
|
+
|
102
|
+
### 4. Deploy and Sync Assets
|
103
|
+
|
104
|
+
After compilation, ensure your compiled assets in `public/packs` are accessible to your CDN:
|
105
|
+
|
106
|
+
- **Push CDN**: Upload the files to your CDN's storage
|
107
|
+
- **Pull CDN**: Deploy your application normally; the CDN will pull assets on first request
|
108
|
+
|
109
|
+
## CloudFlare Specific Setup
|
110
|
+
|
111
|
+
For CloudFlare CDN setup:
|
112
|
+
|
113
|
+
### 1. Create a CloudFlare Account and Add Your Domain
|
114
|
+
|
115
|
+
1. Sign up for CloudFlare (if you haven't already)
|
116
|
+
2. Add your domain to CloudFlare
|
117
|
+
3. Update your domain's nameservers to CloudFlare's
|
118
|
+
|
119
|
+
### 2. Configure Page Rules for Assets
|
120
|
+
|
121
|
+
Create a page rule for your assets:
|
122
|
+
|
123
|
+
1. Go to **Page Rules** in CloudFlare dashboard
|
124
|
+
2. Create a new rule for `*yourdomain.com/packs/*`
|
125
|
+
3. Set the following settings:
|
126
|
+
- **Cache Level**: Cache Everything
|
127
|
+
- **Edge Cache TTL**: 1 month (or your preference)
|
128
|
+
- **Browser Cache TTL**: 1 month
|
129
|
+
|
130
|
+
### 3. Set Up CloudFlare for Assets Only (Optional)
|
131
|
+
|
132
|
+
If you want CloudFlare to only serve your assets (not your entire site):
|
133
|
+
|
134
|
+
1. Create a CNAME record: `cdn.yourdomain.com` → `yourdomain.com`
|
135
|
+
2. Set CloudFlare proxy (orange cloud) ON for this record
|
136
|
+
3. Configure Shakapacker:
|
137
|
+
|
138
|
+
```bash
|
139
|
+
export SHAKAPACKER_ASSET_HOST=https://cdn.yourdomain.com
|
140
|
+
```
|
141
|
+
|
142
|
+
### 4. Configure CloudFlare Settings
|
143
|
+
|
144
|
+
Recommended CloudFlare settings for assets:
|
145
|
+
|
146
|
+
- **SSL/TLS**: Full or Full (Strict)
|
147
|
+
- **Caching Level**: Standard or Aggressive
|
148
|
+
- **Browser Cache TTL**: Respect Existing Headers
|
149
|
+
- **Always Online**: On
|
150
|
+
- **Auto Minify**: OFF (Shakapacker already minifies)
|
151
|
+
|
152
|
+
## Verification
|
153
|
+
|
154
|
+
To verify your CDN setup is working:
|
155
|
+
|
156
|
+
### 1. Check Compiled Assets
|
157
|
+
|
158
|
+
After compilation, inspect a compiled JavaScript file:
|
159
|
+
|
160
|
+
```bash
|
161
|
+
# Look for the publicPath setting in your compiled bundles
|
162
|
+
grep -r "publicPath" public/packs/js/
|
163
|
+
```
|
164
|
+
|
165
|
+
You should see your CDN URL in the publicPath configuration.
|
166
|
+
|
167
|
+
### 2. Check Page Source
|
168
|
+
|
169
|
+
In production, view your page source and verify script tags use CDN URLs:
|
170
|
+
|
171
|
+
```html
|
172
|
+
<!-- Correct: Assets loading from CDN -->
|
173
|
+
<script src="https://cdn.example.com/packs/js/application-abc123.js"></script>
|
174
|
+
|
175
|
+
<!-- Wrong: Assets loading from relative path -->
|
176
|
+
<script src="/packs/js/application-abc123.js"></script>
|
177
|
+
```
|
178
|
+
|
179
|
+
### 3. Check Network Tab
|
180
|
+
|
181
|
+
1. Open browser DevTools
|
182
|
+
2. Go to Network tab
|
183
|
+
3. Reload the page
|
184
|
+
4. Verify JavaScript files are loaded from CDN domain
|
185
|
+
|
186
|
+
### 4. Check Dynamic Imports
|
187
|
+
|
188
|
+
If using code splitting, verify dynamic chunks load from CDN:
|
189
|
+
|
190
|
+
```javascript
|
191
|
+
// This dynamic import should load from CDN
|
192
|
+
import('./components/HeavyComponent').then(module => {
|
193
|
+
// Check Network tab - chunk should load from CDN
|
194
|
+
});
|
195
|
+
```
|
196
|
+
|
197
|
+
## Troubleshooting
|
198
|
+
|
199
|
+
### Assets Not Loading from CDN
|
200
|
+
|
201
|
+
**Problem**: Assets are still loading from your application domain.
|
202
|
+
|
203
|
+
**Solutions**:
|
204
|
+
1. Ensure you set `SHAKAPACKER_ASSET_HOST` **before** running `assets:precompile`
|
205
|
+
2. Clear Rails cache: `rails tmp:cache:clear`
|
206
|
+
3. Check the manifest.json file includes CDN URLs:
|
207
|
+
```bash
|
208
|
+
cat public/packs/manifest.json
|
209
|
+
```
|
210
|
+
|
211
|
+
### CORS Errors
|
212
|
+
|
213
|
+
**Problem**: Browser shows CORS errors when loading assets from CDN.
|
214
|
+
|
215
|
+
**Solutions**:
|
216
|
+
1. Configure your CDN to add CORS headers:
|
217
|
+
```
|
218
|
+
Access-Control-Allow-Origin: *
|
219
|
+
```
|
220
|
+
2. Or configure for specific domain:
|
221
|
+
```
|
222
|
+
Access-Control-Allow-Origin: https://yourdomain.com
|
223
|
+
```
|
224
|
+
|
225
|
+
### Fonts Not Loading
|
226
|
+
|
227
|
+
**Problem**: Web fonts fail to load from CDN due to CORS.
|
228
|
+
|
229
|
+
**Solutions**:
|
230
|
+
1. Ensure CDN sends proper CORS headers for font files
|
231
|
+
2. In CloudFlare, create a page rule for `*.woff2`, `*.woff`, `*.ttf` files with CORS headers
|
232
|
+
3. Consider hosting fonts separately or using base64 encoding
|
233
|
+
|
234
|
+
### Development Environment Issues
|
235
|
+
|
236
|
+
**Problem**: CDN URLs appearing in development environment.
|
237
|
+
|
238
|
+
**Solution**: Only set `SHAKAPACKER_ASSET_HOST` in production:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
# config/environments/development.rb
|
242
|
+
# Ensure asset_host is NOT set in development
|
243
|
+
|
244
|
+
# config/environments/production.rb
|
245
|
+
# Set asset_host only in production
|
246
|
+
```
|
247
|
+
|
248
|
+
## Advanced Configuration
|
249
|
+
|
250
|
+
### Using Different CDNs for Different Assets
|
251
|
+
|
252
|
+
You can use Rails asset host proc for dynamic CDN selection:
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
# config/environments/production.rb
|
256
|
+
config.action_controller.asset_host = Proc.new do |source|
|
257
|
+
if source =~ /\.(js|css)$/
|
258
|
+
'https://js-css-cdn.example.com'
|
259
|
+
else
|
260
|
+
'https://images-cdn.example.com'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
265
|
+
### CDN with Integrity Hashes
|
266
|
+
|
267
|
+
When using Subresource Integrity (SRI) with CDN:
|
268
|
+
|
269
|
+
```yaml
|
270
|
+
# config/shakapacker.yml
|
271
|
+
production:
|
272
|
+
asset_host: https://cdn.example.com
|
273
|
+
integrity:
|
274
|
+
enabled: true
|
275
|
+
hash_functions: ["sha384"]
|
276
|
+
cross_origin: "anonymous"
|
277
|
+
```
|
278
|
+
|
279
|
+
Ensure your CDN serves files with CORS headers:
|
280
|
+
```
|
281
|
+
Access-Control-Allow-Origin: *
|
282
|
+
```
|
283
|
+
|
284
|
+
### Multiple CDN Domains for Parallel Downloads
|
285
|
+
|
286
|
+
For HTTP/1.1 optimization (less relevant with HTTP/2):
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
# config/environments/production.rb
|
290
|
+
config.action_controller.asset_host = Proc.new do |source|
|
291
|
+
"https://cdn#{Digest::MD5.hexdigest(source)[0..2].to_i(16) % 4}.example.com"
|
292
|
+
end
|
293
|
+
# This creates cdn0.example.com through cdn3.example.com
|
294
|
+
```
|
295
|
+
|
296
|
+
### Cache Busting
|
297
|
+
|
298
|
+
Shakapacker automatically includes content hashes in production:
|
299
|
+
|
300
|
+
```yaml
|
301
|
+
# config/shakapacker.yml
|
302
|
+
production:
|
303
|
+
# This is already true by default in production
|
304
|
+
useContentHash: true
|
305
|
+
```
|
306
|
+
|
307
|
+
This ensures CDN caches are invalidated when content changes.
|
308
|
+
|
309
|
+
### Preloading Critical Assets
|
310
|
+
|
311
|
+
Use Rails helpers to preload critical assets from CDN:
|
312
|
+
|
313
|
+
```erb
|
314
|
+
<%= preload_pack_asset 'application.js' %>
|
315
|
+
<%= preload_pack_asset 'application.css' %>
|
316
|
+
```
|
317
|
+
|
318
|
+
## Security Considerations
|
319
|
+
|
320
|
+
1. **Use HTTPS**: Always use HTTPS for your CDN URL to prevent mixed content warnings
|
321
|
+
2. **Configure CSP**: Update Content Security Policy headers to allow CDN domain:
|
322
|
+
```ruby
|
323
|
+
# config/initializers/content_security_policy.rb
|
324
|
+
Rails.application.config.content_security_policy do |policy|
|
325
|
+
policy.script_src :self, 'https://cdn.example.com'
|
326
|
+
policy.style_src :self, 'https://cdn.example.com'
|
327
|
+
end
|
328
|
+
```
|
329
|
+
3. **Use SRI**: Enable Subresource Integrity for additional security
|
330
|
+
4. **Monitor CDN**: Set up monitoring for CDN availability and performance
|
331
|
+
|
332
|
+
## Example Configuration
|
333
|
+
|
334
|
+
Here's a complete example for a production setup with CloudFlare:
|
335
|
+
|
336
|
+
```yaml
|
337
|
+
# config/shakapacker.yml
|
338
|
+
production:
|
339
|
+
compile: false
|
340
|
+
cache_manifest: true
|
341
|
+
asset_host: <%= ENV.fetch('SHAKAPACKER_ASSET_HOST', 'https://cdn.example.com') %>
|
342
|
+
|
343
|
+
# Enable integrity checking
|
344
|
+
integrity:
|
345
|
+
enabled: true
|
346
|
+
hash_functions: ["sha384"]
|
347
|
+
cross_origin: "anonymous"
|
348
|
+
```
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
# config/environments/production.rb
|
352
|
+
Rails.application.configure do
|
353
|
+
# Fallback if SHAKAPACKER_ASSET_HOST is not set
|
354
|
+
config.action_controller.asset_host = 'https://cdn.example.com'
|
355
|
+
|
356
|
+
# Ensure proper headers for CDN
|
357
|
+
config.public_file_server.headers = {
|
358
|
+
'Cache-Control' => 'public, max-age=31536000',
|
359
|
+
'X-Content-Type-Options' => 'nosniff'
|
360
|
+
}
|
361
|
+
end
|
362
|
+
```
|
363
|
+
|
364
|
+
```bash
|
365
|
+
# Deployment script
|
366
|
+
export SHAKAPACKER_ASSET_HOST=https://cdn.example.com
|
367
|
+
RAILS_ENV=production bundle exec rails assets:precompile
|
368
|
+
```
|
369
|
+
|
370
|
+
## Summary
|
371
|
+
|
372
|
+
Setting up a CDN with Shakapacker involves:
|
373
|
+
|
374
|
+
1. Configuring your CDN service
|
375
|
+
2. Setting the `SHAKAPACKER_ASSET_HOST` environment variable
|
376
|
+
3. Compiling assets with the CDN URL
|
377
|
+
4. Deploying and verifying the setup
|
378
|
+
|
379
|
+
The key is ensuring `SHAKAPACKER_ASSET_HOST` is set during asset compilation so webpack's `publicPath` is configured correctly for dynamic imports and code-split chunks.
|