Just started using assectic in my Symfony2 project and have it working quite well but can't see a nice easy way to include all the javascript files within a bundle.
The structure for my AppBundle
is
AppBundle
- Controller
- Resources
- views
- public
- js
- Model
- User.js
- View
- Dashboard.js
- Bundle.js
- Router.js
My current code to compile this is
{% javascripts '@AppBundle/Resources/public/js/*' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
Which dumps out
<script src="/js/d356fea_part_1_Bundle_1.js"></script>
<script src="/js/d356fea_part_1_Router_2.js"></script>
So how can I get it to include all the javascript files in the sub folders?
Also is it possible to change the name of part_1
? Would love that to say AppBundle
during development.
After much research and playing this isn't possible with Assetic. I had to drop Assetic from the project for this reason and the fact it's too slow to update files which was causing problems for the front end developers.
Not really a proper answer but as it's the only solution I could find in a short amount of time I ended up hacking a solution together.
We now have a JSON config file like so:
{
"lib": {
"cwd": {
"vendor": "app/Resources/vendor"
},
"files": [
"%vendor%/jquery/dist/jquery.min.js",
"%vendor%/underscore/underscore-min.js",
"%vendor%/backbone/backbone-min.js"
]
},
"app": {
"cwd": {
"app": "app/Resources/public/js",
"AppBundle": "src/AppBundle/Resources/public/js"
},
"files": [
"%app%/*.js",
"%AppBundle%/*.js"
]
}
}
Then use grunt-contrib-symlink
to symlink these directories into the web
directory.
symlink: {
expanded: {
files: function () {
var symlinks = [];
Object.keys(js).forEach(function (key) {
var file = js[key];
Object.keys(file.cwd).forEach(function (name) {
symlinks.push({
src: [file.cwd[name]],
dest: 'web/js/' + name
});
});
});
return symlinks;
}()
}
},
Then we have a simple twig function which will pull this apart and find all the filenames to include them each individually inside the development environment.
class AssetService
{
protected $rootDir;
public function __construct($rootDir)
{
$this->rootDir = $rootDir;;
}
public function getJavascriptFiles($ref)
{
$output = [];
$data = json_decode(file_get_contents(realpath($this->rootDir . '/Resources/config/include.json')), true);
$paths = [];
foreach ($data[$ref]['cwd'] as $key => $path) {
$paths['%' . $key . '%'] = $this->rootDir . '/../' . $path;
}
foreach ($data[$ref]['files'] as $file) {
$output = array_merge($output, str_replace(
$paths,
array_keys($data[$ref]['cwd']),
$this->globRecursive(str_replace(array_keys($paths), $paths, $file), GLOB_NOCHECK)
));
}
return $output;
}
protected function globRecursive($pattern, $flags = 0)
{
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
$files = array_merge($files, $this->globRecursive($dir . '/' . basename($pattern)));
}
return $files;
}
}
Then in development we have the output which looks something like this:
<script src="/js/vendor/jquery/dist/jquery.min.js"></script>
<script src="/js/vendor/underscore/underscore-min.js"></script>
<script src="/js/vendor/backbone/backbone-min.js"></script>
<script src="/js/AppBundle/Bundle.js"></script>
<script src="/js/AppBundle/Router.js"></script>
<script src="/js/AppBundle/Collection/Products.js"></script>
<script src="/js/ProjectsBundle/Model/Project.js"></script>
<script src="/js/AppBundle/View/Product/Index.js"></script>
And after uglifying the files with Grunt using the same logic, in production we have:
<script src="/js/lib.js"></script>
<script src="/js/app.js"></script>
Bit hacky, but it's instant updates and keeps the PHP production environment completely unaware of the front-end assets.