In Sitefinity WebForms you have a ResourceLinks control allowing you to combine multiple, but what do you use in MVC layouts?
I'm not sure if the razor helper #Html.StyleSheet will do the job?
Adding all the CSS files to the Global folder in App_Data\Sitefinity\WebsiteTemplates[template_folder]\App_Themes[theme] will automatically add them to the site, but won't combine them.
We're working with Sitefinity 8.x and looking for a definitive way to compress and combine JS and CSS, but the pickings seem slim.
With the move from webforms to mvc, Sitefinity didn't include specifically introduce a new bundler or something so you're left with essentially 2 default options, but they've seemed to have opted for approach #3.
1) Use .less and .sass to pre-process as part of your build process.
So in your theme folder you would have a global.less (or scss or sass) that essentially combines them using the #import directive.
Install a VisualStudio extension like Mad's Kristensen Bundler and Minification VS Extension (previously part of WebEssentials) and then define in the VS settings that it should compile and minify on build.
Then every time you build or publish, your one bundled-and-compressed .min.css will be available for Sitefinity.
2) Second option would be to use default ASP.NET Web Optimization.
Where you define static bundles in VisualStudio and then use these bundles by means of #Styles.Render or #Scripts.Render to output them.
3) Lastly a new way has been added with the new Feather approach, which uses the current fashionable approach of Grunt to bundle and optimize your styles and scripts.
In the /ResourcePackages folder you'll already see a gruntfile.js file which has a task you can run which can then compile (and can be extended to prefix, bundle, minify, etc) your .sass into a .min.css which you can then add to your solution.
A sample can be seen here (https://github.com/Sitefinity/feather-packages/blob/master/Bootstrap/gruntfile.js)
I'd use a combination of the above approach to receive the maximum result with Sitefinity where you use option 1 to have VS build out your core/base CSS and JS and then include them using Web.Optimization.
Any additional page or widget related styles or JS can then be included afterwards manually through the css widget which gets compiled through option number 3.
Once you get more familiar with this new approach you can create and load optimized .css and .js on demand - even using a RequireJS approach to load them depended on the widget dragged and dropped on the page. RequireJS might seem out-dated given the latest gadgets and gizmo's but with v9.0 its still being used by Sitefinity itself to add inline-editing functionality.
Let me know if you need more info on option 3, I'm happy to extend my answer with some code snippets, or sample scripts on how I've tailored them.
Related
I created a small vue.js library that is using scss for styling and published that as npm package. It works well with a default theme included into the package. But what if I would like to provide a custom theme from the application that consumes that npm package, how would you do that?
The source for a very basic version of the library is here: https://github.com/gwildu/gwi-vue-components
The idea is, that you would copy paste the styling folder somewhere (e.g., into your application directory or into another npm package) and configure the library package to import from that copyied directory.
I did some investigation myself and found that there is a big discussion about having dynamic imports in sass since years. This issue (open since 2013) claims to add such a feature (they call it load). Not sure, how actively sass is still developed and when this feature will be supported. For now I see 3 possible solutions:
move to LESS as it supports dynamic imports. Semantic UI gives you a hint about how theming could be done in LESS
It is possible to import from relative paths in SASS. That way you are also able to import from a parent directory of your package root directory (your application directory) like, e.g., #import '../../theme/index';. You would support somewhere in your package an example of a theme that the consumer then would have to copy to, e.g., the root directory of his application and adjust it to his needs. In your package you would then import the theme from that directory in the consumers application folder. The downside is, that the package would not work out of the box
You have a default theme in your package and you add some instructions into the readme how the user can override that theme in a build script. The consumer would have to copy the default theme to his application directory, adjust it to his needs and in the build script he would replace the theme in, e.g., node_modules/your-library-package-folder/theme/ by the theme in your application folder.
To be complete here is the approach with a dynamic import (that is not yet supported by SASS):
In your main theme file in the library package (that would be imported by the components) you would do a relative import of kind of a config file from the consumers application folder like in approach 2 (see above) but that config file yould not contain the theme but only the import path of the theme in a variable. that variable then would be used by the package main theme file to import the theme. For making the library work out of the box, I guess there would be a way to have a default theme as backup if the config file in the consumers directory would not exist (not tested)
Update:
I tried approach 3 but failed to get something useful. The issue with that approach is that you would have to somehow sync your custome theme with the default theme when you update the library to a higher version which might get too complex to handle in a reasonable way. Then I tried to use the overwrite feature of SASS as described here: How to overwrite SCSS variables when compiling to CSS which led me to approach
In your library component you first import a file with possible custom variables and you declare your variables in the library as default.
The issue with that approach is that SASS does not support optional imports. The file with the custom variables have to exist somewhere. So if the library updates you again have to sync your custom theme files for each component / file that was changed in the library. Apparently SASS also don't want to support such a feature in the future: https://github.com/sass/sass/issues/779 which is sad, as it seems to me an essential feature for being able to do theming without a highly complex build step.
Overall, it seems SASS itself is making every effort to prevent a simple theming approach which makes me think of moving back to LESS again. Not having a simple way for static theming in SASS in my opinion outweight the cons of not having an easy way to define custom functions in LESS.
I'm having a hard time trying to set up dojo build in my project.
Basically, I have my js folder with all my custom widgets and components. I simply want to combine all javascript files form js folder into one single file.
dojo sources are located outside this folder. The structure looks similar to this:
/public
/prod
/dojo-1.9
/dijit
/dojo
/dojox
/js
myScript1.js
myScript2.js
Do you have any idea on how should I configure the package.json and profile.js? The documentation doesn't seem to help since all I am getting is an output folder with the same contents as the js folder (no javascript is merged).
You can start by reading this article:
https://dojotoolkit.org/reference-guide/1.10/build/simpleExample.html
It provides a simplified overview of dojo build system.
Additional there is dojo boilerplate with a sample of folder structure and profile.js configuration for quick start here:
https://github.com/csnover/dojo-boilerplate
I definitely suggest you to use the boilerplate as start for your project as it simplify a lot initial configurations.
Could someone explain the right approach in managing assets in Laravel 5?
For example, let's imagine I want to install some plugins using bower. The recommended way, as I got it, to keep all files into /vendor/bower_components. So I got some css, some images, fonts and javascript files withing the plugins.
Also I have a "app.less", where I import everything I need, like #import ('../../../vendor/bower_components/someplugin/somestyle.css'). The problem though that I don't have images/js/fonts in my public directory. Okay, I saw that you can use gulp copy function. However, when the number of plugins is getting higher, how I am supposed to manage where each plugin keeps its pictures or other files?
Actually I wanted to try semantic ui. I've downloaded it with bower. I know nothing about semantic ui, but there is a dist folder with semantic-ui.css. Also there are some fonts files withing themes/basic/assets/fonts. If I just copy it to public, it'll be public/themes/basic/assets/fonts. Then I import semantic-ui.css into my app.les and it'll find necessary fonts. What if I have some other plugins, it'll become unbearable to manage it all.
What is the typical workflow for this problem? The most simple way is just something like put everything into public and include it manually using <link> and <script> tags, but it'll require a lot of queries.
And why it's bad to keep all bower_components inside public? On the analogy of composer, we don't have autoloader for bower, so there is a mess of assets.
You are correct in the recommended place to put bower_components. It's not recommended to put bower_components in the public directory because it contains ALL the files in that specific package, not just the file you need to include in your HTML.
Since your talking about Laravel5, it is recommended to utilize laravel-elixir to manage assets. http://laravel.com/docs/5.0/elixir which utilizes gulp and can compile less, sass or various other files. I don't have any experience with semantic ui, but it looks to be similar to bootstrap. Without a SaaS or Less version available on npmjs.org you would need to copy the necessary files to your public directory. Elixir provides a simple way to copy files or whole directories from bower_components to your public directory.
The easiest way to include all the files needed without a ton of or is to use saas or less.
Personally what I do is this using node
var elixir = require('laravel-elixir');
var nodeDir = './node_modules/'; //This is the node directory(base directory) where all vendor files are downloaded in your case might be different
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Sass
| file for our application, as well as publishing vendor resources.
|
*/
elixir(function(mix) {
mix the styles and copy fonts to my public/css folder
mix.styles([
'bootstrap/dist/css/bootstrap.css',
'font-awesome/css/font-awesome.css'
], './public/css/app.css', nodeDir)
.copy(nodeDir + 'font-awesome/fonts', 'public/fonts')
.copy(nodeDir + 'bootstrap/fonts', 'public/fonts');
//mix javascript from node directory and output to public/js/ folder
mix.scripts([
'jquery/dist/jquery.js',
'bootstrap/dist/js/bootstrap.js'
], './public/js/app.js', nodeDir);
});
What advantages does compiling the LESS files have over just git cloning the Bootstrap Repo and copy/pasting various bootstrap.css files from there?
With LESS compiled Bootstrap you can get a customized and minified CSS file exclusive for your requirements (classes and colors). It is just performance, it reduce file size and petitions to the web server, principally.
Take a look to Bootstrap online LESS compiler (http://getbootstrap.com/customize/) to view all the variables you can choose.
Is it possible to use Dojo build without the need to modify JavaScript files?
The article dgrid and Dojo Nano Build provides the instruction to create the build, but it requires adding the following line into JavaScript file, which initializes the application:
require(['dgrid/dgrid'], function () {
(replacing 'dgrid/dgrid' with your build module name).
However, it is very problematic when using build for own modules, because, of course, in development mode the require with own layer can't be included, otherwise the modifications made to own modules wouldn't be visible. But in production mode this line must be added.
So either you must modify the file manually before production build, or write a script that would modify the file during the build. Both are very error-prone.
Is there a better way to achieve that result? Is it possible for Dojo to recognize that the build is provided and should be used, instead of loading each module separately?
The following line of code can be included in both development and production modes.
require(['dgrid/dgrid'], function () {
I describe the reasons why in my answer here.
What you need to do is configure Dojo differently based on what environment.
In a blog post that I wrote, I describe this in more detail. The following summarizes the post:
I create three modes: Production, Uncompressed, and Development.
Development
When developing code, I will have the js source linked into the web server and the Development mode will point to the dojo.js file and the raw css file(s). The browser will load modules that I need using xhr. And I point to the top level css files which import other css files. The result is that a lot of requests will be made to the server and the loading of the page will be noticeably slow. The benefit is that you can see development changes without having to do a full build.
Production
Production mode points the main dojo file at the dojo.js that is built using the build tool. I also create <script> elements for the other layers that are needed in the page. I point the css to the built css files which the build tool has inlined the imported css. The page loads quickly, but it is difficult to debug
Uncompressed
Similar to production, but I point to the .uncompressed.js files. Production and Uncompressed are available in the released version of our software. I use uncompressed when trying to troubleshoot an issue in a production environment. The value of this mode is dwindling as the developer tools are better supporting compressed javascript (ie source maps, etc.)
Server side
The default mode is Production, but I use a query parameter to switch modes. I also store the current mode in the session, so that I only have to set the mode once to change it. Subsequent pages will run in the changed mode, until I change it back.
Here is a java implementation of this code.