Error while requiring external library with browserify (this = undefined) - javascript

I'm trying to require the library Chart.js with Browserify (tbh it's development environment with gulp, browserify and some other stuff that I barely know how it works togheter):
'use strict';
var angular = require('angular');
require('angular-ui-router');
require('./templates');
require('./controllers/_index');
require('./services/_index');
require('./directives/_index');
window.gauge = require('./vendors/gauge');
//this is what i'm trying to require
window.chartjs = require('./vendors/chart');
angular.element(document).ready(function() {
var requires = [
'ui.router',
'templates',
'app.controllers',
'app.services',
'app.directives'
];
window.app = angular.module('app', requires);
angular.module('app').constant('AppSettings', require('./constants'));
angular.module('app').config(require('./routes'));
angular.module('app').config(require('./PostFix'));
angular.module('app').run(require('./on_run'));
angular.bootstrap(document, ['app']);
});
Tbh it did work well with window.gauge = require('./vendors/gauge'); but when I require vendors/chart.js it throws this error:
undefined // chart.js:4
Uncaught TypeError: Cannot read property 'Chart' of undefined // chart.js:4
And here is those lines in the chart.js file:
(function(){
"use strict";
console.log(this); <------ outputs the "undefined"
var root = this,
previous = root.Chart; <----- fails, as "root" doesn't exist
It's weird, because when I add chart.js using <script></script> that console.log(this) outputs the window object/scope, but when executed from browserify, it's undefined, that's why the chart.js fails.
I'm a total newb with browserify/node/gulp, but I tried different stuff such as:
Browserify-shim -> same error
Requiring the script in different ways, like trying to require it inside an object { }, trying to do a var whatever = new require('./vendors/chart') but failed miserably like a beheaded chicken trying to go to the bathroom.
I'm guessing that somehow I have to attach that script to an object or something so this would not be undefined when executed, but I'm failing to find the way.

I already solved it. The problem was a browserify transform called Babelify. I still don't know why Babel was doing that, but I didn't need it anyway so I just disabled it and that was it. Just posting it here in case it happens to someone else.

Related

Browserify + AngularJS index.js IIFE params undefined

I have the following index.js for an angular app. Even though the var statements are executed first, and all variables are successfully logged to the console before the IIFE is executed, they are undefined once it steps into the IIFE scope, with the exception of angular. Presumably angular is defined, because angular is a global object. I've seen window and jquery passed in the same way. I'm just wondering if there is a way for me to pass these locally declared objects to my app's main IIFE script like this? Did I do it wrong? Please help - I'm stumped.
var angular = require('angular'),
config = {
params: require('./config/params').config,
routes: require('./config/routes').config
},
x = {};
(function (angular, config, x) {
// *****angular is the only one of these parameters that is defined here
console.info(angular) // works
console.info(config) // undefined
console.info(x) // works
})(angular, config, x);
Updated
As a commenter pointed out, this is an issue with browserify. If I pass an object I declare literally, it works fine. Does anyone know why this is happening or how to fix it?
Here's my browserify command:
browserify -e -d src/index.js -p [minifyify --map sourcemap.json --output sourcemap.json --uglify] > build/index.js
(I removed the parameter value and shortened the paths for brevity.)

Adding Webpack to an existing Angular app

I'm working on an existing (and working) Angular 1.5.5 app. It's very small and has a controller, a directive and a couple of services, all split into individual files.
I'd now like to move to Webpack and make the minimum number of changes to the app to support that. A lot of the Webpack/Angular demos I've found have been about creating a new Angular app with web pack built in from the start, but I don't want to rebuild the existing app, just make whatever changes are necessary to use a webpack-produced bundle. It's also using regular JS, whereas most of the tutorials I've seen are for ES6.
I've got grunt-webpack installed and working, it's creating the bundle.js file and I can see inside the bundle that it's pulling in Angular, Angular-aria and Angular-animate (my module dependencies)
However, when I run the site I see an error:
Uncaught TypeError: angular.module is not a function
My webpack task is as follows:
module.exports = {
dist: {
entry: './Static/js/Ng/app.js',
output: {
path: './Static/dist/js',
filename: 'bundle.js'
}
}
};
As I say, the actual Webpack bundling seems to be working as expected and creates the bundle.js file.
The main entry file (app.js) is as follows:
(function () {
'use strict';
var angular = require('../vendor/angular.js');
var ngAria = require('../vendor/angular-aria.js');
var ngAnimate = require('../vendor/angular-animate.js');
angular.module('app', [ngAria, ngAnimate]);
}());
If I log out the angular variable in this file, it's just an empty object, even though I can see the Angular source in the bundle.
What am I missing?
You probably shadow the global angular property by your local var angular variable. Try this:
(function () {
'use strict';
require('../vendor/angular.js');
require('../vendor/angular-aria.js');
require('../vendor/angular-animate.js');
angular.module('app', [ngAria, ngAnimate]);
}());

External library variable not defined

I'm trying to include a javascript library (WaveSurfer) into my Angular app (Using Mean.io).
The problem is a warning appears into the console each time I run grunt :
In packages\tracks\public\services\tracks.js :
'WaveSurfer' is not defined.
Here is the code of my different files:
public/controllers/tracks.js
angular.module('mean').controller('PlayerController', ['$scope', 'Global', 'Tracks','myWaveSurfer',
function($scope, Global,Tracks, myWaveSurfer) {
$scope.global = Global;
//Player WaveSurfer
var wavesurfer = Object.create(myWaveSurfer);
wavesurfer.load('music.mp3');
public/services/tracks.js
angular.module('mean.tracks').factory('myWaveSurfer', function() {
return WaveSurfer; /*Warning here*/
});
The content of the wavesurfer.min.js looks like :
var WaveSurfer = {
defaultParams: {...}
init: function(params) {...}
...
}
I included correctly the library into config/assets.json so the library can be loaded.
I can see it on the Chrome console :
<script type="text/javascript" src="/bower_components/wavesurfer.js/build/wavesurfer.min.js"></script>
It only works with grunt --force but is there a solution to include properly this library without warning ?
Thanks in advance !
I assume you are inside the Node env.
Add this to your globals:
GLOBAL.WaveSurfer = {};
Or you could pull it in with require
GLOBAL.WaveSurfer = require('...');
If you require make sure the library module.exports the global object.

The synchronous form of require throws errors when resolving a circular dependency, unless I rename require

I have a strange behaviour in require, that I dont know how to avoid (or maybe I have my basics wrong?).
Consider the following code:
define (require) ->
potoo = require "potoo"
service = require "communication.data"
downloadIfNeeded = ->
# ...
service.download()
new potoo.App
pageContainer: potoo.UI.NGStylePage
userRequired: true
stdRoute: "overview"
onLogin: downloadIfNeeded
This is not going to work, because 'communication.data' itself requires 'app' (the code shown). so we obviously have a circular dependency. That fails with a 'Uncaught Error: Module name "app" has not been loaded yet for context: _'
Since the downloadIfNeeded function doesn't get called until after the user actually clicks something, I figured, that something like the following should work:
define (require) ->
potoo = require "potoo"
downloadIfNeeded = ->
service = require "communication.data"
service.download()
...
But that actually throws the same error as above. To make it work, i have to use a little hack. I alias the require function with some other name:
define (require) ->
potoo = require "potoo"
reqs = require
downloadIfNeeded = ->
service = reqs "communication.data"
service.download()
...
Is this the best way to do so? Or would you recommend the CommonJS Style (module.export) that is also supported by requirejs.
I've done a test here and was able to find a solution. What you have is equivalent to this JavaScript:
define(function (require) {
This is enough to be able to use the (fake) synchronous form of require. However, RequireJS will give you the error you got when you try to use a synchronous require and you have circular dependencies. What you need is this:
define(function (require, exports, module) {
This is so that your module uses exports to export its values and consequently RequireJS has an object that can be updated when the module has finished initialized.

Testing a Node Module with Intern Js- Can't resolve 'require'

I am trying to test a simple node Module with intern.The module is an AMD module. I am running into a couple of issues
If the module is defined as below, I get the error "moduleName" has
no method 'map' "
define('moduleName',[]function(require){ var r= require('request');
})
If the module is defined as below without a moduleName, I see this
error "undefined is not a function" - I guess its not able to resolve 'require'
define([]function(require){ var r= require('request'); })
Here is how my Test Looks
define([
'intern!object',
'intern/chai!assert',
'/src/api/nameApi'
], function (registerSuite, assert,nameApi) {
registerSuite({
name: 'GetName Test',
getName: function () {
var nameFromApi = nameApi.getName();
assert( nameFromApi!= null,'name is not null');
}
});
});
Providing an explicit module ID as the first argument to define destroys module portability and shouldn’t be done. It is not currently supported by the loader used by the master branch because it is such a bad idea. It is supported by the geezer branch, but again, I strongly advise you to never use this pattern.
The second module definition you have provided is just wrong; you need to put 'require' in your dependencies array if you expect to load the special require function. You also can’t use a variable to pass a module ID to the require function if you are expecting it to be pre-loaded as a dependency. So, it should look like this:
define(['require', 'foo'], function (require) {
var foo = require('foo');
});
or, using the CommonJS compatibility wrapper syntax, where require is implicitly provided:
define(function (require) {
var r = require('foo');
});
EDIT: Also, now that you have added the test module: within your test’s define, '/src/api/nameApi' is not a valid AMD module identifier.

Categories