Grunt and Stylus or RequireJS subtasks - requirejs

It seems to me that I've missed something. Is there any possibility to make subtasks for Stylus or RequireJS within Grunt? I mean something like that:
grunt.initConfig({
stylus: {
dev: {
compile: {...}
},
prod: {
compile: {...}
}
}
});
For me it doesn't work. However when I write:
...
stylus: {
compile: {...}
}
...
it work fine, creates file and so on... So what am I doing wrong?

Grunt tasks run in the next format:
taskname: {
subtaskname: {
// options
}
}
So in order to make it work, you don't need to put the compile object within your dev and prod subtasks.
stylus: {
dev: {
// options
},
prod: {
// options
}
}
Best regards.

Related

Different builds based on targeting client vs server code

I currently have 2 separate webpack builds for server rendered vs client rendered code. Is there an easy way to change the build output based on server/client build?
For example something like this:
// Have some code like this
if(is_client){
console.log('x.y.z')
} else {
server.log('x.y.z')
}
// Webpack outputs:
// replaced code in client.js
console.log('x.y.z')
// replaced code in server.js
server.log('x.y.z')
Have you tried anything like this?
// webpack.config.js
module.exports = () => ['web', 'node'].map(target => {
const config = {
target,
context: path.resolve('__dirname', 'src'),
entry: {
[target]: ['./application.js'],
},
output: {
path: path.resolve(__dirname, 'dist', target),
filename: '[name].js'
},
modules: { rules: ... },
plugins: [
new webpack.DefinePlugin({
IS_NODE: JSON.stringify(target === 'node'),
IS_WEB: JSON.stringify(target === 'web'),
}),
],
};
return config;
});
// later in your code
import logger from 'logger';
if (IS_NODE) {
logger.log('this is node js');
}
if (IS_WEB) {
console.log('this is web');
}
how the compilation works?
// client.bundle.js
import logger from 'logger';
// DefinePlugin creates a constant expression which causes the code below to be unreachable
if (false) {
logger.log('this is node js');
}
if (true) {
console.log('this is web');
}
Finally you will produce your build in production mode, so webpack will include a plugin called UglifyJS, this has a feature called dead code removal (aka tree shaking), so it will delete any unused/unreachable code.
and the final result will look like:
// node.bundle.js
import logger from 'logger';
console.log('this is node js');
//web.bundle.js
console.log('this is node js');

Loading CreateJS with RequrieJS “shim” dosen't work

I have made requirejs work for my own modules (with define), but I'm not able to use shim for createjs. I've gone through countless examples and ended up using this: https://github.com/CreateJS/EaselJS/wiki/Using-easeljs-and-tweenjs-with-requirejs, but I'm getting net::ERR_ABORTED error
My module:
define(function (require) {
var createjs = require('createjs');
var start = function () {
var canvas = document.getElementById('canvas');
var stage = new createjs.Stage(canvas);
}
return {
start: start
};
});
My configuration:
require.config({
shim: {
easel: {
exports: 'createjs'
}
},
paths: {
easel: 'libs/easeljs.min'
}
});
I finally found the answer somewhere else; it should be:
require('libs/createjs');
not:
var createjs=require('libs/createjs');
As c

unable to run a grunt command

