dontdrinkandroot/angular-integration-bundle
Installation
composer require dontdrinkandroot/angular-integration-bundle
Add the bundle to config/bundles.php:
return [
// ...
DontDrinkAndRoot\AngularIntegrationBundle\DontDrinkAndRootAngularIntegrationBundle::class => ['all' => true],
];
Basic Configuration
Create a config file at config/packages/dont_drink_and_root_angular_integration.yaml:
angular_integration:
entry_point: 'dist/app' # Path to your Angular entry JS file
assets_path: '%kernel.project_dir%/public/dist' # Angular build output
enabled: true
First Use Case: Serve Angular Assets
ng build --prod).public/dist.php bin/console cache:clear
http://your-app.dev/dist/index.html).Routing Integration
Use Symfony’s Router to proxy API calls while letting Angular handle client-side routes:
{# templates/base.html.twig #}
<div id="app-root"></div>
<script src="{{ asset(parameter('angular_integration.entry_point')) }}"></script>
API Endpoints Expose Symfony routes as REST APIs for Angular to consume:
# config/routes.yaml
api_users:
path: /api/users
controller: App\Controller\UserController::index
methods: GET
Asset Management
assets_path to match your Angular build output.asset() Twig function to reference Angular files:
<link rel="stylesheet" href="{{ asset('dist/styles.css') }}">
Environment-Specific Config
Override config per environment (e.g., config/packages/dev/angular_integration.yaml):
angular_integration:
entry_point: 'dist/app.dev.js' # Use non-minified for dev
Webpack Encore Integration
If using Encore, sync build paths with assets_path:
// webpack.config.js
Encore.setOutputPath('public/dist/');
Caching Issues
php bin/console cache:clear
rm -rf public/dist/* # Force rebuild Angular
ng build --prod
AppCache in config/packages/dev/framework.yaml if Angular routes conflict:
framework:
http_cache:
enabled: false
Asset Path Conflicts
assets_path in config matches your Angular build output exactly.base href (e.g., <base href="/dist/">) to avoid 404s.Route Collisions
/dashboard) may conflict with Symfony’s server-side routes.requirements to block non-API routes:
# config/routes.yaml
_angular_fallback:
path: /{path}
controller: App\Controller\AngularFallbackController::index
requirements:
path: .*
Debugging Angular in Symfony
request.getPathInfo() in a base controller:
// src/Controller/BaseController.php
public function isAngularRoute(Request $request): bool {
return str_starts_with($request->getPathInfo(), '/dist/');
}
Hot Module Replacement (HMR)
For development, use webpack-dev-server alongside Symfony’s built-in server:
symfony server:start --port=8000
npm run start # Angular CLI dev server on port 4200
Proxy API calls in angular.json:
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
}
}
Extension Points
entry_point config dynamically (e.g., per route):
<script src="{{ asset(app.angular_integration.entry_point_for_route(request.get('_route'))) }}"></script>
angular_integration:
assets_path: '%kernel.project_dir%/public/dist'
version: '{{ hash("md5", "contents-of-version-file") }}'
Then reference in Twig:
<script src="{{ asset('dist/app.' ~ parameter('angular_integration.version') ~ '.js') }}"></script>
Performance
HttpCache for API routes while letting Angular handle static assets.Vary: Accept headers for API responses to optimize caching.Testing
BrowserKit by simulating client-side navigation:
$client = static::createClient();
$client->request('GET', '/'); // Loads Angular entry point
$client->getCrawler()->filter('#app-root')->assertCount(1);
How can I help you explore Laravel packages today?