Bootstrap - Sass - Gulp - Toolchain

Great news :lol:

Is there any means by which to automatically publish the newly compiled CSS file to overwrite the current published asset? Deleting it by hand each time is a bit of a pain :rolleyes:

I just reference it in my AppAsset:


namespace frontend\assets;


use yii\web\AssetBundle;


class AppAsset extends AssetBundle

{

	public $basePath = '@webroot';

	public $baseUrl = '@web';

	public $css = [

    	'css/all.css',

	];

	public $js = [

    	'js/all.js',

	];

}



No need to mess around with publishing :)

I tell my Gulp tool chain to copy to my web dir and it works.

Ah yes, I am following your advice and am publishing directly to the web-accessible assets folder, rather than to a folder for an AssetBundle.

One thing that is still really annoying me is my inability to completely remove BootstrapAsset. Even when this bundle is set to FALSE in my config, it still publishes the folder, which is entirely needless as all those assets are not controlled by the developer (me!).

Is removing the BootstrapAsset bundle realistically achievable? I would imagine it is a dependency of of a number of extensions etc so if I did completely remove it, I would still have to keep an eye on extension asset dependency to remove the BootstrapAsset dependency?

I have this in frontend/config and backend/config:


    	'assetManager' => [

        	'bundles' => [

            	'yii\bootstrap\BootstrapAsset' => false,

            	'yii\validators\ValidationAsset' => false,

            	'yii\web\YiiAsset' => false,

            	'yii\widgets\ActiveFormAsset' => false,

            	'yii\bootstrap\BootstrapPluginAsset' => false,

            	'yii\web\JqueryAsset' => false,

    	],

	],// assetManager



It does not publish anything!

I then have to handle the js myself, thoughā€¦

My list of js to concat is:


[

	"vendor/bower/yii2-pjax/jquery.pjax.js",

	"vendor/bower/bootstrap/dist/js/bootstrap.js",

	"vendor/yiisoft/yii2/assets/yii.js",

	"vendor/yiisoft/yii2/assets/yii.validation.js",

	"vendor/yiisoft/yii2/assets/yii.gridView.js",

	"vendor/yiisoft/yii2/assets/yii.activeForm.js",

	"js/custom.js"

]



And then, finally, I just link to jQuery CDN on my main layout:


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>  

My assets folder is empty, except for the debug toolbar assets when itā€™s active.


'yii\bootstrap\BootstrapPluginAsset' => false,

That was the culprit! Youā€™ve been a tremendous help to me in getting the skeleton app leaned down to a point where I can start to develop it going forward, knowing I have just what I need and no moreā€¦ less files, less complications, less to look at and less time wasted!

Thanks!

Being in control is great :)

gulp sass, browser-synch and watches are awesome :)

What I have ended up doing is basically having a set up like this: -




/backend

	all.scss

/frontend

	all.scss

/common

	_*.scss



Which allows me to edit and recompile both the frontend and backend .scss with maximum code reuse/minimal waste. I edited my watch task to this: -




gulp.task('watch', function () {


    // this arguement is to be either 'frontend' or 'backend' to tell the function

    // which URL to load with browsersync and which application's published CSS path

    // needs to be watched for browsersync

    var appname = process.argv[4];


    strPublishedCssPath = (appname == 'frontend') ? strBootstrapPublishedFrontendCssPath : strBootstrapPublishedBackendCssPath;


    browsersync.init({proxy: "http://mywebsite." + appname + "/"});

    gulp.watch(strFrontendScssWatchPath, ['build-frontend']);

    gulp.watch(strBackendScssWatchPath, ['build-backend']);

    gulp.watch(strCommonScssWatchPath, ['build-frontend', 'build-backend']);

    gulp.watch([strPublishedCssPath + '/*']).on('change', browsersync.reload);

});



This allow me to begin the watch task with an argument telling the task whether it is the frontend or backend that is is to be synched with a command like this: -


gulp watch --appname frontend

It seems to be working well.

I am looking at jQuery and the yii.js files now. Are any of your assets being published at all now? For inclusion of asset files such as yii.captcha.js, yii.activeform.jsā€¦ are you allowing these to be attached by the widget or are you manually including these manually? jQuery I would just add in the layout file as itā€™s really needed through all pages.

None. :)

I am concatenating them with my custom js - see above for the json list of files to concatenate. (Post #25)

I also learned another trick with the asset manager:


    	'assetManager' => [

        	'bundles' => false,

    	],



As simple as that :)

But I donā€™t because I am too lazy to deal with the debug toolbar and other things that I turn off in production. ;)

Ah, OK, I didnā€™t pay enough attention to post #25. So you are basically just throwing all js scripts (asides from the the core jQuery itself) into a single file and publishing it on every page?

That is what I am currently doing, yes.

One could also create different script tasks and then reference different concatenated jsā€™s from different WebAssetā€™s. :)

I am not using enough js to warrant the additional work, to be honest.

Yeah, the frontend of my site at least will have minimal .js on it anyway. The backend will be a lot more complex I think but unless I can really justify atomizing things, I think I will just stick to a single .js file (plus the jQuery). It might have unneeded script in there for certain pages but 1) it keeps simple and 2) itā€™s less http requests for the page loading anyway.

Iā€™ve successfully compiled all my .js into one script and set all asset bundles to FALSE but I am having an issue with one thing.

What do you recommend in cases where the extension is publishing asset files directly?

