No Directive annotation found on TodoApp Server Rendering - angularjs

I'm trying to do server rendering with angular2-universal. I copy paste the example todo app of the official repo https://github.com/angular/universal/tree/master/examples/src/universal/todo into my own Trails/Express server.
I manage to start my server but when I call http://localhost:3000 I have the following error :
Error: No Directive annotation found on TodoApp
at new BaseException (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/compiler/src/facade/exceptions.js:17:23)
at DirectiveResolver.resolve (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/compiler/src/directive_resolver.js:31:15)
at CompileMetadataResolver.getDirectiveMetadata (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/compiler/src/metadata_resolver.js:55:51)
at RuntimeCompiler.resolveComponent (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/compiler/src/runtime_compiler.js:34:47)
at /Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/application_ref.js:99:37
at /Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/application_ref.js:292:26
at ZoneDelegate.invoke (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/zone.js/dist/zone-node.js:281:29)
at Object.NgZoneImpl.inner.inner.fork.onInvoke (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/zone/ng_zone_impl.js:45:41)
at ZoneDelegate.invoke (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/zone.js/dist/zone-node.js:280:35)
at Zone.run (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/zone.js/dist/zone-node.js:174:44)
at NgZoneImpl.runInner (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/zone/ng_zone_impl.js:76:71)
at NgZone.run (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/zone/ng_zone.js:223:66)
at ApplicationRef_.run (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/application_ref.js:290:14)
at Object.coreLoadAndBootstrap (/Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/#angular/core/src/application_ref.js:96:19)
at /Users/jaumard/IdeaProjects/trails-angular2-isomorphic/node_modules/angular2-universal/dist/node/bootloader.js:186:34
at Array.map (native)
The example of the universal repo is working so I don't understand why it's not working for me. I don't change anything on the angular2 sources.
All my code is here https://github.com/jaumard/trails-angular2-isomorphic with the configuration here https://github.com/jaumard/trails-angular2-isomorphic/blob/master/api/controllers/ViewController.js#L58 for the route and here for the template engine https://github.com/jaumard/trails-angular2-isomorphic/blob/master/config/web.js#L76

Your problem is that you're working with different packages angular2 at the same time.
You start server with modules from ./node_modules/ folder but your component TodoApp will be decorated by instance ComponentMetadata (extends DirectiveMetadata) from ./dist/src/node_modules/#angular/core/ folder.
I think that first you need to transfer packages to dist folder and then run server. And you have to use the same path to angular2 modules (./dist/src/node_modules)
For example you can try something like this:
server.js
'use strict'
const gulp = require('gulp');
const rimraf = require('gulp-rimraf');
const path = require('path');
const dest = './dist';
gulp.task('clean', (cb) => {
return gulp.src(dest).pipe(rimraf())
});
gulp.task('prerun', ['clean'], () => {
return gulp.src([
'node_modules/rxjs/**/*',
'node_modules/zone.js/**/*',
'node_modules/core-js/**/*',
'node_modules/reflect-metadata/**/*',
'node_modules/systemjs/**/*',
'node_modules/#angular/**/*',
'node_modules/angular2-universal/**/*',
'node_modules/angular2-universal-polyfills/**/*',
'node_modules/angular2-express-engine/**/*',
'node_modules/angular2-hapi-engine/**/*'
], { base: './' })
.pipe(gulp.dest(path.join(dest, 'src')))
});
gulp.start('prerun', run)
function run() {
require('./dist//src/node_modules/angular2-universal/polyfills')
const app = require('./')
const TrailsApp = require('trails')
const server = new TrailsApp(app)
server.start().catch(err => server.stop(err))
}
I added reflect-metadata in package.json. Also you need to change a bit componentUrl like this:
ViewController.js
module.exports = class ViewController extends Controller {
helloWorld(req, res) {
const todoApp = require('../../dist/src/todo/app')
let queryParams = ng2U.queryParamsToBoolean(req.query);
let options = Object.assign(queryParams , {
// client url for systemjs
buildClientScripts: true,
systemjs: {
componentUrl: 'todo/browser', <== remove src/
map: {
'angular2-universal': 'node_modules/angular2-universal',
'#angular': 'node_modules/#angular'
},
packages: PACKAGES
},
...
Then you can see the following error:
So you need to add rxjs in your configuration:
ViewController.js
const PACKAGES = {
'angular2-universal/polyfills': {
format: 'cjs',
main: 'dist/polyfills',
defaultExtension: 'js'
},
...
rxjs: { <== this property
defaultExtension: 'js'
}
};
...
systemjs: {
componentUrl: 'todo/browser',
map: {
'angular2-universal': 'node_modules/angular2-universal',
'#angular': 'node_modules/#angular',
'rxjs': 'node_modules/rxjs' <== this line
},
packages: PACKAGES
},
See also the full list of changes here https://github.com/alexzuza/trails-angular2-isomorphic/commit/45f2e59529821757f6a6c03c5872e08fdce3f3e7
Hope it helps you!

Related

Gulp with React not compiling a functional component correctly

I have the following gulpfile.js:
var gulp = require('gulp'),
babel = require('gulp-babel'),
concat = require('gulp-concat'),
react = require('gulp-react'),
sass = require('gulp-sass'),
jsxToJs = function() {
//gulp.src('src/**/*.js')
gulp.src('./src/sections/header/header.js')
.pipe(react())
.pipe(babel({
presets: ['es2015']
}))
.pipe(concat('javascript.js'))
.pipe(gulp.dest('./'));
};
gulp.task('jsxToJs', jsxToJs);
gulp.task('build', ['jsxToJs', 'styles']);
gulp.task('watch', function () {
gulp.watch([
'./src/**/*.js',
'./src/**/*.scss'
], [
'jsxToJs',
'styles'
]);
});
gulp.task('default', ['build', 'watch']);
And I'm trying to compile the following functional React component:
let Header = (props) => {
return(
<div />
);
};
However, when I run the javascript.js file created by gulp I get the following error:
Uncaught TypeError: e.render is not a function
If I convert the component back to the old way of doing things like this (which is how I found it as I'm revisiting an old problem):
var Header = React.createClass({
render: function() {
}
});
Then it works.
Looking at the compiled JS shows me this - where I can see that render is being compiled out correctly with the old syntax, but for the new syntax, while it's being ESfivified it's not being reactified:
// not working
"use strict";
var Header = function Header(props) {
return React.createElement("div", );
};
// working
"use strict";
var Header = React.createClass({ displayName: "Header",
render: function render() {
return React.createElement("div", );
}
});
I've checked that I've installed my gulp requires correctly and I'm using Node 6.10.2. My gulp file has some extra things for scss in that I've removed for this question.
A couple of other points:
I'm not using a bundling tool like browserify as I think it's overkill for this project - so no imports or exports.
I'm just loading HTML pages that do JSONP to an endpoint and load a script on page that includes the JSON - this is done in a getInitialState in the page level HOCs.
Can anyone explain what I'm doing wrong?
The solution turned out to be pretty simple.
Babel requires presets to be provided in order to transpile.
I had the es2015 preset, but not the react one. Therefore react specific tranpilations were not occurring. This addition fixed the problem:
.pipe(react())
.pipe(babel({
presets: ['es2015', 'react']
}))
The mistake I was making, that sent me down the wrong rabbit hole in Google, was assuming that failing to reactify was something to do with the gulp-react function - silly me.

Grunt-browserify external libs give: Cannot find module

I'm working on app with Backbone Marionette and i'm building my files with grunt-browserify 3.8.
Backbone, Marionette, underscore and jQuery are added with npm.
I'm compiling all my files in one single file.
Everything was working fine but the build was extremly slow (like 1.5mins) so i read about using external config option in grunt-browserify.
Now the build is quite fast but when i access to the page i got:
Uncaught Error: Cannot find module 'underscore' to the line when i first use my require function
I read everywhere but i cannot figured out the correct configuration for grunt-brwoserify.
Here is my GruntFile:
'use strict';
module.exports = function (grunt) {
require('grunt-config-dir')(grunt, {
configDir: require('path').resolve('tasks')
});
require('jit-grunt')(grunt);
// show elapsed time at the end
require('time-grunt')(grunt);
grunt.registerTask('i18n', [ 'clean', 'dustjs', 'clean:tmp' ] ); // not used for now
grunt.registerTask('build', ['i18n', 'less', 'cssmin', 'browserify', 'concurrent:build'] );
grunt.registerTask('serve', [ 'build', 'concurrent:server'] ); // Build & run the server locally, for development.
};
Here my Browserify task:
'use strict';
module.exports = function browserify(grunt) {
// Load task
grunt.loadNpmTasks('grunt-browserify');
// Options
return {
build: {
files: {
'.build/js/theme-smarty.js': ['public/js/assets/smarty-themeApp/plugin/jquery.min.js', 'public/js/assets/smarty-themeApp/**/*.js'],
'.build/js/app-bundled.js': ['public/js/app.js'],
'.build/js/landing-page.js': ['public/js/landing-page.js']
// '.build/js/app-admin-bundled.js': ['public/js/app-admin.js']
},
options: {
// activate watchify
watch: true,
watchifyOptions: {
spawn: false
},
include: [
'public/js/**/*.js'
],
transform: [['babelify', {'presets': 'es2015', 'compact': false}]],
external: [
'backbone',
'underscore',
'jquery',
'backbone.marionette'
]
}
}
};
};
And here my first views where i require libs:
'use strict';
const
_ = require('underscore'),
$ = require('jquery'),
Backbone = require('backbone'),
Marionette = require('backbone.marionette'),
MainRouter = require('./main-router'),
MainController = require('./main-controller');
Backbone.$ = $;
let View = Marionette.LayoutView.extend({
template: require('./main-page.dust'),
regions: {
mainContainer: '.main-container',
modalContainer: '.modal-container'
},
initialize: function () {
this.model = new Backbone.Model({
page: this.$el.data('page')
});
new MainRouter({
controller: new MainController({
mainContainer: this.mainContainer,
modalContainer: this.modalContainer
})
});
},
onRender: function () {
Backbone.history.start({pushState: true});
}
});
module.exports = View;
Look like libs are not even compiled in my app-bundled.js files.
What's the best/correct way to compile them?
Is better to have two separate files? libs and app?
Is possible to do with just one file using libs from npm?

Grunt - Get variable exported in the environemnt to string in a file

Hi I would like to do a simple task:
export a variable in linux:
export API = "http://127.0.0.1:999"
then get it with grunt script.
And replace a row inside my apiService.
currently i wasn't able to console.log the environment variable:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
destination: process.env.API,
grunt.loadNpmTasks('grunt-envpreprocess');
grunt.registerTask('default',['watch']);
console.log("here: " + process.env.API);
};
Can someone help me figure out how to do that?
THanks
you did not close curly bracket (LN5), try something like this:
const grunt = require('grunt');
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
destination: process.env.API || 'none',
});
grunt.registerTask('default', () => {
console.log("here: ", grunt.config.get('destination'));
});
};

Angular 2 system-config.ts doesn't seem to be working with my app specific barrels

Here is my system-config.ts:
'use strict';
// SystemJS configuration file, see links for more information
// https://github.com/systemjs/systemjs
// https://github.com/systemjs/systemjs/blob/master/docs/config-api.md
/***********************************************************************************************
* User Configuration.
**********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
'moment': 'vendor/moment/moment.js',
'ng2-bootstrap': 'vendor/ng2-bootstrap'
};
/** User packages configuration. */
const packages: any = {
'moment': {
format: 'cjs'
},
'ng2-bootstrap': {
format: 'cjs',
defaultExtension: 'js',
main: 'ng2-bootstrap.js'
}
};
////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
* Everything underneath this line is managed by the CLI.
**********************************************************************************************/
const barrels: string[] = [
// Angular specific barrels.
'#angular/core',
'#angular/common',
'#angular/compiler',
'#angular/forms',
'#angular/http',
'#angular/router',
'#angular/platform-browser',
'#angular/platform-browser-dynamic',
// Thirdparty barrels.
'rxjs',
// App specific barrels.
'app',
'app/shared',
'app/photos'
/** #cli-barrel */
];
const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
cliSystemConfigPackages[barrelName] = { main: 'index' };
});
/** Type declaration for ambient System. */
declare var System: any;
// Apply the CLI SystemJS configuration.
System.config({
map: {
'#angular': 'vendor/#angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js'
},
packages: cliSystemConfigPackages
});
// Apply the user's configuration.
System.config({ map, packages });
I am able to import all the modules EXCEPT for the app specific barrels.
So, import { AlertComponent } from 'ng2-bootstrap/ng2-bootstrap'; works just fine.
However, import { PhotoService } from 'app/shared'; does not.
I am exporting correctly because if I do import { PhotoService } from '../../shared'; it works.
Can someone help me out? What am I doing wrong?
Needs to be a relative path.
import { PhotoService } from './app/shared';
That's why ../../* works. Doesn't have anything to do with system.

