Images not found when deploying Sails JS to Heroku - javascript

I have developed a Sails.js application which is working as expected locally. However, when I deploy it to production (Heroku) the images in the "/assets/images/"-folder cannot be found (404).
I know there are some tasks that transfer the files in the "/assets"-folder to a ".tmp/public"-folder to be accessible when the application is being lifted. The .js- and .less-files are being loaded as expected, but not the images.
How can I make sure that the "/assets/images"-folder is being transferred to the public-folder as well?

I had this issue.
The main idea is to make an uploads folder in .tmp.
And make a symbolic link in public folder leading to uploads.
The problem is that Grunt rewrite all the content of '.tmp/public' every time we lift application.
Thus I made a proper Grunt task which simply creates symlink.
sudo npm install grunt-contrib-symlink
Create Grunt task in tasks/config. And name it smth like symlink.js.
module.exports = function(grunt) {
grunt.config.set('symlink', {
dev: {
src: '.tmp/uploads/**',
dest: '.tmp/public/uploads/'
}
});
grunt.loadNpmTasks('grunt-contrib-symlink');
};
And finally add task to tasks/register/compileAssets.js.
module.exports = function (grunt) {
grunt.registerTask('compileAssets', [
'clean:dev',
'jst:dev',
'less:dev',
'copy:dev',
'coffee:dev',
'symlink:dev'
]);
};

Related

Loading grunt tasks from a remote Gruntfile.js

In the root directory of a project, I'm trying to load Grunt tasks, and all the content of the file as well, from a remote Gruntfile.js, accessible through a network (web or internal network).
I've already tried several things (see below), first hosting the Gruntfile.js on a local Apache server for the tests.
Using the --gruntfile option
> /project/path> grunt --gruntfile=http://localhost/Gruntfile.js build
Reading "Gruntfile.js" Gruntfile...ERROR
Fatal error: Unable to find "/project/path/http://localhost/Gruntfile.js" Gruntfile.
Using the --base option
> /project/path> grunt --base=http://localhost/Gruntfile.js build
process.chdir(grunt.option('base') || path.dirname(gruntfile));
Error: ENOENT, no such file or directory
Creating a Gruntfile.js located at the root directory of my project, which contains only the following code :
module.exports = function (grunt) {
grunt.loadTasks( 'http://localhost/Gruntfile.js' );
};
The result was :
> /project/path> grunt build
>> Tasks directory "http://localhost/Gruntfile.js" not found.
Warning: Task "build" not found. Use --force to continue.
Aborted due to warnings.
Another try with the Gruntfile.js
module.exports = function (grunt) {
require( 'http://localhost/Gruntfile.js' )( grunt );
};
Gave me this :
> /project/path> grunt build
Loading "Gruntfile.js" tasks...ERROR
>> Error: Cannot find module 'http://localhost/Gruntfile.js'
Warning: Task "build" not found. Use --force to continue.
Aborted due to warnings.
Edit: It seems there is no way of loading tasks from a grunt file not located on the disk. I will find another solution.
I ran into the same problem and this is my solution. I hope it helps someone in the present/future:
Create a npm package to host the Gruntfile.js and upload it to a repository (I´am currently using Bitbucket) This is how my package.json looks like:
{
"name": "my-remote-gruntfile-package",
"private": true,
"version": "0.0.1"
}
Configure it in the package.json of your current project and install it using npm install or just run
npm install git+ssh://git#bitbucket.org:user/my-remote-gruntfile-package.git#0.0.1
Create a bash script (or windows bash equivalent) to cover the problem of changing Gruntfile.js location and setting current base path. This is to avoid passing --gruntfile and --base parameters on every execution (this step is not mandatory)
#!/bin/bash
grunt --base ./ --gruntfile ./node_modules/my-remote-gruntfile-package/GruntFile.js $1
Note: take care of relative paths used on your Gruntfile.js
Requiring a separate file should work, note that you shouldn't refer to it via localhost, but rather the location on disk, for example ./somedir/yourtask.js. Here's an example:
yourtask.js:
module.exports = {
// your task config goes here
};
Your Gruntfile.js:
module.exports = function(grunt) {
var externalFile = require('./somedir/yourtask.js');
grunt.initConfig({
// some random tasks go here
yourtask: externalFile
});
};
This should work but I'm not able to run it right now and you haven't posted what kind of info you have defined in your separate file. You can also have a function in there as well.

