sourceComment in Gulp is showing path relative to computer, rather than folder - node.js

I have been doing sourceComments for a project I am working with and the comments that get outputted in the CSS so that I can find the correct scss file are showing paths that are relatvie to my computer
e.g.
/* line 39, /Applications/MAMP/htdocs/usaa/bare-minimum/framework/scss/settings/_typography.scss */
I would like this to be
/* line 39, settings/_typography.scss */
How would I accomplish this when this is my gulpfile.js (showing here the sass function)
var sassSrc = './framework/scss/*.scss';
var watchSrc = './framework/**/*.scss';
function doSass(cb) {
gulp.src([sassSrc, watchSrc], {
base: 'framework/scss'
})
.pipe(sourcemaps.init())
.pipe(sass({
errLogToConsole: true,
soureMap: 'scss',
sourceComments: 'map'
}).on('error', sass.logError))
.pipe(cmq())
.pipe(autoprefixer())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dev/css/'))
.pipe(cssmin())
.pipe(rename({
extname: '.min.css'
}))
.pipe(gulp.dest('dev/css/'))
.on('end', function() {
if (cb && typeof cb === 'function')
cb();
});
}
gulp.task('sass', doSass);

Unfortunately it's not possible with LibSass. Answer from node-sass member:
With sourceComments option, libsass emits diagnostics information for each selector it encounters.
It is supposed to be a raw debug info, hence the paths are not (relatively) resolved.
On a more serious note, this info emerges from core abstract syntax tree, where resolving canonical file paths will slow down the performance of the overall compilation.
For the browser dev tools aid, please use sourceMap option instead, as source-map carries relative paths.
Link to Github discussion
Discussion on libsass: Link

Related

Running multiple transforms on gulp/browserify bundle

I have a React component that I've been exporting to a bundle file. I've been successfully transforming it using babelify, however, I now would like to run envify on it. I can't seem to figure out how to run multiple transforms using browserify. I think it must be possible, but I can't tell if my syntax is slightly off or if I need to write a custom transform or if I should specify the transforms in my package.json. Here is the code in my gulp file:
var bundleComponent = function(bundler, source, component) {
//bundler is just browserify('./client/components/TVScheduleTab/render.js')
gutil.log('Bundling ' + component)
return bundler
//this throws an error
.transform(babelify, envify({
NODE_ENV: 'production'
}))
.bundle()
.on('error', function(e){
gutil.log(e);
})
.pipe(source)
.pipe(gulp.dest('output/'));
};
Have you tried chaining? Correct solution is in comments
var bundleComponent = function(bundler, source, component) {
//bundler is just browserify('./client/components/TVScheduleTab/render.js')
gutil.log('Bundling ' + component)
return bundler
//this throws an error
.transform(babelify)
.transform(envify({
NODE_ENV: 'production'
}))
.bundle()
.on('error', function(e){
gutil.log(e);
})
.pipe(source)
.pipe(gulp.dest('output/'));
};
Although this answer appears after the accepted answer, and the accepted somewhat covers the question, I wanted to make it clear without the need to navigate through the linked github issue.
Chaining, in particular with envify, should look like:
// NOTE: the "custom" part
var envify = require('envify/custom');
gulp.task('build-production', function() {
browserify(browserifyOptions)
.transform(babelify.configure(babelifyOptions))
.transform(envify({
NODE_ENV: 'production'
}))
.bundle()
.on('error', handleErrors)
.pipe(source('app.js'))
.pipe(buffer())
.pipe(uglify({ mangle: false }))
.pipe(gulp.dest('./build/production/js'));
});

Durandal optimization with Gulp and Gulp-Durandal not working