Express.js with Foundation for Apps

I am trying to set up the Express.js web framework to use with the foundation for apps architecture. I am relatively new to the Node world.
What changes must I make to the gulpfile.js, and app.js to get this up and running? I would imagine the use of gulp-express dependency can come in handy, but there is so much going on that I don't know what would break.
Relevant code:
package.json:
{
...
"scripts": {
"start": "gulp"
},
"devDependencies": {
...
}
app.js (Don't know how to tie these together..):
var express = require('express');
var app = module.exports.app = exports.app = express();
app.use(require('connect-livereload')());
(function() {
'use strict';
var myApplication = angular.module('TODO', [
'ui.router',
'ngAnimate',
'foundation.core',
...
gulpfile.js:
var gulp = ...
...
var server = require('gulp-express');
gulp.task('server:start', function() {
// connect.server({
// root: './build',
// middleware: function() {
// return [
// modRewrite(['^[^\\.]*$ /index.html [L]'])
// ];
// },
// });
server.run({
root: './build',
file: './build/assets/js/app.js'
});
});
FileStructure:
build/
...
client/
-assets/
-img/
-scss/
-js/
-app.js
node_modules/
...
bower.json
Gemfile
Gemfile.lock
gulpfile.js
package.json
I worked through this small tut once upon a time, this would be a good place to start for node / express and should give you the basic idea of how it hangs together (easier than me trying to explain it anyway):
http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/
I would also recommend checking out the express API guide on their website.

Resources