After modularizing an AngularJS app, how do you include the entire project in the index.html without having to type a ton of <script> tags

I've been learning Angular for awhile now and am looking into the best ways to modularize the application. I think my understanding of that is going pretty well, but I've looked around for awhile and can't seem to get a good answer as to how all of these .js files get included inside of the index.html without just manually typing out a bunch of tags. I've been looking into Grunt/Gulp and get how those are combining the entire app into one .js file, but for development I'm guessing you don't want to have to re-run grunt or gulp every time you want to update the app.
There are many different options: gulp, grunt, or webpack seem to be the most popular. I tend to use webpack the most these days.
A good setup will typically run a local node server, which will refresh the browser automatically every time you make a change to a file.
There are many yeoman generators that will set this all up for you, or you can find simple examples on github.
The basic idea is to
concatenate all your js files (in proper order so the module definitions go before controllers/services)
minify if for production
copy to a fixed path
include this single js file in your html
during development have your grunt/gulp script watch for changes in js files and re-run the above steps so you don't have to run the grunt/gulp task manually.
Now if you are using gulp here is how you would typically handle above steps
gulp.task('process-js', function () {
return gulp.src(jsFiles, {base: './'})
.pipe(gulpif(isProd, concat('all.min.js'), concat('all.js')))
.pipe(gulpif(isProd, uglify({mangle: true, preserveComments: 'some'})))
.pipe(gulp.dest(deployFolder + '/static/js'))
});
where jsFiles is an array of files/folders that contain your angular app js files
var jsFiles = [
'!static/js/**/*.js',
'!static/js/plugin/**/*.*',
'app/index/**/*module.js',
'app/index/**/*config.js',
'app/index/**/*ctrl.js'
];
Note: use ! prefix to exclude certain files/folders from processing.
isProd is just a flag that indicates whether you are preparing for production or development.
During development I also use BrowserSync to watch any changes to my js files and re-run the gulp task to prepare all.js. It also refreshes the page in browser automatically.
gulp.task('run', function () {
browserSync({
server: {
baseDir: deployFolder
},
open: true,
browser: ['google chrome'],
files: deployFolder + '/**/*',
watchOptions: {
debounceDelay: 2000
}
});
gulp.watch(jsFiles, ['process-js']);
});
gulp.task('default', function () {
runSequence(
'clean',
'run'
);
});
Gulp/Grunt to concat all your angular files.
Create 2 tasks :
a dev build task
concat to one file BUT don't uglify.
a distribution/production task which is the same as dev one but this one uglify the concatenated file.

Running grunt just opens up a Notepad file instead of actually running the tasks

I'm trying to create a basic Grunt file to execute some tasks.
Trouble is, when I execute grunt from within the directory of the project, a Notepad file opens, displaying the contents of grunt.js rather than actually running.
I've also tried naming the file Gruntfile.js but then I get a message
grunt-cli: The grunt command line interface. (v0.1.13)
Fatal error: Unable to find local grunt.
If you're seeing this message, either a Gruntfile wasn't found or grunt
hasn't been installed locally to your project. For more information about
installing and configuring grunt, please see the Getting Started guide:
and I've already installed grunt-cli.
The grunt.js and Gruntfile.js both look like:
module.exports = function(grunt) {
grunt.initConfig({
});
grunt.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) {
if (arguments.length === 0) {
grunt.log.writeln(this.name + ", no args");
} else {
grunt.log.writeln(this.name + ", " + arg1 + " " + arg2);
}
});
grunt.registerTask('default', []);
};
The problem was that I was missing a package.json file. I simply never created one.
I resolved the problem by running
npm init
to generate it
Even if grunt is installed globally, you also need to add it to your project - in your project directory, run:
npm install grunt --save-dev
Do not rename your task file (keeg Gruntfile.js), then running grunt should work fine.

Grunt Watch not working with file base set to subdirectory