We are building an application with Durandal which is quite big at the moment and we currently looking into bundling all JS files located in the App folder into a main-built.js file. Pretty basic and usual stuff I guess.
I'm using Gulp with the Gulp-Durandal extension. Here our gulpfile :
var gulp = require('gulp');
var durandal = require('gulp-durandal');
gulp.task('build-portal', function () {
durandal({
baseDir: 'app',
main: 'main.js',
output: 'main-built.js',
almond: false,
minify: false
}).pipe(gulp.dest('app'));
});
And here's a snippet of our main.js file
require.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions'
},
shim: {
},
waitSeconds: 0
});
define('jquery', [], function () { return jQuery; });
define('knockout', [], function () { return ko; });
define('ga', function () { return ga; });
define(
["require", "exports", "durandal/app", "durandal/viewLocator", "durandal/system", "plugins/router", "services/logger", "modules/knockout.extensions", "modules/knockout.validation.custom"],
function (require, exports, __app__, __viewLocator__, __system__, __router__, __logger__, __koExtensions__, __koValidationCustom__) {
var app = __app__;
var viewLocator = __viewLocator__;
var system = __system__;
var router = __router__;
As you can see in the gulpfile, we do not want to use Almond but RequireJs instead, for some reasons almond isn't workin with our project and anyhow, we prefer RequireJs whether its bigger than almond at the end. That's where it look to brake. Running the command to build the main-built.js file took sometime but at the end I get the file built with everything in it.
The problem is that when I try to load the application, it is stuck to the loading screen. It doesn't go any further and there's no errors at all in the browser console.
I created a new project on the side to test if our code was somewhat faulty and found that it might not. You can found that project here :
https://github.com/maroy1986/DurandalGulpBundling
If I build that project with almond option to true, everything works fine but if I switch almound off to tell gulp to use RequireJs, I got the same behavior as our app. You got stuck at the loading screen, without any errors.
So here I am, I do read a lot on the subject but didn't found anything to solve this. Hope someone here already encounter these behavior and have a solution to share.
Thanks!
I had the same requirement and issue. It seems require.js wasn't calling the main module which will startup the Durandal app, that's why it's stuck in the loading screen. I was able to resolve it by implicitly calling the main module:
gulp.task("durandal", function() {
return durandal({
baseDir: "app",
main: "main.js",
output: "main-built.js",
almond: false,
minify: true,
rjsConfigAdapter: function(config) {
//Tell requirejs to load the "main" module
config.insertRequire = ["main"];
return config;
}
})
.pipe(gulp.dest("dist"));
});
I downloaded your project and tried building it with the latest versions of gulp and durandal. Initially it didn't build and gave me the following error:
TypeError: Cannot read property 'normalize' of undefined
This is a problem with the text-plugin of rjs and you can solve this by adding the following to your gulp-file (next to the almond, minify, output... properties):
rjsConfigAdapter : function(rjsConfig){
rjsConfig.deps = ['text'];
return rjsConfig;
}
Once I did that, the build finished and I could build with or without minify, almond and require and the application works fine.

I don't understand how to work Bower properly

I'm building a site and I've decided to use a bootstrap template for the back-end (admin tools and whatnot).
I like the look of sb-admin-2 (http://startbootstrap.com/template-overviews/sb-admin-2/) but I'ma bit confused how to practically employ this in my site.
I installed Bower and installed sb-admin using bower install startbootstrap-sb-admin-2
Now I have a folder called bower_components, and it's filled with all the relevant packages... However, these packages include the development files as well.
If I upload this to my site as is, 80% of it will be unnecessary source data.
I'm currently using Gulp with my project, but I don't yet see how the 2 are supposed to interact. Is there a gulp package for compiling the bower_components into 1 concise thing?
I'm new to this kind of workflow and I can't find the answers to the questions despite my efforts. Apologies if I sound like a total noob.
There's no pre-built gulp package that will pull in all your bower source files. You should write a task that pulls in just the files you need. Here's an example from a project I'm working on (simplified):
var scripts = [
'bower_components/timezone-js/src/date.js', // https://github.com/mde/timezone-js
'bower_components/jquery/jquery.min.js', // http://api.jquery.com/
'bower_components/jquery-migrate/jquery-migrate.js', // https://github.com/appleboy/jquery-migrate
'bower_components/jquery-ui/ui/minified/jquery-ui.min.js', // todo: include just the bits we need
'bower_components/jqueryui-touch-punch/jquery.ui.touch-punch.min.js', // https://github.com/furf/jquery-ui-touch-punch
'bower_components/jquery-cookie/jquery.cookie.js', // https://github.com/carhartl/jquery-cookie
'bower_components/jquery.expander/jquery.expander.min.js', // https://github.com/kswedberg/jquery-expander
'bower_components/jquery.transit/jquery.transit.js', // http://ricostacruz.com/jquery.transit/
'bower_components/select2/select2.min.js', // http://ivaynberg.github.io/select2/
'bower_components/fancybox/source/jquery.fancybox.pack.js', // http://fancyapps.com/fancybox/
'bower_components/lodash/dist/lodash.compat.min.js', // https://lodash.com/docs
'bower_components/underscore.string/dist/underscore.string.min.js', // https://github.com/epeli/underscore.string#string-functions
'bower_components/json2/json2.js', // https://github.com/douglascrockford/JSON-js
'bower_components/jquery-validation/dist/jquery.validate.min.js', // http://jqueryvalidation.org/documentation/
'bower_components/jquery-file-upload/js/jquery.iframe-transport.js',
'bower_components/jquery-file-upload/js/jquery.fileupload.js', // https://blueimp.github.io/jQuery-File-Upload/
'bower_components/DataTables/media/js/jquery.dataTables.js', // https://datatables.net/
];
gulp.task('scripts', function () {
return gulp.src(scripts, {base: '.'})
.pipe(plumber())
.pipe(sourcemaps.init({
loadMaps: false,
debug: debug,
}))
.pipe(concat('all_the_things.js', {
newLine:'\n;' // the newline is needed in case the file ends with a line comment, the semi-colon is needed if the last statement wasn't terminated
}))
.pipe(uglify({
output: { // http://lisperator.net/uglifyjs/codegen
beautify: debug,
comments: debug ? true : /^!|\b(copyright|license)\b|#(preserve|license|cc_on)\b/i,
},
compress: { // http://lisperator.net/uglifyjs/compress, http://davidwalsh.name/compress-uglify
sequences: !debug,
booleans: !debug,
conditionals: !debug,
hoist_funs: false,
hoist_vars: debug,
warnings: debug,
},
mangle: !debug,
outSourceMap: true,
basePath: 'www',
sourceRoot: '/'
}))
.pipe(sourcemaps.write('.', {
includeContent: true,
sourceRoot: '/',
}))
.pipe(plumber.stop())
.pipe(gulp.dest('www/js'))
});
I'm cherry-picking the source files I want, combining and minifying them, and dumping them into my public directory so that can be served to the client. You don't need to upload the bower_components folder to your production server; but it probably wouldn't hurt much either (it's not THAT big!).

Using Gulp to build requireJS project - gulp-requirejs

I am trying to use gulp-requirejs to build a demo project. I expect result to be a single file with all js dependencies and template included. Here is my gulpfile.js
var gulp = require('gulp');
var rjs = require('gulp-requirejs');
var paths = {
scripts: ['app/**/*.js'],
images: 'app/img/**/*'
};
gulp.task('requirejsBuild', function() {
rjs({
name: 'main',
baseUrl: './app',
out: 'result.js'
})
.pipe(gulp.dest('app/dist'));
});
// The default task (called when you run `gulp` from cli)
gulp.task('default', ['requirejsBuild']);
The above build file works with no error, but the result.js only contains the content of main.js and config.js. All the view files, jquery, underscore, backbone is not included.
How can I configure gulp-requirejs to put every js template into one js file?
If it is not the right way to go, can you please suggest other method?
Edit
config.js
require.config({
paths: {
"almond": "/bower_components/almond/almond",
"underscore": "/bower_components/lodash/dist/lodash.underscore",
"jquery": "/bower_components/jquery/dist/jquery",
"backbone": "/bower_components/backbone/backbone",
"text":"/bower_components/requirejs-text/text",
"book": "./model-book"
}
});
main.js
// Break out the application running from the configuration definition to
// assist with testing.
require(["config"], function() {
// Kick off the application.
require(["app", "router"], function(app, Router) {
// Define your master router on the application namespace and trigger all
// navigation from this instance.
app.router = new Router();
// Trigger the initial route and enable HTML5 History API support, set the
// root folder to '/' by default. Change in app.js.
Backbone.history.start({ pushState: false, root: '/' });
});
});
The output is just a combination this two files, which is not what I expected.
gulp-requirejs has been blacklisted by the gulp folks. They see the RequireJS optimizer as its own build system, incompatible with gulp. I don't know much about that, but I did find an alternative in amd-optimize that worked for me.
npm install amd-optimize --save-dev
Then in your gulpfile:
var amdOptimize = require('amd-optimize');
var concat = require('gulp-concat');
gulp.task('bundle', function ()
{
return gulp.src('**/*.js')
.pipe(amdOptimize('main'))
.pipe(concat('main-bundle.js'))
.pipe(gulp.dest('dist'));
});
The output of amdOptimize is a stream which contains the dependencies of the primary module (main in the above example) in an order that resolves correctly when loaded. These files are then concatenated together via concat into a single file main-bundle.js before being written into the dist folder.
You could also minify this file and perform other transformations as needed.
As an aside, in my case I was compiling TypeScript into AMD modules for bundling. Thinking this through further I realized that when bundling everything I don't need the asynchronous loading provided by AMD/RequireJS. I am going to experiment with having TypeScript compile CommonJS modules instead, then bundling them using webpack or browserify, both of which seem to have good support within gulp.
UPDATE
My previous answer always reported taskReady even if requirejs reported an error. I reconsidered this approach and added error logging. Also I try to fail the build completely as described here gulp-jshint: How to fail the build? because a silent fail really eats your time.
See updated code below.
Drew's comment about blacklist was very helpfull and gulp folks suggest using requirejs directly. So I post my direct requirejs solution:
var DIST = './dist';
var requirejs = require('requirejs');
var requirejsConfig = require('./requireConfig.js').RJSConfig;
gulp.task('requirejs', function (taskReady) {
requirejsConfig.name = 'index';
requirejsConfig.out = DIST + 'app.js';
requirejsConfig.optimize = 'uglify';
requirejs.optimize(requirejsConfig, function () {
taskReady();
}, function (error) {
console.error('requirejs task failed', JSON.stringify(error))
process.exit(1);
});
});
The file at ./dist/app.js is built and uglified. And this way gulp will know when require has finished building. So the task can be used as a dependency.
My solution works like this:
./client/js/main.js:
require.config({
paths: {
jquery: "../vendor/jquery/dist/jquery",
...
},
shim: {
...
}
});
define(["jquery"], function($) {
console.log($);
});
./gulpfile.js:
var gulp = require('gulp'),
....
amdOptimize = require("amd-optimize"),
concat = require('gulp-concat'),
...
gulp.task('scripts', function(cb) {
var js = gulp.src(path.scripts + '.js')
.pipe(cached('scripts'))
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(remember('scripts'))
.pipe(amdOptimize("main",
{
name: "main",
configFile: "./client/js/main.js",
baseUrl: './client/js'
}
))
.pipe(concat('main.js'));
.pipe(gulp.dest(path.destScripts));
}
...
This part was important:
configFile: "./client/js/main.js",
baseUrl: './client/js'
This allowed me to keep my configuration in one place. Otherwise I was having to duplicate my paths and shims into gulpfile.js.
This works for me. I seems that one ought to add in uglification etc via gulp if desired. .pipe(uglify()) ...
Currently I have to duplicate the config in main.js to run asynchronously.
....
var amdOptimize = require("amd-optimize");
...
var js = gulp.src(path.scripts + '.js')
.pipe(cached('scripts'))
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(remember('scripts'))
.pipe(amdOptimize("main",
{
name: "main",
paths: {
jquery: "client/vendor/jquery/dist/jquery",
jqueryColor: "client/vendor/jquery-color/jquery.color",
bootstrap: "client/vendor/bootstrap/dist/js/bootstrap",
underscore: "client/vendor/underscore-amd/underscore"
},
shim: {
jqueryColor : {
deps: ["jquery"]
},
bootstrap: {
deps: ["jquery"]
},
app: {
deps: ["bootstrap", "jqueryColor", "jquery"]
}
}
}
))
.pipe(concat('main.js'));
Try this code in your gulpfile:
// Node modules
var
fs = require('fs'),
vm = require('vm'),
merge = require('deeply');
// Gulp and plugins
var
gulp = require('gulp'),
gulprjs= require('gulp-requirejs-bundler');
// Config
var
requireJsRuntimeConfig = vm.runInNewContext(fs.readFileSync('app/config.js') + '; require;'),
requireJsOptimizerConfig = merge(requireJsRuntimeConfig, {
name: 'main',
baseUrl: './app',
out: 'result.js',
paths: {
requireLib: 'bower_modules/requirejs/require'
},
insertRequire: ['main'],
// aliases from config.js - libs will be included to result.js
include: [
'requireLib',
"almond",
"underscore",
"jquery",
"backbone",
"text",
"book"
]
});
gulp.task('requirejsBuild', ['component-scripts', 'external-scripts'], function (cb) {
return gulprjs(requireJsOptimizerConfig)
.pipe(gulp.dest('app/dist'));
});
Sorry for my english. This solution works for me. (I used gulp-requirejs at my job)
I think you've forgotten to set mainConfigFile in your gulpfile.js. So, this code will be work
gulp.task('requirejsBuild', function() {
rjs({
name: 'main',
mainConfigFile: 'path_to_config/config.js',
baseUrl: './app',
out: 'result.js'
})
.pipe(gulp.dest('app/dist'));
});
In addition, I think when you run that task in gulp, require can not find its config file and
This is not gulp-requirejs fault.
The reason why only main.js and config.js is in the output is because you're not requiring/defining any other files. Without doing so, the require optimizer wont understand which files to add, the paths in your config-file isn't a way to require them!
For example you could load a main.js file from your config file and in main define all your files (not optimal but just a an example).
In the bottom of your config-file:
// Load the main app module to start the app
requirejs(["main"]);
The main.js-file: (just adding jquery to show the technique.
define(["jquery"], function($) {});
I might also recommend gulp-requirejs-optimize instead, mainly because it adds the minification/obfuscation functions gulp-requirejs lacks: https://github.com/jlouns/gulp-requirejs-optimize
How to implement it:
var requirejsOptimize = require('gulp-requirejs-optimize');
gulp.task('requirejsoptimize', function () {
return gulp.src('src/js/require.config.js')
.pipe(requirejsOptimize(function(file) {
return {
baseUrl: "src/js",
mainConfigFile: 'src/js/require.config.js',
paths: {
requireLib: "vendor/require/require"
},
include: "requireLib",
name: "require.config",
out: "dist/js/bundle2.js"
};
})).pipe(gulp.dest(''));
});

gulp-sass, watch stops when invalid property name

watch stops when error messages occur.
stream.js:94
throw er; // Unhandled stream error in pipe.
^
source string:51: error: invalid property name
How I can keep watch running and just to tell me where is the error located.
grunt could deal with errors and doesn't need to stop,
styleSheet.scss:41: error: invalid property name
otherwise, I need to keep typing "gulp" in the command-line when an error occurs.
This answer has been appended to reflect recent changes to Gulp. I've retained the original response, for relevance to the OPs question. If you are using Gulp 2.x, skip to the second section
Original response, Gulp 1.x
You may change this default behavior by passing errLogToConsole: true as an option to the sass() method.
Your task might look something like this, right now:
gulp.task('sass', function () {
gulp.src('./*.scss')
.pipe(sass())
.pipe(gulp.dest('./'));
});
Change the .pipe(sass()) line to include the errLogToConsole: true option:
.pipe(sass({errLogToConsole: true}))
This is what the task, with error logging, should look like:
gulp.task('sass', function () {
gulp.src('./*.scss')
.pipe(sass({errLogToConsole: true}))
.pipe(gulp.dest('./'));
});
Errors output will now be inline, like so:
[gulp] [gulp-sass] source string:1: error: invalid top-level expression
You can read more about gulp-sass options and configuration, on nmpjs.org
Gulp 2.x
In Gulp 2.x errLogToConsole may no longer be used. Fortunately, gulp-sass has a method for handling errors. Use on('error', sass.logError):
gulp.task('sass', function () {
gulp.src('./sass/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
If you need more fine-grained control, feel free to provide a callback function:
gulp.task('sass', function () {
gulp.src('./sass/**/*.scss')
.pipe(sass()
.on('error', function (err) {
sass.logError(err);
this.emit('end');
})
)
.pipe(gulp.dest('./css'));
});
This is a good thread to read if you need more information on process-control: https://github.com/gulpjs/gulp/issues/259#issuecomment-55098512
Actually above anwsers doesn't work for me (Im using gulp-sass 3.XX). What really worked:
gulp.task('sass', function () {
return gulp.src(config.scssPath + '/styles.scss')
.pipe(sourcemaps.init())
.pipe(sass({ outputStyle: 'compressed' })
.on('error', sass.logError)
)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(config.cssPath))
});
In gulp-sass 3.x.x when I was using "sass.logError(err);" I constantly recive error that "this.emit('end'); is not a function". Now when I'm using:
.pipe(sass({ outputStyle: 'compressed' })
.on('error', sass.logError)
)
everything is working like a charm
In gulp "^2.0.0" the option errLogToConsole will no longer work. Instead gulp-sass has a built in error logging callback that uses gulp-util under the hood. Also, because gulp has some problems with killing the process on errors, if you are using with watch you will have to call this.emit('end')
https://github.com/gulpjs/gulp/issues/259#issuecomment-55098512
var sass = require('gulp-sass');
//dev
sass(config.sassDev)
.on('error', function(err) {
sass.logError(err);
this.emit('end'); //continue the process in dev
})
)
//prod
sass(config.sassProd).on('error', sass.logError)
A heads up for Gulp 3 users:
I liked #dtotheftp solution above, regarding gulp 2.x. Interestingly, it doesn't work unter Gulp3, at least not under #3.9.1:
.on('error', function(err){
sass.logError(err);
this.emit('end'); //continue the process in dev
})
gets me
TypeError: this.emit is not a function
at Function.logError (/depot/myproject/node_modules/gulp-sass/index.js:181:8)
Note, that the complaint is not coming from his this.emit() in the gulpfile but rather from the sass node-module, hence from the prior line.
This works for me:
.on('error', function(err){
gutil.log(err);
this.emit('end');
})
I do get all errors², and the watch never ends ;) (I am also using plumber() right after gulp.src(), which might help with that).
(Yes, the fix might be highly illogical, since sass.logError is said to be based on gutil...)
—
²also on undefined macros which went silent before on my setup for whatever reason.

Resources