Taking the raoul2000\widget\scrollup\ScrollUp widget as an example. In ScrollUp, you have this code: -




	/**

	 * @see \yii\base\Widget::run()

	 */

	public function run()

	{

		$this->registerClientScript();

	}


	public function registerClientScript()

	{


		$view = $this->getView();


		if (isset($this->theme)) {

			$path = $view->getAssetManager()->publish(__DIR__ . '/assets/css/themes');

			$view->registerCSSFile($path[1] . '/' . $this->theme . '.css');


			if ($this->theme == 'image' && isset($this->pluginOptions['scrollText'])) {

				$this->pluginOptions['scrollText'] = '';

			}

		}


		ScrollupAsset::register($view);


		$options = empty($this->pluginOptions) ? '{}' : Json::encode($this->pluginOptions);

		$js = "$.scrollUp($options);";

		$view->registerJs($js);

	}




Now, I have successfully added the .js and .css into my compiled files, so these assets are no longer required. For obvious reason I do not want to start making changes to the files within the vendor directory so it would seem the obvious choice would be for me to create a class like this: -





namespace developer\extensions\overwrites\scrollup


class Scrollup extends raoul2000\widget\scrollup\Scrollup

{


	/**

	 * This is an overwrite of the Scroll::registerClientScript() function

	 * for the purposes of disabling direct publishing of asset files

	 * as these assets have been included in the compiled site files

	 */

	public function registerClientScript()

	{


		ScrollupAsset::register($view);


		$options = empty($this->pluginOptions) ? '{}' : Json::encode($this->pluginOptions);

		$js = "$.scrollUp($options);";

		$view->registerJs($js);


	}

}




Then in my view file (which will be the main layout file), this: -




user developer\extensions\overwrites\scrollup\Scrollup



Would be the best way to do it?

Raol2000 is not following Yii best practices :)

Itā€™s funny that itā€™s ScrollUp, because I just use it directly - I initialize it ā€˜custom.jsā€™ and include jquery.scrollUp.js in my list of js files to concatenate.

And the style sheet is just dropped in the scss vendors dir.

But I think that, given the situation, overriding the widget is the best way to approach this rogue code.

Not as a big a coincidence as you may think - I was looking through your scripts JSON when I was developing my own and I saw you were using it. I actually wasnā€™t planning on doing any real ā€œdevelopmentā€ of the views until I had finished modelling the database and created the relevant models, views and controllers but I saw you were using it and I thought I might as well just throw it will while I was at it. I was originally simply doing the assets work to get the development functionality ready with a minimalised setup (no needless components) for when I started the view stuff.

I noticed Raol2000 wasnā€™t following best practice but I wasnā€™t sure about including it directly. However, Iā€™ve already included the asset files for the plugin and Iā€™ve been able to embed it with this: -




<script type="text/javascript">

	jQuery(document).ready(function () {			

		$.scrollUp(

			{"scrollText":"",

"scrollName":"scrollUp","topDistance":400,"topSpeed":3000,"animation":"slide","animationInSpeed":200,"animationOutSpeed":200,"activeOverlay":false});

    });

</script>



However, I see on http://www.yiiframework.com/doc-2.0/guide-index.html there is a version of it that uses glyphicon as opposed to a direct image. I would much rather use glyphicon or font-awesome in place of images where ever possible. Would you be able to show me how I could replicate that version?

Thanks.

I canā€™t off the cuff, but I can tell you that I use a base64 encoded image directly embedded in the CSS, because I donā€™t like images either.

Come to think of it: I do have an idea.

I am not sure that it will work but you can probably set the font to fontawesome and then set content in: before to the value of the glyph that you want -just copy it from the FA stylesheet. That might work.

Thatā€™s what I have done and itā€™s work perfectly. So now I have a folder structure of frontend, backend and common for both JS and SCSS compilation. I completely removed the ScrollToTop extension, placing the script to create the element in the jquery.scrollUp.js file itselfā€¦




jQuery(document).ready(function () {

    $.scrollUp({

        "scrollText":"",

        "scrollName":"scrollUp",

        "topDistance":400,

        "topSpeed":100000,

        "animation":"slide",

        "animationInSpeed":200,

        "animationOutSpeed":200,

        "activeOverlay":false});

});



As mentioned, the CSS was included as .scss for compilation purposes, and now looks like thisā€¦




#scrollUp {

    bottom: 20px;

    right: 20px;

    width: 38px;

    height: 38px;

    color: #333;

}


#scrollUp:before {

    content: "\f139";

    font-size: 43px;

    line-height: 41px;

    font-family: FontAwesome;

}



Iā€™ve included the font-awesome SCSS in my scss directories. As for now, as I am not yet actually using any .fa classes, the only .scss I have included is in my \scss\common\font-awesome\ directory and is just the very basicsā€¦




@font-face {

  font-family: 'FontAwesome';

  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');

  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');

  font-weight: normal;

  font-style: normal;

}


.fa {

  display: inline-block;

  font: normal normal normal 14px/1 FontAwesome;

  font-size: inherit;

  text-rendering: auto;

  -webkit-font-smoothing: antialiased;

  -moz-osx-font-smoothing: grayscale;

}




And this is being called in both my frontend\all.scss and backend\all.scss files: -


@import "../common/font-awesome/font-awesome.scss";

I kept the .fa in there as it will eventually be used without a doubt. Then I can simple add into any classes into the common, frontend or backend .scss on demand, rather than have the whole lot in there needlessly.

While I was at it, I also threw in the site.css (as .scss) into the common folder so now I only have a single .css file (all.css) for both the frontend and the backend apps. I also now only have a single .js file for both apps. All of which is in no small way a result of your help, so thanks again!

Well, all it took was gentle nudges - it has been great to watch your success :)