I'm having an issue where Grunt Watch is not working with my subdirectory using Grunt. Here's my directory setup:
/home
--/repos
--/common
--/node_modules
-- gruntfile.js
-- package.json
And I've set the base manually to the home directory in my gruntfile:
grunt.file.setBase('../../');
I'd like to keep my gruntfile located in this directory for working with other folks on my team and not use multiple gruntfiles.
Running 'grunt' works just fine. However, when I have Grunt Watch running, I get an error when I update my files:
Waiting...OK
>> File "repos/common/js/controllers/UserCtrl.js" changed.
grunt-cli: The grunt command line interface. (v0.1.13)
Fatal error: Unable to find local grunt.
Here is the watch portion of my gruntfile:
watch: {
// js
js: {
files: [
'js/*.js',
'js/controllers/*.js',
'js/services/*.js',
'js/lib/*.js',
'm/js/*.js',
'm/js/controllers/*.js',
'm/js/services/*.js',
'm/js/lib/*.js',
'repos/common/js/controllers/*.js',
'repos/common/js/services/*.js',
'repos/common/js/lib/*.js',
],
tasks: ['concat']
},
// css
css: {
files: [
'repos/common/less/*.less',
'm/less/*.less',
'css/*.css',
'repos/common/css/lib/*.css',
],
tasks: ['newer:less', 'newer:cssmin', 'newer:concat_css']
}
}
What on earth am I not getting here? Any help would be super appreciated!
You missed installing the grunt module
The grunt-cli is a different module to the actual grunt. I think you should install grunt (that is what is meant with the local error message) at the local directory or above where your gruntfile.js is located.

Can I have multiple gruntjs files in my project for code organization?

I'm using gruntjs for my project and was wondering if it's possible to have multiple grunt.js files in my project? The reason I'm asking is that my project is organized like so:
grunt.js
|
|- project1
| |
| |-grunt.js
|
|- project2
|
|- project3 (etc..)
I want the top level grunt.js to build all the projects. However as the list of projects grow I don't want my top level grunt.js file to become huge. So I would like to organize it so that the top level grunt can call the project level grunt files to build them. Or if someone wants to just build project1, they can go to the project1 folder and run it's own grunt.js. Can this be done? If so, how do I call the other grunt files? If not, then what's an alternative solution other than having one huge grunt.js file? Thanks.
I recently solved this issue with a very simple solution.
I implemented grunt.config.merge(config) to replace grunt.initConfig(config). You can call it multiple times, and it will simply merge the config into a single config.
Update: As of Grunt v0.4.5, the grunt.config.merge function is built-in, so you no longer need to include it as a separate library.
This allows me to organize my config by feature.
I create a config file for each feature, such as desktop-javascripts.js, desktop-css.js, mobile-javascripts.js, mobile-css.js.
Also, they share common configuration in default-options.js, so I can specify compression settings and what not.
Example
Gruntfile.js:
module.exports = function(grunt) {
require('./default-options.js')(grunt);
require('./desktop-javascripts.js')(grunt);
require('./desktop-css.js')(grunt);
require('./mobile-javascripts.js')(grunt);
require('./mobile-css.js')(grunt);
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
};
desktop-javascripts.js:
module.exports = function(grunt) {
// Configure all JavaScript tasks:
grunt.registerTask('desktop-javascripts', [ 'concat:JS', 'jshint' ]);
grunt.config.merge({
concat: { 'JS': { files: allJS } },
jshint: { 'JS': { files: allJS } },
watch: { 'JS': { files: allJS, tasks: [ 'desktop-javascripts' ] } }
});
};
There's a grunt task called grunt-hub which seems to do what you want to do.
grunt-hub:
A Grunt task to watch and run tasks on multiple Grunt projects.
hub task
The hub task is for running tasks on multiple projects. It would like to know which Gruntfiles to use and which tasks to run on each Grunt project. For example if I would like to lint and test on every Grunt project one folder up:
I haven't used it, but it might meet your requirements. Also you might want to look into more lower level such as grunt-exec or creating your own tasks to spawn child processes.
I know this question might be old, but I want to clarify there is a way to organise your codes in a proper way.
To prevent having multi call like this:
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
Replace them with:
require('load-grunt-tasks')(grunt);
And use:
grunt-config-dir
To run the tasks from a folder.
To know more about it, check this out.

Categories

Resources