I would like to load vendor assets, downloaded with composer inside vendor directory, from my twig template.
Using a relative path is one solution (in this example I'm going to include bootstrap css, but the same problem is for any other libs required from composer, as jQuery, jQueryUI etc. )
<link rel="stylesheet" href="{{ asset('../vendor/twbs/bootstrap/dist/css/bootstrap.min.css') }}" >
Symfony docs suggest to use asset:install in order to generate a symlink from vendor directory to public, but I was unable to understand how it works. assets:install -h wasn't so clear to let me understand how to link a specific vendor path to the public directory.
Creating a simlink with
ln -s /path/of/vendor/lib /path/public/dir
works fine but, symlinks created will be deleted every time I look for an update with composer.
Any idea about "a best practice" to include assets from vendor directory?
Thank you
The reason why you can't tell the assets:install
to link and arbitrary vendor directory is that the command is designed to loop through the list of installed bundles and link a well-known directory (Resources/public
) directory if it exists. It relies on both the short bundle name and the directory existing, so it can only work with symfony bundles, there's no support for other libraries like bootstrap or jquery. (Link to current command source).
The recommended way to handle frontend libraries nowadays is encore.
In a situation where that's not possible, you could use composer scripts. I wouldn't call this "best practice", might end up being more trouble than it's worth but is an option you can consider.
You would create a shell, php script or console command where you basically replicate the functionality of assets:install
to link your library assets. You will still need to manually update the script when you install a new library, but you can configure it to automatically run after installing or updating packages.
Copy this simple sample bash script into you project directory, name it install_vendors.sh
:
#!/bin/bash
BASE_PATH=`pwd`
PUBLIC="public"
if [ "$1" != "" ]; then
PUBLIC=$1
fi;
PUBLIC=${BASE_PATH}/${PUBLIC}/vendor
VENDOR=${BASE_PATH}/vendor
rm $PUBLIC -rf
mkdir $PUBLIC
function link_asset
{
SOURCE_DIR=${VENDOR}/$1
TARGET_DIR=${PUBLIC}/$2
ln -s $SOURCE_DIR $TARGET_DIR
}
link_asset twbs/bootstrap/dist bootstrap
Add it to the scripts
section of composer.json
and the auto-scripts
:
"scripts": {
"vendors:install": "bash install_vendors.sh",
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
"@vendors:install"
},
// ...
}
You can also execute it at any time with composer run vendors:install
.
Then include them in your twig files: {{ asset('vendor/bootstrap/css/bootstrap.min.css') }}
.
In terms of 'Best Practice', I generally use npm with gulp or something to that effect, which generates distribution css and js files that are output to a designated file in public/
.
Here's an example from a recent project package.json
file
{
"devDependencies": {
"bootstrap": "^4.1.3",
"gulp": "^4.0.0",
"gulp-concat": "^2.6.1",
"gulp-sass": "^3.1.0"
},
"scripts": {
"compile:styles": "gulp styles"
}
}
Rather run npm install --save-dev bootstrap gulp gulp-concat gulp-sass
to get the latest versions etc.
And you'll need this gulpfile.js
too
var gulp = require('gulp');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
gulp.task('styles', function(){
return gulp
.src([
'app/Resources/sass/main.scss',
])
.pipe(sass({outputStyle:'compressed', includePaths: ['node_modules']}).on('error', sass.logError))
.pipe(concat('styles.min.css'))
.pipe(gulp.dest('public/css'));
});
Once setup, you can run npm run compile:styles
from the console and the app/Resources/sass/main.scss
SASS file will be pre-processed, minified and output to public/css/styles.min.css
.
Note that the gulp file includes the node_modules folder so you can import bootstrap inside the main.scss
file, e.g.
$primary: #55a367;
@import 'bootstrap/scss/bootstrap';
From a twig template:
<link rel="stylesheet" type="text/css" href="{{ asset('css/styles.min.css') }}">
I generally commit both the main.scss
and styles.min.css
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With