Loading CreateJS with RequrieJS “shim” dosen't work - requirejs

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

Related

RequireJS + Mocha + JSDom + Node -> Shim config not supported in Node

I'm trying to setup a Mocha testing framework using JSDom with RequireJS. Because I'm running the test on node instead of using a browser (since I'm using JSDom), all the non AMD modules doesn't seem to be imported and is throwing Shim config not supported in Node. Does anyone know how I can export those modules to AMD or what the right approach is? (aka what I'm doing wrong)
Example of my set-up
Component.js
define(["jquery", "non_AMD_Module", ... ], function($, NonAMDModule, ...) {
let component = {
...
foo = () => {
NonAMDModule.bar();
};
};
return component;
});
Component.test.js
const requirejs = require('requirejs');
const { JSDOM } = require('jsdom');
requirejs.config({
baseUrl: "dist/app",
paths: {
jquery: "lib/jquery",
component: "path_to_component",
non_AMD_Module: "path_to_module"
},
shim: {
non_AMD_Module: { exports: "non_AMD_Module" } // This doesn't work
}
});
const { window } = new JSDOM("<html></html>");
global.window = window;
global.document = window.document;
global.$ = requirejs('jquery');
const Component = requireJS('component');
describe('test', () => {
it('is a simple test', () => {
const testComponent = new Component();
testComponent.foo();
}
});
When I run the test suite, I get:
Mocha Exploded!
TypeError: Cannot read property 'bar' of undefined
running r.js -convert "path_to_module" did not work for this module
Looking at the source code for jQuery, I found that there's this boiler-plate coded that exports it to AMD.
This can be added at the bottom of the non-AMD-module in order to export it to an AMD module accessible by RequireJS
if ( typeof define === "function" && define.amd ) {
define([], function {
return non_AMD_Module;
});
}
Other Resources:
Shim a module in Require.js that uses module.exports possible?
https://github.com/requirejs/requirejs/wiki/Updating-existing-libraries#anon

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');

requirejs optimization with gulp

I am using requirejs and gulp to build angular app. I am using amd-optimize and gulp-requirejs-optimize to add all js files into single file. Here is my main.js file:
require.config(
{
paths: {
app : 'app',
angular : '../bower_components/angular/angular',
jquery : '../bower_components/jquery/dist/jquery',
angularResource : '../bower_components/angular-resource/angular-resource',
angularRoute : '../bower_components/angular-route/angular-route',
publicModule : 'public_module',
route : 'route'
},
shim: {
'app': {
deps: ['angular']
},
'angularRoute': ['angular'],
angular : {exports : 'angular'}
}
}
);
And gulpfile.js
var gulp = require('gulp');
var rjs = require('gulp-requirejs');
var connect = require('gulp-connect');
var requirejsOptimize = require('gulp-requirejs-optimize');
var amdOptimize = require('amd-optimize');
var concat = require('gulp-concat');
// using amd-optimize.
gulp.task('bundle', function () {
return gulp.src('app/**/*.js')
.pipe(amdOptimize('main'))
.pipe(concat('main-bundle.js'))
.pipe(gulp.dest('dist'));
});
// using gulp-requirejs-optimize.
gulp.task('scripts', function () {
return gulp.src('app/main.js')
.pipe(requirejsOptimize())
.pipe(gulp.dest('dist'));
});
When I run gulp bundle or gulp scripts, it shows me same content of main.js file in output file(not showing all js template in one output file).
The output file is:
require.config({
paths: {
angular: '../bower_components/angular/angular',
jquery: '../bower_components/jquery/dist/jquery',
angularResource: '../bower_components/angular-resource/angular-resource',
angularRoute: '../bower_components/angular-route/angular-route',
publicModule: 'public_module',
route: 'route'
},
shim: {
'app': { deps: ['angular'] },
'angularRoute': ['angular'],
angular: { exports: 'angular' }
}
});
define('main', [], function () {
return;
});
How can I configure gulp to put every js template into one js file?
check the docs for all the options for amdoptimize. For example you can point to your config file or add paths.
I always have trouble getting all the paths to line up, so make sure to check them diligently.
here is how you can start to put the options in:
gulp.task('requirejsBuild', function() {
gulp.src('app/**/*.js',{ base: 'app' })
.pipe(amdOptimize("app",{
baseUrl: config.app,
configFile: 'app/app-config.js',
findNestedDependencies: true,
}))
.pipe(concat('app.js'))
.pipe(gulp.dest('dist'))
});
You are not requiring any files - you just define an empty module named main.
You need to kick off you app by requiring a module, eg.
require(['app'], function (App) {
new App().init();
});

require.js listener or callback

I am loading a 3rd party script that simply creates an overlay on a site it has been loaded onto. It works fine but sites using require.js seem to have intermittent issues I'm assuming with async loading some js files. Is there any type of callback or way to create a module in the DOM as sort of a listener to see if require.js is done loading?
I tried this but not even close:
define(function() {
alert('test');
return {};
});
and
define('myModule',
function () {
var myModule = {
doStuff:function(){
console.log('Yay! Stuff');
}
};
return myModule;
});
console.log(myModule);
I ended up just creating a secondary require.config file and loading the module with require if require is detected, seems to work fine.
if(typeof require === 'function') {
var base = 'http://' + someDomainVar;
function getJSTreeURL() {
var url = base + '/js/libs/jstree.min';
return url;
}
function getModuleURL() {
var url = base + '/module';
return url;
}
var reqTwo = require.config({
context: "instance2",
baseUrl: "instance2",
paths: {
'jq': 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
'jqTree': getJSTreeURL(),
'module': getModuleURL()
},
shim: {
'jq': {
exports: 'jq'
},
'jqTree': {
deps: ['jq'],
exports: 'jqTree'
},
'module': {
deps: ['jq', 'jqTree'],
exports: 'module'
}
}
});
reqTwo(['require', 'jq', 'jqTree'],
function(require, jq, jqTree) {
setTimeout(function() {
require(['module'],
function(module) {
console.log('loaded');
}
);
}, 0);
});

node assetmanager with more modules

I'm trying to set up assetmanager
for my blog that has three modules
default
login
admin
I tried like
assets.json
{
"css": {
"app":{
"public/src/dist/default/css/dist.min.css": [
"public/src/assets/default/css/*.css"
]
},
"login":{
"public/src/dist/login/css/dist.min.css": [
"public/src/assets/default/css/*.css"
]
},
"admin":{
"public/src/dist/admin/css/dist.min.css": [
"public/src/assets/admin/css/*.css"
]
}
}
}
express.js
assetmanager.init({
js: assets.js,
css: assets.css,
debug: (process.env.NODE_ENV !== 'production'),
webroot: 'public'
});
// Add assets to local variables
app.use(function(req, res, next) {
res.locals({
assets: assetmanager.assets
});
next();
});
console.log(assetmanager.assets);
but console.log(assetmanager.assets);
give me a empty array []
so is there a way to manage assetmanager
with more than one module ?
the best way I found up to now
is like in my controllers:
'use strict';
var assetmanager = require('assetmanager');
exports.render = function(config) {
var assets = require(config.sroot+'/config/assets.json');
assetmanager.init({
js: assets.js.app,
css: assets.css.app,
debug: (process.env.NODE_ENV !== 'production'),
webroot: 'public'
});
return function(req, res) {
res.render('layouts/default', {appTitle:'ilwebdifabio',assets:assetmanager.assets});
}
};
but it's quite ugly and I have
duplicate code :(
END UP
There is no way to use assetmanager module
in different modules (login,default,admin).
Modules are automatically cached by the Node.js application upon first load. As such, repeated calls to require() - the global method that loads modules - will all result in a reference to the same cached object.
so you end up ie if you use in a module
to the have the dedicate assets in all other module so
I worked it out with :
'use strict';
var _ = require('lodash');
module.exports = function (path,route) {
var env = (process.env.NODE_ENV === 'production') ? 'production' : null;
var debug = (env !== 'production');
var data = require(path+'/config/assets.json');
var assets = {
css: [],
js: []
};
var getAssets = function (pattern) {
var files = [];
if (_.isArray(pattern)) {
_.each(pattern, function (path) {
files = files.concat(getAssets(path));
});
} else if (_.isString(pattern)) {
var regex = new RegExp('^(//)');
if (regex.test(pattern)) {
// Source is external
//For the / in the template against 404
files.push(pattern.substring(1));
} else {
files.push(pattern);
}
}
return files;
};
var getFiles = function () {
var current = data[route];
_.each(['css', 'js'], function (fileType) {
_.each(current[fileType], function (value, key) {
if (!debug) {
assets[fileType].push(key);
} else {
assets[fileType] = assets[fileType].concat(getAssets(value));
}
});
});
};
var getCurrentAssets = function(){
return assets;
};
getFiles();
return {
getCurrentAssets: getCurrentAssets
};
};
in the controller
var assetmanager = require(config.sroot+'/utils/assetsmanager')(config.sroot,'app');
res.render('layouts/default', {
assets:assetmanager.getCurrentAssets()
});
There is a new version of assetmanager 1.0.0 that I believe accomplishes what you're trying to do more effectively. In the new version you can break apart your assets into groups so that you can support multiple layouts. The github has a complete example here but essentially your asset files ends up looking something like this:
{
"main": {
"css": {
"public/build/css/main.min.css": [
"public/lib/bootstrap/dist/css/bootstrap.css",
"public/css/**/*.css"
]
},
"js": {
"public/build/js/main.min.js": [
"public/lib/angular/angular.js",
"public/js/**/*.js"
]
}
},
"secondary": {
"css": {
"public/build/css/secondary.min.css": [
"public/css/**/*.css"
]
},
"js": {
"public/build/js/secondary.min.js": [
"public/js/**/*.js"
]
}
}
}
And then in your layouts you just include the group you want. Hopefully that helps out.

Resources