Installation
composer require davidjegat/jam-bundle
Add the bundle to config/bundles.php:
return [
// ...
DavidJegat\JamBundle\DavidJegatJamBundle::class => ['all' => true],
];
Configure jam.php
Place in config/packages/davidjegat_jam.yaml (or merge into config/packages/dev/jam.yaml for dev-only):
jam:
node_path: /usr/local/bin/node # Path to Node.js (required for dev)
output_dir: '%kernel.project_dir%/web/js' # Output directory for built JS
packages_dir: '%kernel.project_dir%/vendor/jam' # Cache for npm packages
requirejs_config: '%kernel.project_dir%/config/requirejs.config.js' # Custom RequireJS config
First Use Case: Install a Package
Define a jam.json in your project root (or config/jam.json):
{
"packages": {
"jquery": "3.6.0",
"backbone": "1.4.0"
}
}
Run the installer:
php bin/console jam:install
This downloads packages to vendor/jam and generates a requirejs.config.js.
Integrate with Twig
Use the jam_assets Twig function to include built JS:
{% jam_assets 'app' %}
<script src="{{ asset('js/app.js') }}"></script>
Project Structure
Organize JS modules in src/Resources/public/js/ (e.g., app/main.js, app/modules/user.js).
Use AMD format:
// app/modules/user.js
define(['jquery'], function($) {
return {
init: function() { /* ... */ }
};
});
Define Dependencies
Update jam.json to include local modules:
{
"packages": {
"jquery": "3.6.0",
"backbone": "1.4.0"
},
"modules": {
"app": ["jquery", "backbone", "./js/app/main"]
}
}
Build Process Run in development:
php bin/console jam:build --dev
For production (optimized):
php bin/console jam:build --prod
Twig Integration Dynamically load modules per route:
{% if app.user %}
{% jam_assets 'admin' %}
{% else %}
{% jam_assets 'public' %}
{% endif %}
Environment-Specific Configs
Use jam.yaml overrides for dev/prod:
# config/packages/dev/jam.yaml
jam:
requirejs_config: '%kernel.project_dir%/config/requirejs.dev.config.js'
Custom Build Hooks
Extend the bundle by overriding JamBundle's services or creating a custom command:
// src/Command/CustomJamBuildCommand.php
class CustomJamBuildCommand extends BuildCommand {
protected function configure() {
$this->setName('jam:custom-build');
// Add custom logic (e.g., post-build tasks)
}
}
Integration with Webpack (Hybrid Setup)
Use jam:build for vendor packages and Webpack for app-specific code, then merge outputs.
Node.js Dependency
Command "jam:install" requires Node.js.jam.node_path is correct. Test with:
node --version
Caching Issues
jam:install.output_dir manually or use:
php bin/console jam:clear-cache
RequireJS Path Conflicts
Script error for "jquery" (404).requirejs.config.js paths. Example:
paths: {
jquery: 'vendor/jam/jquery/jquery-3.6.0/jquery'
}
Symfony Asset Versioning
asset() URLs may break if output_dir isn’t web-accessible.output_dir is symlinked to web/ or use asset() with relative paths:
<script src="{{ asset('js/app.js') }}"></script>
Check Build Logs
Run with --verbose:
php bin/console jam:build --dev --verbose
Inspect requirejs.config.js
The generated config at config/requirejs.config.js is the single source of truth for paths and shims.
Use jam:list
Debug installed packages:
php bin/console jam:list
Custom Package Resolvers
Override DavidJegat\JamBundle\Resolver\PackageResolverInterface to fetch packages from private registries.
Post-Build Scripts
Subscribe to the jam.post_build event in a service:
// src/EventListener/JamBuildListener.php
class JamBuildListener {
public function onPostBuild(BuildEvent $event) {
// Example: Minify CSS after JS build
}
}
Dynamic Module Loading
Use the jam:add-module command to inject modules at runtime (e.g., for A/B testing):
php bin/console jam:add-module 'experiment' './js/experiment'
packages_dir Permissions
Ensure vendor/jam is writable by the web server user:
chmod -R 755 vendor/jam
Dev vs. Prod Output
The --dev flag skips optimization (e.g., no UglifyJS). Always test both modes.
Symfony Flex Compatibility
If using Symfony Flex, place jam.yaml in config/packages/ and merge with environment-specific files.
How can I help you explore Laravel packages today?