Simple AngularJS application: Showing error in Gruntfile.js - angularjs

$ grunt connect:development:keepalive
ERROR:
Running "connect:development:keepalive" (connect) task
Warning: undefined is not a function Use --force to continue.
Aborted due to warnings.
I am presently learning AngularJS from the book Professional AngularJS (wrox) and here's a basic code from the book:
app/index.html
<!DOCTYPE HTML>
<html ng-app="Workflow">
<head>
<title>Chapter Two</title>
<link rel="stylesheet" href="main.css" />
</head>
<body ng-controller="ToolsCtrl">
<h1>Workflow tools from this chapter:</h1>
<ul>
<li ng-repeat="tool in tools">{{tool}}</li>
</ul>
<script src="bower_components/angular/angular.js"></script>
<script src="app.js"></script>
</body>
</html>
app/main.less
html,
body {
h1 {
color: steelblue;
}
app/app.js
'use strict';
angular.module('Workflow', [])
.controller('ToolsCtrl', function($scope) {
$scope.tools = [
'Bower',
'Grunt',
'Yeoman'
];
});
Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
options: {
port: 9000,
open: true,
livereload: 35729,
hostname: 'localhost'
},
development: {
options: {
middleware: function(connect) {
return [
connect.static('app')
];
}
}
}
},
less: {
development: {
files: {
'app/main.css': 'app/main.less'
}
}
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('default', []);
};
.bowerrc
{
"directory": "app/bower_components"
}
These are all the codes provided by the book as is, for this application. Also, as the book asked, I ran these commands on the root folder from the terminal:
sudo npm install -g bower
sudo npm install -g grunt-cli
sudo npm install --save-dev grunt
sudo npm install --save-dev load-grunt-tasks
sudo npm install --save-dev grunt-contrib-connect
sudo npm install --save-dev grunt-contrib-jshint
sudo npm install --save-dev grunt-contrib-less
sudo npm install --save-dev grunt-contrib-watch
sudo npm install -g less
lessc app/main.less > app/main.css
grunt less
I had to use sudo because, otherwise it was throwing error:
Please try running this command again as root/Administrator.
According to the book, if I run grunt connect:development:keepalive from my terminal, then, my browser should fire up with the application running. But is giving me the error as I mentioned above.
Please help me with the situation as I have no idea what wrong am I doing. This is why I included all the code. I am very new to these tools and technologies, and I am not even sure if I should follow this book to learn AngularJS.
Thank you.
EDIT:
Since I am using the WebStorm IDE, it is showing me a problem in the Gruntfile.js in the line connect.static('app'). It says Unresolved function or method static() when I hover the mouse over it.

