brunschgi/terrific-composer-bundle
brunschgi/terrific-core-bundle first (follow its README).composer require brunschgi/terrific-composer-bundle:^1.0
config/bundles.php (Laravel 5.4+) or AppKernel.php (Symfony/Laravel <5.4):
// config/bundles.php
return [
// ...
Brunschgi\TerrificComposerBundle\TerrificComposerBundle::class => ['all' => true],
];
php artisan vendor:publish --tag=terrific-composer-assets
TerrificComposer service to generate a frontend manifest:
use Brunschgi\TerrificComposerBundle\TerrificComposer;
$composer = $this->container->get('terrific_composer');
$manifest = $composer->compose('frontend_name');
Frontend Composition:
Define frontend bundles in config/terrific_composer.php:
frontend_bundles:
my_frontend:
entry: 'resources/assets/js/app.js'
output: 'public/build/my_frontend.js'
modules:
- '@my_module'
- 'vendor/package'
Trigger composition via CLI:
php artisan terrific:compose my_frontend
Integration with Laravel Mix/Webpack:
Use the bundle’s TerrificComposer service to inject Webpack paths dynamically:
// webpack.mix.js
const terrificComposer = require('./vendor/brunschgi/terrific-composer-bundle/resources/config/paths');
mix.webpackConfig({
resolve: {
alias: terrificComposer.aliases,
},
});
Dynamic Module Loading: Load modules conditionally in PHP:
if ($user->isPremium()) {
$composer->addModule('my_frontend', 'premium-module');
}
Asset Versioning: Leverage the bundle’s built-in versioning for cache busting:
<script src="{{ asset('build/my_frontend.js?v=' ~ terrific_composer.version('my_frontend')) }}"></script>
Symfony/Laravel Hybrid:
Use the bundle’s TerrificComposer service in both Symfony controllers and Laravel routes:
// Laravel Route Service Provider
public function boot() {
$composer = app('terrific_composer');
Route::get('/build/{frontend}', function ($frontend) use ($composer) {
return $composer->compose($frontend);
});
}
Environment-Specific Configs:
Override config/terrific_composer.php per environment (e.g., .env-based):
// config/terrific_composer.php
return [
'environments' => [
'production' => [
'optimization' => true,
],
],
];
Dependency Order:
modules override earlier ones. Use @ prefix for absolute paths (e.g., @my_module) to avoid conflicts.modules:
- '@core/module' # Loads from vendor/
- 'relative/path' # Loads from project root
Cache Invalidation:
php artisan cache:clear
php artisan config:clear
php artisan terrific:compose --force my_frontend
Webpack Conflicts:
terrific-composer-bundle’s Webpack config doesn’t clash with Mix’s. Merge configs explicitly:
mix.webpackConfig({
...terrificComposer.webpackConfig,
resolve: {
...terrificComposer.webpackConfig.resolve,
alias: {
...terrificComposer.webpackConfig.resolve.alias,
'@my_alias': path.resolve(__dirname, 'custom/path'),
},
},
});
Symfony vs. Laravel:
$composer = app('terrific_composer'); // Laravel <5.5
// OR
$composer = resolve('terrific_composer'); // Laravel 5.5+
Verbose Output:
Enable debug mode in config/terrific_composer.php:
'debug' => env('APP_DEBUG', false),
Run with:
php artisan terrific:compose --verbose my_frontend
Log Inspection:
Check storage/logs/laravel.log for composition errors. Enable monolog:
'logging' => true,
Dry Runs: Test configs without writing files:
php artisan terrific:compose --dry-run my_frontend
Custom Composers:
Extend the TerrificComposer class to add logic:
namespace App\Services;
use Brunschgi\TerrificComposerBundle\TerrificComposer as BaseComposer;
class CustomComposer extends BaseComposer {
public function addPostProcess($frontend, callable $callback) {
$this->postProcessors[$frontend][] = $callback;
}
}
Bind in AppServiceProvider:
$this->app->bind('terrific_composer', function () {
return new CustomComposer($this->app);
});
Hooks:
Use the terrific.composer.compose event to intercept composition:
// EventSubscriber
public static function getSubscribedEvents() {
return [
'terrific.composer.compose' => 'onCompose',
];
}
public function onCompose($event) {
$event->getComposer()->addModule('my_frontend', 'dynamic-module');
}
Asset Filters:
Filter assets during composition via the asset_filter config:
'asset_filters' => [
'my_frontend' => [
'exclude' => ['node_modules/', 'tests/'],
],
],
How can I help you explore Laravel packages today?