Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sails.js use different layout with different js libraries

I'm creating my first nodejs/sails.js project, I want to use 3 different layout for 3 different occasions:

frontend_layout.ejs
admin_layout.ejs
mobile_layout.ejs
  • In frontend_layout.ejs, I want to load bootstrap.css, jquery.js and bootstrap.js.
  • In admin_layout.ejs, I want to load bootstrap.css, angular.js and ui-bootstrap-tpls.js(angular-ui js library).
  • In mobile_layout.ejs, I want to load ionic.css and ionic.bundle.js

I have created 3 folders in sailsProject/views/ which are admin_pages, mobile_pages and frontend_pages, the 3 layout.ejs files reside in each of these folders respectively, but no matter which layout I load, it always include all the css/js files in assets/js and assets/styles. I know I need to do something to pipeline.js, but how exactly? I'm not efficient at grunt, so I would really appreciate if anyone could point me which config files need to be modified and how... Thanks!

like image 648
dulan Avatar asked Dec 12 '22 01:12

dulan


2 Answers

I wanted something very similar in my project, except I also wanted to take advantage of Sail's cool built-in ability to auto minimize/uglify javascript files for "sails lift --prod" in various layouts with different sets of javascript files. This answer only deals with the JS files, but you can make similar changes to support the same concept with your CSS files.

In my project I had 2 different layouts -- layout.ejs and layoutadmin.ejs. I created a new /assets/jsadmin folder which holds my admin javascript files. I left the sails existing /assets/js folder as-is to hold the javascript files for the public web pages.

My goal was for the /assets/js folder contents to be inserted between these tags (sails does this by default and these tags are used in the layout.ejs file):

<!--SCRIPTS-->
<!--SCRIPTS END-->

While the /assets/jsadmin folder contents was to be inserted between these tags (I made up these "custom" tag names and they are used in the layoutadmin.ejs file. I will add add support for this new tag in the rest of this answer):

<!--SCRIPTS_ADMIN-->
<!--SCRIPTS_ADMIN END-->

I created a full code sample demo of this here.

For development... (sails lift), I modified so sails would populate my custom tags with the assets/jsadmin js files upon lifting.

I modified tasks/pipeline.js by adding a new variable called jsAdminFilesToInject which is very similar to the existing jsFilesToInject except it collects the js files from the jsAdmin folder.

var jsAdminFilesToInject = [

  // Load sails.io before everything else
  //'jsAdmin/dependencies/sails.io.js',

  // Dependencies like jQuery, or Angular are brought in here
  'jsAdmin/dependencies/**/*.js',

  // All of the rest of your client-side js files
  // will be injected here in no particular order.
  'jsAdmin/**/*.js'
];

Note: I also had to export this new variable at the bottom of the pipeline.js file.

module.exports.jsAdminFilesToInject = jsAdminFilesToInject.map(function(path) {
  return '.tmp/public/' + path;
});

I modified tasks/config/sails-linker.js by adding a new devJsAdmin task where it looks for tags and calls the new .jsAdminFilesToInject added in the pipeline.js file above.

    devJsAdmin: {
        options: {
            startTag: '<!--SCRIPTS_ADMIN-->',
            endTag: '<!--SCRIPTS_ADMIN END-->',
            fileTmpl: '<script src="%s"></script>',
            appRoot: '.tmp/public'
        },
        files: {
            '.tmp/public/**/*.html': require('../pipeline').jsAdminFilesToInject,
            'views/**/*.html': require('../pipeline').jsAdminFilesToInject,
            'views/**/*.ejs': require('../pipeline').jsAdminFilesToInject
        }
    },

I Added a new task step to the tasks/register/linkAssets.js file which calls the devJsAdmin added above.

    'sails-linker:devJsAdmin',

To test, run sails in demo mode:

sails lift

Browse to http://localhost:1337/home - you will see it is using the layout.ejs template and viewing the source will show the following at the bottom (files pulled from js folder):

<!--SCRIPTS-->
<script src="/js/dependencies/sails.io.js"></script>
<script src="/js/jquery-1.10.2.js"></script>
<!--SCRIPTS END-->