it is correct that the problem is in the Gruntfile.js in the line connect.static('app')
According to the forum from the website for the book "static" is no longer a part of Connect module and you will need to run npm install serve-static. after that declare a variable above your grunt.intConfig line in your Gruntfile.js like so...
var serveStatic = require('serve-static');
then change your middleware function to look like this
middleware: function(connect) {
return [
serveStatic('app')
hope this helps. It helped me solve it

Related

Reactjs file size: script-file vs npm-version

I am using reactjs and gulp for the build-process. Currently I use react from npm with browserify. When I want to minify my App in production-mode the react code ends up with about 180kb.
This is the gulp code I use:
gulp.task('production', function () {
var bundler = browserify('./public/dev/js/main.js').transform(babelify, { presets: ['react'] });
return bundler.bundle()
.on('error', map_error)
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(rename('bundle-build.min.js'))
.pipe(envify({'_': 'purge', NODE_ENV: 'production'}))
.pipe(uglify())
.pipe(gulp.dest('./public/dist/js/'));
});
However, if I download the minified script files from the react-website and load the script files like this:
<script type="text/javascript" src="./react.min.js"></script>
<script type="text/javascript" src="./react-dom.min.js"></script>
it ends up with about 150kb.
Why is the with gulp minified version bigger? How can I bring it to the same size? Also, is there a difference in the development / production of the app between loading the provided script files or using it from npm?
Thanks in advance
Cheers

Angular2 - Angular-CLI installing lodash - Cannot find module

Mac OSX El capitan | angular-cli: 0.1.0 | node: 5.4.0 | os: darwin x64
I try to install a 3rd party npm module according to the angular-cli wiki: https://github.com/angular/angular-cli/wiki/3rd-party-libs but fail. I've been struggling with this for days now and would greatly appreciate any help.
Steps to get the error:
ng new lodashtest3
cd lodashtest3
npm install lodash --save
typings install lodash --ambient --save
angular-cli-build.json:
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
...
'lodash/**/*.js'
]
});
};
ng build
(lodash gets correctly added in dist/vendor)
system-config.ts:
/** Map relative paths to URLs. */
const map: any = {
'lodash': 'vendor/lodash/lodash.js'
};
/** User packages configuration. */
const packages: any = {
'lodash': {
format: 'cjs'
}
};
(all according to spec in
https://github.com/angular/angular-cli/wiki/3rd-party-libs)
Note - I've tried all config settings I can think of here, all giving the same result.
lodashtest3.component.ts:
import * as _ from 'lodash';
ng build
Could not start watchman; falling back to NodeWatcher for file system events.
Visit http://ember-cli.com/user-guide/#watchman for more info.
Build failed.
The Broccoli Plugin: [BroccoliTypeScriptCompiler] failed with:
Error: Typescript found the following errors:
/Users/danielmattsson/git/lodashtest3/tmp/broccoli_type_script_compiler-input_base_path-g2lDIaq6.tmp/0/src/app/lodashtest3.component.ts (2, 20): Cannot find module 'lodash'.
at BroccoliTypeScriptCompiler._doIncrementalBuild (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
at BroccoliTypeScriptCompiler.build (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:152:21
at lib$rsvp$$internal$$tryCatch (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1048:17)
at lib$rsvp$$internal$$publish (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1019:11)
at lib$rsvp$asap$$flush (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1198:9)
at nextTickCallbackWith0Args (node.js:456:9)
at process._tickCallback (node.js:385:13)
The broccoli plugin was instantiated at:
at BroccoliTypeScriptCompiler.Plugin (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/broccoli-plugin/index.js:10:31)
at BroccoliTypeScriptCompiler.CachingWriter [as constructor] (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:21:10)
at BroccoliTypeScriptCompiler (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:26:49)
at Angular2App._getTsTree (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:280:18)
at Angular2App._buildTree (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:101:23)
at new Angular2App (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/lib/broccoli/angular2-app.js:42:23)
at module.exports (/Users/danielmattsson/git/lodashtest3/angular-cli-build.js:6:10)
at Class.module.exports.Task.extend.setupBroccoliBuilder (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/models/builder.js:55:19)
at Class.module.exports.Task.extend.init (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/models/builder.js:89:10)
at new Class (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/core-object/core-object.js:18:12)
at Class.module.exports.Task.extend.run (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/tasks/build.js:15:19)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/lib/commands/build.js:32:24
at lib$rsvp$$internal$$tryCatch (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1048:17)
at /Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:331:11
at lib$rsvp$asap$$flush (/Users/danielmattsson/git/lodashtest3/node_modules/angular-cli/node_modules/angular-cli/node_modules/rsvp/dist/rsvp.js:1198:9)
EDIT: more information according to comments below
dist/index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Lodashtest3</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Service worker support is disabled by default.
Install the worker script and uncomment to enable.
Only enable service workers in production.
<script type="text/javascript">
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/worker.js').catch(function(err) {
console.log('Error installing service worker: ', err);
});
}
</script>
-->
</head>
<body>
<lodashtest3-app>Loading...</lodashtest3-app>
<script src="vendor/es6-shim/es6-shim.js"></script>
<script src="vendor/reflect-metadata/Reflect.js"></script>
<script src="vendor/systemjs/dist/system.src.js"></script>
<script src="vendor/zone.js/dist/zone.js"></script>
<script>
System.import('system-config.js').then(function () {
System.import('main');
}).catch(console.error.bind(console));
</script>
</body>
</html>
With the stable release and current angular-cli (1.0.0-beta.15), it's simply adding the npm package plus type definitions
npm install lodash --save
npm install #types/lodash --save-dev
For early versions such as 1.0.0-beta.15, the next is necessary. It should not be required for current versions:
Add the library to the angular-cli.json to list of global scripts (add "../node_modules/lodash/lodash.js" to the list apps[0].scripts).
See https://github.com/angular/angular-cli#global-library-installation
FWIW, as of today (1.0.0-beta.26), adding the scripts entry is not necessary anymore.
Simply add the proper entries to package.json using:
npm i --save lodash
npm i --save-dev #types/lodash
Then, in your TypeScript code, use:
import * as _ from 'lodash';
The code will run just fine.
In my case, actually adding the scripts entry was causing issues.
[updated answer] After the new version of angular-cli (1.0.0-beta.15):
just add
npm install lodash --save
npm install #types/lodash --save-dev
then add the library to the angular-cli.json to list of global scripts(add "../node_modules/lodash/lodash.js" to the list apps[0].scripts).
and in your component where you want to use , try this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
before : angular-cli (1.0.0-beta.15):
add this line in src/index.html
<script src="/vendor/lodash/lodash.js" type="text/javascript"></script>
and in your component where you want to use , try this way
declare var _:any;
#Component({
})
export class YourComponent {
ngOnInit() {
console.log(_.chunk(['a', 'b', 'c', 'd'], 2));
}
}
I tried straight away , it worked for me
In order to support 3rd party libraries in Angular CLI and System.js, you have to specify them manually on system.config.ts and angular-cli-build.js.
I've answered it here with example for lodash and also other dependencies.
As of 4/15/2017 with #angular/cli 1.0.0:
You need to be very specific about which versions you install otherwise the TypeScript bindings will give all sorts of failures. What I did is update my devDependencies as follows in package.json:
"#types/lodash": "ts2.0"

