Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 4, include assets from vendor directory

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

like image 879
snipershady Avatar asked Jan 26 '18 19:01

snipershady


2 Answers

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') }}.

like image 85
msg Avatar answered Sep 20 '22 13:09

msg


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

like image 45
Prof Avatar answered Sep 20 '22 13:09

Prof