sailsCasts

Learning about sails.js one screencast at a time.

sailsCasts Answers: Ep5 - Where Should I Put the Assets in My Sails Project?

| Comments

Transcript

Howdy and welcome back.

So I’ve seen a bunch of questions asking where should you put your assets in your sail’s project. In this episode I’m going to talk specficially about javascript and css assets.

So, Sails uses grunt to manage assets. And Grunt generically provides ways for you to automate repeititve tasks. Sails uses grunt for tasks like syncing files between a project folder structure and the server’s public folder, but as always, I’m getting ahead of myself.

The configuration of grunt is based upon a file called Gruntfile.js found in the root of your sails project. There’s a lot going on in this file, however, again I’m going to concentrate on the javascript and css assets.

Your Project’s Assets

When you first create a project, you have the option of using the --linker flag. I’m going to actually create two projects, one with the linker flag and one without. Let’s compare the two. Both have an /assets folder. But the project with linker, not surprisingly has a /linker folder and that’s within the /assets folder. In the linker example, an additional /templates folder is also created.

USING the --linker flag

1
2
3
4
5
6
/assets
  /images
  /linker
    /js
    /styles
    /templates

NOT USING the --linker flag

1
2
3
4
/assets
  /images
  /js
  /styles

The Server’s Public Folder

Okay, great we have a /linker folder, but so what? Well, let’s add some javascript and css to both projects and see what happens. I’ve replaced the index.ejs file in the `/views/home’ folder of both projects with some very basic mark-up.

1
2
3
<h1>Custom View</h1>
<div class="custom">
</div>

Next, I added jquery to the /js folder of both projects. I also added my own javascript file — custom.js to the /js/ folder.

1
2
3
4
$(document).ready(function() {
    $('.custom').append("<h1>Yes Irl, javascript is here and if I'm red css is working as well.</h1>");
    $('.custom').addClass('working');
});

Finally I added custom.css in the /styles folder:

1
2
3
.working {
  color: red;
}

If the javascript and css are being linked properly, this is what our page should look like.

The custom.js file appends some html to the div in the index.js file. Then it will add a new class working to the div which will trigger the css located in the custom.css file.

Let’s take a look at the project where we used the --linker flag first. I’ll start sails using sails lift. The first thing you’ll notice is that a hidden .tmp folder is created. This is the server’s public folder. Opening up this folder reveals files that have been sync’d with the /assets folder. So we can see that jquery.js, custom.js, and custom.css files have all been copied into the public folder. Next, I’ll open up a browser and enter localhost:1337. Our heading showed up, but something’s up with my javascript because the appended html isn’t showing up. Let’s take a look at the console. Okay, there’s our problem. Jquery isn’t being loaded. Let’s take a look at the page’s source. Jquery is there, however, it’s being loaded in the wrong order. You might be asking yourself, how, did those links make it into page in the first place. That’s where some addition Grunt magic happens. Let’s take a look at our layout.ejs file.

Here is where the javascript links have been placed. Notice the two tags SCRIPTS and SCRIPTS END.

1
2
<!--SCRIPTS-->
<!--SCRIPTS END-->

This is where Grunt will place links to any javascript files placed in the /assets/linker/js folder. Grunt will also do this for our css between thse two tags, the STYLES and STYLES END:

1
2
<!--STYLES-->
<!--STYLES END-->

Now you may have noticed these socket.io.js, sails.io.js, and app.js files that are being injected into layout.ejs. Not surprisingly these files have to do with socket.io and sails, however, for the purposes of this screencast we can ignore those files.

But we still have this ordering problem with jquery. To fix this we can go back into the Grunfile.js and towards the top of this file is where Grunt is cofigured to inject css and javascript into layout.ejs. I’m going to put a path to jquery below some other javascript files but before this default “catch-all” link and I say catch-all link because as you can see with these astericks, grunt is going to look at the linker folder and any folder underneath the linker folder it’s going to look for any files with the .js ending. It’s going to take those files and place them in between these two tags.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var jsFilesToInject = [

    // Below, as a demonstration, you'll see the built-in dependencies 
    // linked in the proper order order

    // Bring in the socket.io client
    'linker/js/socket.io.js',

    // then beef it up with some convenience logic for talking to Sails.js
    'linker/js/sails.io.js',

    // A simpler boilerplate library for getting you up and running w/ an
    // automatic listener for incoming messages from Socket.io.
    'linker/js/app.js',

    // *->    put other dependencies here   <-*

    'linker/js/jquery.js'

    // All of the rest of your app scripts imported here
    'linker/**/*.js'
  ];

So now jquery will be loaded before any other javascript files located in the assets/linker/js folder. Let’s restart the sails server and go back to the browser and reload the page. Great now links to both our javascript and css files are being injected correctly. And just to make sure let’s go back to the source. And yes, we can see here that jquery is now being loaded before custom.js.

So to sum it up, having the linker folder provides for the automatic injection of links to any javascript or css files that are placed in the ‘assets/linker/js’ or ‘assets/linker/styles’ folders. Grunt based upon Gruntfile.js injects the links in layout.ejs.

Now let’s look at the project that doesn’t have a linker folder. When I start the sails server for this project using sails lift, the hidden .tmp folder is also created. The javascript and css files are copied into the public folder this time without the /linker folder. I’ll open up a browser and again go to localhost:1337.

This time, however, we don’t have the appended text from the custom.js file nor the red color to the text from the custom.css file. Why is that? If we look at the layout.ejs file, you’ll notice that the STYLE and SCRIPT tags are missing. These are automatically inserted when using the linker flag. Therefore, grunt doesn’t have these tags to tell it where to put the javascript and css file paths.

We can “upgrade” this project simply by adding the tags in layout.ejs. We also need to remove the paths that were initially added to layout.ejs when the project was created. Now let’s go into Gruntfile.js and insert the path to jquery like we did in the linker example. Finally we’ll need to move the css and javascript assets we currently have under a /linker folder. Now when I start sails and open a browser, the appended html is displayed in red, just as we expected. Looking at the page source, the css and javascript were injected properly and in the correct order into the page.

I hope you found this helpful and thanks as always for watching.

Comments