Browse to http://localhost:1337/admin - you will see it is using the layoutadmin.ejs template and viewing the source will show the following at the bottom of the source (files pulled from jsAdmin folder):

<!--SCRIPTS_ADMIN-->
<script src="/jsAdmin/dependencies/jquery-1.10.2.js"></script>
<script src="/jsAdmin/knockout-3.3.0.debug.js"></script>
<!--SCRIPTS_ADMIN END-->

For production... (sails lift --prod), I wanted to do the same as development except I first wanted to concat and uglify the production javascript that goes in my new SCRIPTS_ADMIN tags.

I added a new jsAdmin section in the grunt tasks/config/concat.js file which pulls in the files from the previously added jsAdminFilesToInject in the pipeline.js to produce a concat/productionAdmin.js output file.

    jsAdmin: {
        src: require('../pipeline').jsAdminFilesToInject,
        dest: '.tmp/public/concat/productionAdmin.js'
    },

I added a new distAdmin section in the grunt tasks/config/uglify.js file which makes the concat/productionAdmin.js "ugly" by producing a new min/productionAdmin.min.js file.

    distAdmin: {
        src: ['.tmp/public/concat/productionAdmin.js'],
        dest: '.tmp/public/min/productionAdmin.min.js'
    }

I added a new prodJSAdmin section in the tasks/config/sails-linker.js file which adds the min/productionAdmin.min.js file between the SCRIPTS_ADMIN tags.

    prodJsAdmin: {
        options: {
            startTag: '<!--SCRIPTS_ADMIN-->',
            endTag: '<!--SCRIPTS_ADMIN END-->',
            fileTmpl: '<script src="%s"></script>',
            appRoot: '.tmp/public'
        },
        files: {
            '.tmp/public/**/*.html': ['.tmp/public/min/productionAdmin.min.js'],
            'views/**/*.html': ['.tmp/public/min/productionAdmin.min.js'],
            'views/**/*.ejs': ['.tmp/public/min/productionAdmin.min.js']
        }
    },

Finally, I called this new prodJSAdmin from the prod grunt task by adding a line in the prod.js file.

    'sails-linker:prodJsAdmin',

Run sails in production mode:

sails lift --prod

Browse to http://localhost:1337/home - you will see it is using the layout template and viewing the source will show the following at the bottom (using production.min.js):

<!--SCRIPTS-->
<script src="/min/production.min.js"></script>
<!--SCRIPTS END-->

Browse to http://localhost:1337/admin - you will see it is using the layoutadmin.ejs template and viewing the source will show the following at the bottom of the source (using productionAdmin.min.js):

<!--SCRIPTS_ADMIN-->
<script src="/min/productionAdmin.min.js"></script>
<!--SCRIPTS_ADMIN END-->
like image 177
JFar Avatar answered Dec 19 '22 09:12

JFar


By default, Sails automatically insert all your css files (assets/styles) into tags between STYLES and STYLES END and js files (assets/js) into tags between SCRIPTS and SCRIPTS END.

<!--STYLES-->
<!--STYLES END-->

.
.
.

<!--SCRIPTS-->
<!--SCRIPTS END-->

This is set in pipeline.js file. By default it has set to get all css files from assets/styles. You can find it in cssFilesToInject section.

'styles/**/*.css'

You can change it as you wish. you can comment or delete it simply. (keep in mind if you want to put some css files common to every layout you can put them in here.)

Same for the js files. By default it has set to get all js files from assets/js. You can find it in jsFilesToInject section. Remove or add js files according to your requirement. You can find more information about grunt globbing patterns in here which helps to understand filtering pattern.

So easiest thing you can do now is put your layout specific files out side those tags(STYLES and SCRIPTS)

For example look following code sample,

<!--STYLES-->
<!--STYLES END-->
<!--STYLES SPECIFIC TO THIS LAYOUT-->
<link rel="stylesheet" href="/styles/some_layout_specific.css">
like image 45
wvajirak Avatar answered Dec 19 '22 09:12

wvajirak