I'm trying to use Browserify + Debowerify to load Angular.js but I get a Uncaught TypeError: undefined is not a function in browser console after I run gulp serve at run the app. When I use npm to install Angular everything works.
In my package.json I have:
{
"browserify": {
"transform": [
"debowerify"
]
},
"devDependencies": {,
"browserify": "^5.10.0",
"browserify-ngannotate": "^0.1.0",
"debowerify": "^0.8.1",
"vinyl-source-stream": "^0.1.1"
...
}
}
I installed Angular with with
bower install angular
And inside my main.js I add:
require("angular");
In my gulpfile.js I have:
...
gulp.task('browserify', ['clean'], function() {
browserify('./app/scripts/main.js')
.transform(debowerify)
.transform(ngAnnotate)
.transform(uglifyify)
.bundle()
.pipe(source('main.js'))
.pipe($.streamify($.rename({suffix: '.min'})))
.pipe(gulp.dest('.tmp/scripts'));
});
...
Here's a pastebin of my bundled js file http://pastebin.com/Uar8VkVMI'm
What is it that I'm doing wrong? Any clues? Thanks!
Related
Using the angular.mock.inject(...) function when trying to unit test an Angular (Ionic) 1 application throws the following error. The strange thing is that there is no specific error message, making particularly hard to debug. No matter what I try, it always seems to throw this same non-descript error without any message.
PhantomJS 2.1.1 (Linux 0.0.0) LoginController should pass FAILED
bower_components/angular/angular.js:4527:53
forEach#bower_components/angular/angular.js:321:24
loadModules#bower_components/angular/angular.js:4487:12
createInjector#bower_components/angular/angular.js:4409:30
WorkFn#bower_components/angular-mocks/angular-mocks.js:3160:60
loaded#http://localhost:9876/context.js:151:17
Removing the call to angular.mock.inject() allows the test to pass.
Here's the test in question:
describe('LoginController', function() {
var scope;
var controller;
beforeEach(angular.mock.module('mCommonJobs'));
beforeEach(angular.mock.inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('LoginController', {
$scope: scope
});
}));
it('should pass', function() {
expect(true).toEqual(true);
});
});
My bower dependencies:
"dependencies": {
"angular-resource": "#1.5.0",
"ionic": "driftyco/ionic-bower#1.3.2",
"ngCordova": "^0.1.27-alpha",
"ng-cordova-oauth": "^0.3.0",
"ngstorage": "^0.3.11",
"angular-mocks": "^1.5.2"
},
"resolutions": {
"angular": "~1.5.x"
}
And the files set in the Karma test config:
files: [
//Angular source
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-sanitize/angular-sanitize.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/ionic/js/ionic.bundle.js',
'bower_components/ng-cordova-oauth/dist/ng-cordova-oauth.js',
'bower_components/ngCordova/dist/ng-cordova.js',
'bower_components/ngCordova/dist/ng-cordova-mocks.js',
'bower_components/ngstorage/ngStorage.js',
//App code
'app/**/*.module.js',
'app/**/*.js',
'app/*.js',
//Test files
'test/**/*.test.js'
],
This issue was resolved by not including all of ionic.bundle.js in the files config of karma, but by specifically including its parts.
I also explicitly forced all versions of angular-related dependencies to be the same version (special thanks to Phil in the comments.).
In the end, my bower.json had:
"dependencies": {
"angular-resource": "1.5.2",
"ionic": "driftyco/ionic-bower#1.3.2",
"ngCordova": "^0.1.27-alpha",
"ng-cordova-oauth": "^0.3.0",
"ngstorage": "^0.3.11",
"angular-mocks": "1.5.2"
},
and my karma config looked like:
files: [
//Angular source
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-sanitize/angular-sanitize.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/ionic/js/ionic.js',
'bower_components/ionic/js/ionic-angular.js',
'bower_components/ng-cordova-oauth/dist/ng-cordova-oauth.js',
'bower_components/ngCordova/dist/ng-cordova.js',
'bower_components/ngCordova/dist/ng-cordova-mocks.js',
'bower_components/ngstorage/ngStorage.js',
//App code
'app/**/*.module.js',
'app/**/*.js',
'app/*.js',
//Test files
'test/**/*.test.js'
],
My pipeline looks like this:
// Client-side javascript files to inject in order
// (uses Grunt-style wildcard/glob/splat expressions)
var jsFilesToInject = [
// Dependencies like sails.io.js, jQuery, or Angular
'js/dependencies/sails.io.js',
'js/bower_components/angular/*.js',
'js/bower_components/**/*.js',
// All of the rest of your client-side js files
// will be injected here in no particular order.
'js/modules/app.js',
'js/modules/auth/services/accessLevels.js',
'js/**/*.js'
];
and my bower.json:
{
"name": "myapp",
"version": "0.0.1",
"dependencies": {
"angular": "1.3.7",
"angular-cookies": "1.3.7",
"angular-ui-router": "0.2.15"
},
"resolutions": {
"angular": "1.3.7"
}
}
I think this issue is because it's injecting angular.js and angular.min.js, any way to solve this with grunt?
Im facing a problem when I try to use browserify, angularjs and restangular.
When I try to require the npm or bower module, for example require('restangular), browserify returns empty object. This happens when i require any bower or npm modules. When I try to require any local file, everything is working fine.
file structure:
bower_components/
src/
-client
-app
app.js
backend
backend.module.js
-test
test.module.ls
test.js
node_modules/
app.js
(function() {
'use strict';
require('angular');
var rest = require('restangular');
console.log(rest);
module.exports = angular
.module('app', [
require('restangular').name,
require('./test/test.module').name,
]);
})();
package.json
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"restangular": "./bower_components/restangular/dist/restangular.js"
},
"browserify-shim": {
"restangular": "restangular"
}
gulpfile.js
gulp.task('browserify', function() {
gulp.src(['./src/client/app/app.js'])
.pipe(plugins.browserify({
insertGlobals: true,
debug: true
}))
.pipe(plugins.concat('bundled.js'))
.pipe(gulp.dest('./src/client/js'))
});
Can you help me?
Thanks in advance.
Just modify your "browser" part in package.json:
"browserify-shim": {
"angular": {
"exports": "angular"
},
"restangular": {
"depends": [
"angular"
],
"exports": "restangular"
}
}
Hope it will work.
Try modifying your package.json file with this snippet.
"browser": {
"restangular": "./bower_components/restangular/dist/restangular.js"
},
"browserify-shim": {
"restangular": {
"depends": [
"angular",
"lodash:_"
],
"exports": "null"
}
}
Solution courtesy of #newtricks from this discussion
Gulp throws an unclear error when I am trying to bundle angular and angular-hammer (the Ryan Mullins version) with browserify.
For a stripped down version of the app, the package.json file is:
{
"name": "hammer-test",
"version": "0.0.0",
"description": "",
"main": "app/main.js",
"devDependencies": {
"browserify": "^10.2.1",
"browserify-shim": "^3.8.7",
"gulp": "^3.8.11",
"vinyl-source-stream": "^1.1.0"
},
"dependencies": {
"angular": "^1.3.15",
"angular-hammer": "^2.1.10",
"hammerjs": "^2.0.4"
}
}
(I included browserify-shim, because an error was thrown asking for this missing dependency for angular-hammer.)
The gulpfile.js contains a bundle task to run browserify:
'use strict';
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
// Bundle (browserify).
gulp.task('bundle', function() {
return browserify('./app/js/main.js')
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./dist/js'));
});
gulp.task('default', ['bundle']);
And finally, the main javascript file app/js/main.js contains:
(function() {
'use strict';
// Require stuff.
var angular = require('angular');
var Hammer = require('hammerjs');
require('angular-hammer');
// Initialize angular application.
var app = angular.module('myApp', ['hmTouchEvents']);
}());
The directory structure of the app now looks like this:
- app
- js
-main.js
- node_modules
- angular
- angular-hammer
- browserify
- browserify-shim
- gulp
- hammerjs
- vinyl-source-stream
- gulpfile.js
- package.json
When I now try to run the bundle task using the command:
gulp
Then the following error is thrown:
events.js:72
throw er; // Unhandled 'error' event
^
Error: ENOENT, open '/home/brennerd/Develop/hammer-test/node_modules/angular-hammer/node_modules/angular/angular.js'
The error is not very descriptive, but some paths seem to be incorrectly concatenated. Did I make a browserify mistake somewhere? My browserify experience is limited, so that could very well be the case. Or is it not possible to bundle angular-hammer with browserify?
Thanks!
After some searching, learning, and playing around I found the issue. It was indeed a browserify mistake.
Thanks to the documentation of the angular-hammer-propagating fork I figured out that the package.json needed some extension. As far as I understand to 1) let browserify know that it should run browserify-shim and 2) to let browserify-shim know where to find the angular-hammer dependencies. The package.json now looks like this:
{
"name": "hammer-test",
"version": "0.0.0",
"description": "",
"main": "app/main.js",
"devDependencies": {
"browserify": "^10.2.1",
"browserify-shim": "^3.8.7",
"gulp": "^3.8.11",
"vinyl-source-stream": "^1.1.0"
},
"dependencies": {
"angular": "^1.3.15",
"angular-hammer": "^2.1.10",
"hammerjs": "^2.0.4"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"angular-hammer": "./node_modules/angular-hammer/angular.hammer.js"
},
"browserify-shim": {
"angular-hammer": {
"exports": "angular.module('hmTouchEvents').name",
"depends": [
"./node_modules/hammerjs/hammer.js:Hammer"
]
}
}
}
For testing I added a HammerTestCtrl with the handleTap function to the main.js file:
(function() {
'use strict';
// Require both angular and angular-hammer.
var angular = require('angular');
require('angular-hammer');
// Initialize angular application.
var app = angular.module('myApp', ['hmTouchEvents']);
// Add controller to test hammer.
app.controller('HammerTestCtrl', ['$scope', function($scope) {
$scope.handleTap = function() {
console.log('Tap detected.');
}
}]);
}());
I created a basic index.html with a square div that calls the handleTap function when it is tapped:
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title>Test hammer-angular</title>
<script src="js/bundle.js"></script>
</head>
<body ng-controller="HammerTestCtrl">
<div hm-tap="handleTap" style="width: 300px; height: 300px; background-color: #eeeeec;"></div>
</body>
</html>
And in the gulpfile.js I added a task to move this index.html from the app to the dist directory:
'use strict';
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
// Bundle (browserify).
gulp.task('bundle', function() {
return browserify('./app/js/main.js')
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./dist/js'));
});
// HTML.
gulp.task('html', function() {
gulp.src('app/index.html')
.pipe(gulp.dest('dist/'));
});
gulp.task('default', ['bundle', 'html']);
After an npm install and this time successful gulp, the directory structure looks like this:
- app
- index.html
- js
-main.js
- dist
- index.html
- js
- bundle.js
- node_modules
- angular
- angular-hammer
- browserify
- browserify-shim
- gulp
- hammerjs
- vinyl-source-stream
- gulpfile.js
- package.json
After browsing to the dist/index.html file it correctly outputs Tap detected. to the console every time the light-gray square is tapped. The code for this angular-hammer boilerplate web application can be found here.
I have been working on converting a grunt task to gulp. The grunt file looks like this:
browserify: {
options: {
transform: [ require('grunt-react').browserify ]
},
client: {
src: ['react/**/*.jsx'],
dest: 'public/js/browserify/bundle.js'
}
}
I saw many examples of browserify and gulp but all of them had just a single file start point. To get round this I tried using glob. After several false starts I came up with the following. It runs without error and creates a single bundle.js file, but reactify doesn't seem to be working correctly, as jsx does not seem to be converted so I end up with the error:
Uncaught Error: Cannot find module './components/NoteApp.jsx'
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var glob = require('glob');
var reactify = require('reactify');
gulp.task('browserify', function (cb) {
glob('./react/**/*.jsx', {}, function (err, files) {
var b = browserify();
files.forEach(function (file) {
b.add(file);
});
b.transform(reactify);
b.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./public/js/browserify/'));
cb();
});
});
ddprrt requested some further details on structure so here is how the react folder is laid out. The code is taken from this article which uses this github zip source to demonstrate react and reflux. The project was very close to what I needed as a start point but uses Grunt instead of Gulp.
The react folder is structured like this:
react \ App.jsx
\ Bootstrap.jsx
\ components \ NoteApp.jsx
\ NoteCreationBox.jsx
\ Note.jsx
\ NoteListBox.jsx
\ NoteList.jsx
\ TextArea.jsx
The error is coming from a line in the App.jsx file:
var React = require('react');
var NoteApp=require('./components/NoteApp.jsx');
but changing this line causes the gulp talk to fail with a missing file error.
I guess I got the answer now. It was really some version mixup, reactify seems to be more advanced and handle things differently than the reactify in the original did. Might be because both are still in experimental state. I also guess that React/Reflux moved on, so you ended up with some versions which didn't quite comply. However, you still can fix it and run you app:
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var glob = require('glob');
var reactify = require('grunt-react').browserify;
gulp.task('browserify', function (cb) {
glob('./react/Bootstrap.jsx', function (err, files) {
var b = browserify({
entries: files
}).transform(reactify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./public/js/browserify/'));
cb();
});
});
Instead of using require('reactify'), we take the reactify provided by grunt-react. See the code above. You should just be able to switch the middleware. Also, don't go over all the files, just your main entry point, which is in that case Bootstrap.jsx.
I know that this is rather inconvenient, maybe when you try your own app, start with a fresh setup.
** Update**
that was my package.json afterwards, just working into the previous project:
{
"name": "react-note-app",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"main": "./bin/www"
},
"engines": {
"node": ">= 0.10.0"
},
"dependencies": {
"body-parser": "~1.8.1",
"cookie-parser": "~1.3.3",
"debug": "~2.0.0",
"ejs": "~0.8.5",
"express": "~4.9.0",
"express-session": "^1.8.2",
"morgan": "~1.3.0",
"node-jsx": "^0.11.0",
"react": "^0.11.2",
"reflux": "^0.1.13",
"serve-favicon": "~2.1.3"
},
"devDependencies": {
"browserify": "^9.0.7",
"glob": "^5.0.3",
"grunt": "^0.4.5",
"grunt-browserify": "^3.0.1",
"grunt-contrib-watch": "^0.6.1",
"grunt-nodemon": "^0.3.0",
"grunt-react": "^0.9.0",
"gulp": "^3.8.11",
"react-tools": "^0.11.2",
"reactify": "^1.1.0",
"vinyl-source-stream": "^1.1.0"
}
}