I am using this in gruntfile.js.
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
sass: {
options: {
sourceMap: true
},
dist: {
files: {
'css': 'scss/*.scss'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass'); // Load tasks
grunt.registerTask('default', ['sass']); // Register Task as Default
}
But it is giving me an error when I run this command
Task "sass" not found
Please tell me where am i doing it wrong.
I think you are missing task registration in the beginning of gruntfile
require('load-grunt-tasks')(grunt);
The documentation for using grunt-sass can be found at https://github.com/sindresorhus/grunt-sass/blob/master/readme.md

magento2 add new grunt task

I'm trying to create new grunt task for generating sprites for magento2. I'm using grunt-spritesmith plugin for that. In Gulpfile.js I have mapped sprite task to grunt-spritesmith in JitGrunt config:
require('load-grunt-config')(grunt, {
configPath: path.join(__dirname, configDir),
init: true,
jitGrunt: {
staticMappings: {
usebanner: 'grunt-banner',
sprite: 'grunt-spritesmith'
}
}
});
in dev/tools/grunt/configs I made a config file sprite.js with contents:
'use strict';
module.exports = {
sprite: {
all: {
src: 'app/design/frontend/vendor/default/web/images/spritesheets/*.png',
dest: 'app/design/frontend/vendor/default/web/images/spritesheets.png',
destCss: 'app/design/frontend/vendor/default/web/css/source/_sprites.less'
}
}
};
But grunt sprite gives me
>> No "sprite" targets found.
Or if in different configurations I'm able to register sprite task, I'm not able to pass config with src, dest and destCss params.
You have not include task name. This works:
'use strict';
module.exports = {
all: {
src: 'app/design/frontend/vendor/default/web/images/spritesheets/*.png',
dest: 'app/design/frontend/vendor/default/web/images/spritesheets.png',
destCss: 'app/design/frontend/vendor/default/web/css/source/_sprites.less'
}
};

RequireJS - Manually bundling some libs together

I'm trying to migrate a site to use RequireJS to manage it's JS dependencies. Also I want to bundle some libs together.
Currently we are building a base.min.js that comprises underscore, jquery, bootstrap and backbone. They are used all over our site and thus it makes sense to serve them together.
Nevertheless, I think we should have logically the three libs separate by name, thus I have written the following require.config:
require.config({
baseUrl: '/s/js/libs',
paths: {
app: '../app', shims: '../shims'
},
map: {
'*' : {
// underscore, backbone, jquery and bootstrap are bundled
'underscore': '../base',
'backbone': '../base',
'jquery': '../base',
'bootstrap': '../base'
}
},
shim:{
'bootstrap': {
deps: ['jquery']
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'underscore': {
exports: '_'
},
'jquery': {exports: '$'}
}
});
I'm not using the data-main; but instead I'm requiring several things:
require(["jquery", "underscore", "backbone", "bootstrap", "../baseapp"],
function($){
// Next line fixes the bootstrap issue with double modals taken from:
// http://stackoverflow.com/questions/13649459/twitter-bootstrap-multiple-modal-error
$.fn.modal.Constructor.prototype.enforceFocus = function () {};
$('.modal').on('shown', function () {
$('input:text:visible:first, textarea:visible:first', this).focus();
});
$('#search').on('shown', function () {
$('#id_asf-text').focus();
})
require(['micro', 'csrf_xhr', 'locale']);
require(['app/routers']);
});
This however causes the error that $ is undefined.
The global window.$ is defined, but it seems that requirejs is not properly detecting it with the exports of my shims. Even if I do exports: 'window.jQuery' it does not work.
Is this a bug in RequireJS or there a bug in my code? Does map and shim play well together? Does RequireJS support my use case?
Update 2013-11-05
After a long debugging session, I have found that shims are recorded per "real" Module inside RequireJS; so if I just change my shim to be:
shim : {
'../base': {init: function() {return [$, _, Backbone]}}
}
I do get this array as the first argument to my callback. However I would like them to be exploded, i.e; have each of the returned values as arguments...
I thought that an internal map + paths would work. Like this:
var require = {
baseUrl: '/s/js/libs/',
paths: {
app: '../app',
shims: '../shims',
'base-underscore': '../base',
'base-backbone': '../base',
'base-jquery': '../base',
'base-bootstrap': '../base'
},
map: {
'*' : {
// underscore, backbone, jquery and bootstrap are bundled
'underscore': 'base-underscore',
'backbone': 'base-backbone',
'jquery': 'base-jquery',
'bootstrap': 'base-bootstrap',
}
},
shim:{
'base-bootstrap': {
deps: ['base-jquery'],
init: function() {return null}
},
'base-backbone': {
deps: ['base-underscore', 'base-jquery'],
init: function() {return window.Backbone;}
},
'base-underscore': {
init: function() {return window.Underscore;}
},
'base-jquery': {
init: function() {return $}
}
} // shims
};
Unfortunally, it does not. Now the error is: Uncaught Error: Load timeout for modules: base-underscore,base-backbone,base-bootstrap,../base... Notice base-jquery is not listed!
I have found a workaround, but involves a plugin. This is my current solution. On my HTML I have the following config (I changed to require = {...} idiom so that debugging would be easier):
var STATIC_URL = "/s/js/libs/";
var require = {
baseUrl: STATIC_URL,
paths: {
app: '../app',
shims: '../shims',
},
map: {
'*': {
'jquery': 'bundler!jQuery',
'bootstrap': 'bundler!',
'underscore': 'bundler!_',
'backbone': 'bundler!Backbone'
}
},
bundler: {url: '../base'}
};
The bundler.js plugin lies in my js/libs. This is the original CoffeeScript:
global = #
each = (ary, func) ->
if (ary)
i = 0
while i < ary.length and (what = ary[i]) and func(what, i, ary)
i += 1
getGlobal = (value) ->
if not value
value
g = global;
each value.split('.'), (part) ->
g = g[part]
g
define
load: (name, require, onload, config) ->
base = config.bundler?.url ? '../base'
require [base], () ->
if name? and name
value = getGlobal(name)
onload(value)
else
onload()
normalize: (name, norm) -> name
Probably there should be a way to do this without a bundler... I'll keep the question open for while, so that better answers might be provided.

Resources