How to set a bower package dependencies?

I'm creating a bower package named X who depends to angular-local-storage.
I saved angular-local-storage in my bower.json.
My module is declared as :
angular.module('X', ['LocalStorageModule']);
The service as :
angular
.module('X')
.service('XService', XService);
function XService($resource, $q, $window, LocalStorageService) {...}
When I install the package X with bower in another project, LocalStorageModule is not found.
How can I manage this dependencies ?
EDIT : the error is:
Unknown provider: LocalStorageServiceProvider <- LocalStorageService <- XService
Add 'LocalStorageModule' to your main module's list of dependencies.
Include angular-local-storage.js (or angular-local-storage.min.js) from the dist directory in your index.html, after including Angular itself.
More
I would suggest you layout your factory or service this way:
.service('ServiceName', ['$log','OtherService', function($log, OtherService){
var serviceInstance = {};
//stuff
return serviceInstance;
}]);
This has more boilerplate than you absolutely need, but it is minification safe and keeps your namespaces clean.
In order to build a bower package, you need to make sure you follow these steps:
bower package: X
prepare a bower.json with this following (minimal) configuration:
{
"name": "your-package-x",
"version": "1.0.0",
"main": "dist/your-package-x.min.js",
"dependencies": {
"angular": "1.5.0",
"angular-local-storage": "2.0.7"
...
}
}
build all the package's files into dist/your-package-x.min.js (using your favorite build tool)
if the package has HTML templates, you should build a templateCache file and append it to the built file (using your build tool):
a. exemple with grunt: https://www.npmjs.com/package/grunt-angular-templates
b. exemple with gulp: https://www.npmjs.com/package/gulp-angular-templatecache
publish to bower
External project
add your-package-x dependency to your bower.json:
{
"name": "main-project",
"version": "1.0.0",
"dependencies": {
"your-package-x": "path to repo or version"
...
}
}
install bower deps
Inject the package-x and its dependencies:
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
<script src="bower_components/dist/your-package-x/dist/your-package-x.min.js"></script>
==> or use a build tool to do it for you (look for wiredep)
I hope this quick guide would help.

gulp-jasmine Window is not defined error

I am using gulp / gulp-jasmine / angular to run my unit tests. However, I encounter the following error when running my Gulp target:
C:\Projects\website2>gulp test
[01:53:10] Using gulpfile C:\Projects\website2\gulpfile.js
[01:53:10] Starting 'test'...
[01:53:11] Version: webpack 1.4.13
Asset Size Chunks Chunk Names
test.bundle.js 1051728 0 [emitted] test
F
Failures:
1) Exception loading: C:\Projects\website2\scripts\dist\test.bundle.js Error
1.1) ReferenceError: window is not defined
1 spec, 1 failure
Finished in 0.015 seconds
[01:53:11] 'test' errored after 916 ms
[01:53:11] Error in plugin 'gulp-jasmine'
Message:
Tests failed
I believe gulp-jasmine uses PhantomJS (no browser window is triggered). Can someone help me with what I'm doing wrong? Is there a configuration setting I'm missing?
Here is my gulpfile.js:
var gulp = require('gulp');
var path = require('path');
var webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config');
var testWebpackConfig = require('./test.webpack.config');
var jasmine = require('gulp-jasmine');
gulp.task('default', ['build'], function() {
});
gulp.task('build', function() {
return gulp.src(['scripts/app/**/*.js', '!scripts/app/**/*.tests.js'])
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('scripts/dist'));
});
gulp.task('test', function() {
return gulp.src(['scripts/app/**/*.tests.js'])
.pipe(webpack(testWebpackConfig))
.pipe(gulp.dest('scripts/dist'))
.pipe(jasmine());
});
gulp-jasmine runs the tests through Node.js and thus is not suitable for client side testing, see https://github.com/sindresorhus/gulp-jasmine/issues/46
For client side tests, if you want to use Jasmine (instead of Karma or in parallel), you can write a SpecRunner.html file (the name does not matter) and run it in your browser:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner</title>
<!-- You need to specify package 'jasmine-core' in your Node.js package.json -->
<link rel="shortcut icon" href="node_modules/jasmine-core/images/jasmine_favicon.png">
<link rel="stylesheet" href="node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script src="node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
<!-- Source and Spec dependencies -->
<script src="node_modules/underscore/underscore.js"></script>
<script src="node_modules/angular/angular.js"></script>
<script src="node_modules/angular-mocks/angular-mocks.js"></script>
<!-- Source files -->
<script src="app/MySourceCode1.js"></script>
<script src="app/MySourceCode2.js"></script>
<!-- Spec files -->
<script src="test/MySourceCode1.spec.js"></script>
<script src="test/MySourceCode2.spec.js"></script>
</head>
<body>
</body>
</html>
Or use gulp-jasmine-browser:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
// You need to specify packages 'jasmine-core' and 'gulp-jasmine-browser'
// in your Node.js package.json
gulp.task('jasmine', function() {
return gulp.src([
'node_modules/underscore/underscore.js',
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'app/MySourceCode1.js',
'app/MySourceCode2.js',
'test/MySourceCode1.spec.js',
'test/MySourceCode2.spec.js',
])
.pipe($.jasmineBrowser.specRunner())
.pipe($.jasmineBrowser.server());
});
Or use Karma :)
I was able to solve this another way using PhantomJS for the headless browser, karma for the command-line test runner, jasmine for the test framework, and gulp for the task runner.
karma.conf.js
module.exports = function(config) {
config.set({
basePath: './',
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'index-controller.js',
'index-controller.tests.js'
],
exclude: [
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['PhantomJS'],
plugins: [
'karma-jasmine',
'karma-junit-reporter',
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-phantomjs-launcher'
],
junitReporter: {
outputFile: 'unit.xml',
suite: 'unit'
}
})
}
Install the necessary npm modules:
npm install angular
npm install angular-mocks
npm install -g gulp
npm install gulp
npm install karma
npm install -g karma-cli
npm install karma-jasmine
npm install karma-junit-reporter
npm install karma-chrome-launcher
npm install karma-firefox-launcher
npm install karma-phantomjs-launcher
npm install phantomjs
Update your gulpfile.js and provide two tasks: the default task to run the unit tests once, a TDD task to watch the file system and run the tests when any file changes:
gulpfile.js
var gulp = require('gulp');
var karma = require('karma').server;
gulp.task('default', function(done) {
karma.start({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done);
});
gulp.task('tdd', function (done) {
karma.start({
configFile: __dirname + '/karma.conf.js'
}, done);
});
To trigger:
gulp default
gulp tdd
For completeness, here is my index-controller, and associated test:
index-controller.js
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.name = 'mickey mouse';
});
index-controller.tests.js
describe('index-controller', function() {
beforeEach(module('app'));
var $controller;
beforeEach(inject(function(_$controller_){
// The injector unwraps the underscores (_) from around the
// parameter names when matching
$controller = _$controller_;
}));
describe('$scope.name', function() {
it('should be mickey mouse', function() {
var $scope = {};
var controller = $controller('ctrl', { $scope: $scope });
expect($scope.name).toEqual('mickey mouse');
});
});
});

ReactJS NPM module: Undefined error

I copied a ReactJS project to a new folder, made some changes, and it's not finding the react NPM module. I stripped the app down to 1 simple file, took out all the major code. This is driving me nuts, I deleted the node_modules folder, and ran NPM install.
I'm using watchify:
watchify --debug -t reactify app3.jsx -o ./build/app-brow.js
I Restarted my Terminal console in case that was out of sync, still can't find react.
I copied the original project to another folder, and it works OK from that copy, there's something about the code/files below that I'm missing.
It shows Uncaught TypeError: undefined is not a function, here which is the JS return code in my render:
React.createElement("div", null,
"Test, TEST TEST."
)
FILES:
app.jsx
/** #jsx React.DOM */
var React = require('react');
var App = React.createClass({
render: function() {
return (
<div>
Test, TEST TEST.
</div>
);
}
});
React.renderComponent((
<App />
), document.body);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test 3</title>
</head>
<body>
HAH... If you see this there is an error, make sure JavaScript is enabled in your browser.
<script type="text/javascript" src="build/app-brow.js"></script>
</body>
</html>
package.json
{
"name": "Test3",
"dependencies": {
"react": "0.11.x",
"reactify": "0.14.0"
}
}
Reactify is compiling your JSX in the React 0.12 style, but you are using React 0.11. Either upgrade React to 0.12.x or downgrade Reactify to a version that uses react-tools 0.11.

Resources