Skip to content

Commit 5ccdeb7

Browse files
committed
feat(gen): Support for server rendering and Angular's HTML5 mode
Server now uses EJS rendering to serve html views. New structure should allow Jade support later on. Additionally, HTML5 mode is now supported. All un-specified server routes now redirect to index so the angular routing system handles them. BREAKING CHANGE: angular-fullstack:route and angular-fullstack:view will now generate views and routes in the views/partials folder. For existing projects: Please install generator-angular and use it's subgenerators for creating routes and views. They are exactly the same as the generators that you have been using. Example usage: yo angular:route helloworld. For New projects: Continue to use angular-fullstack route and view subgenerators. The reason for this change in folder structure was to support server page rendering. Closes #18, #17
1 parent fce23c0 commit 5ccdeb7

File tree

15 files changed

+103
-52
lines changed

15 files changed

+103
-52
lines changed

Diff for: app/index.js

+30-18
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,26 @@ Generator.prototype.bootstrapJS = function bootstrapJS() {
241241
}
242242

243243
// Wire Twitter Bootstrap plugins
244-
this.indexFile = this.appendScripts(this.indexFile, 'scripts/plugins.js', [
245-
'bower_components/sass-bootstrap/js/affix.js',
246-
'bower_components/sass-bootstrap/js/alert.js',
247-
'bower_components/sass-bootstrap/js/button.js',
248-
'bower_components/sass-bootstrap/js/carousel.js',
249-
'bower_components/sass-bootstrap/js/transition.js',
250-
'bower_components/sass-bootstrap/js/collapse.js',
251-
'bower_components/sass-bootstrap/js/dropdown.js',
252-
'bower_components/sass-bootstrap/js/modal.js',
253-
'bower_components/sass-bootstrap/js/scrollspy.js',
254-
'bower_components/sass-bootstrap/js/tab.js',
255-
'bower_components/sass-bootstrap/js/tooltip.js',
256-
'bower_components/sass-bootstrap/js/popover.js'
257-
]);
244+
this.indexFile = this.appendFiles({
245+
html: this.indexFile,
246+
fileType: 'js',
247+
optimizedPath: 'scripts/plugins.js',
248+
sourceFileList: [
249+
'bower_components/sass-bootstrap/js/affix.js',
250+
'bower_components/sass-bootstrap/js/alert.js',
251+
'bower_components/sass-bootstrap/js/button.js',
252+
'bower_components/sass-bootstrap/js/carousel.js',
253+
'bower_components/sass-bootstrap/js/transition.js',
254+
'bower_components/sass-bootstrap/js/collapse.js',
255+
'bower_components/sass-bootstrap/js/dropdown.js',
256+
'bower_components/sass-bootstrap/js/modal.js',
257+
'bower_components/sass-bootstrap/js/scrollspy.js',
258+
'bower_components/sass-bootstrap/js/tab.js',
259+
'bower_components/sass-bootstrap/js/tooltip.js',
260+
'bower_components/sass-bootstrap/js/popover.js'
261+
],
262+
searchPath: 'app'
263+
});
258264
};
259265

260266
Generator.prototype.extraModules = function extraModules() {
@@ -274,10 +280,15 @@ Generator.prototype.extraModules = function extraModules() {
274280
if (this.routeModule) {
275281
modules.push('bower_components/angular-route/angular-route.js');
276282
}
277-
283+
278284
if (modules.length) {
279-
this.indexFile = this.appendScripts(this.indexFile, 'scripts/modules.js',
280-
modules);
285+
this.indexFile = this.appendFiles({
286+
html: this.indexFile,
287+
fileType: 'js',
288+
optimizedPath: 'scripts/modules.js',
289+
sourceFileList: modules,
290+
searchPath: 'app'
291+
});
281292
}
282293
};
283294

@@ -292,7 +303,7 @@ Generator.prototype.appJs = function appJs() {
292303
};
293304

294305
Generator.prototype.createIndexHtml = function createIndexHtml() {
295-
this.write(path.join(this.appPath, 'index.html'), this.indexFile);
306+
this.write(path.join(this.appPath, 'views', 'index.html'), this.indexFile);
296307
};
297308

298309
Generator.prototype.packageFiles = function () {
@@ -304,6 +315,7 @@ Generator.prototype.packageFiles = function () {
304315
Generator.prototype.serverFiles = function () {
305316
this.template('../../templates/express/server.js', 'server.js');
306317
this.template('../../templates/express/api.js', 'lib/controllers/api.js');
318+
this.template('../../templates/express/index.js', 'lib/controllers/index.js');
307319
};
308320

309321
Generator.prototype.mongoFiles = function () {

Diff for: route/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Generator.prototype.rewriteAppJs = function () {
2222
),
2323
needle: '.otherwise',
2424
splicable: [
25-
" templateUrl: 'views/" + this.name + ".html'" + (coffee ? "" : "," ),
25+
" templateUrl: 'views/partials/" + this.name + ".html'" + (coffee ? "" : "," ),
2626
" controller: '" + this.classedName + "Ctrl'"
2727
]
2828
};

Diff for: templates/coffeescript-min/app.coffee

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
'use strict'
22

33
angular.module('<%= scriptAppName %>', [<%= angularModules %>])
4-
.config ['$routeProvider', ($routeProvider) ->
4+
.config ['$routeProvider', '$locationProvider', ($routeProvider, $locationProvider) ->
55
$routeProvider
66
.when '/',
77
templateUrl: 'views/main.html'
88
controller: 'MainCtrl'
99
.otherwise
1010
redirectTo: '/'
11+
$locationProvider.html5Mode(true)
1112
]

Diff for: templates/coffeescript/app.coffee

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use strict'
22

33
angular.module('<%= scriptAppName %>', [<%= angularModules %>])
4-
.config ($routeProvider) ->
4+
.config ($routeProvider, $locationProvider) ->
55
$routeProvider
66
.when '/',
77
templateUrl: 'views/main.html'
88
controller: 'MainCtrl'
99
.otherwise
1010
redirectTo: '/'
11+
$locationProvider.html5Mode(true)

Diff for: templates/common/Gruntfile.js

+12-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ module.exports = function (grunt) {
1515
yeoman: {
1616
// configurable paths
1717
app: require('./bower.json').appPath || 'app',
18-
dist: 'public'
18+
dist: 'public',
19+
views: 'views'
1920
},
2021
express: {
2122
options: {
@@ -53,7 +54,7 @@ module.exports = function (grunt) {
5354
},<% } %>
5455
livereload: {
5556
files: [
56-
'<%%= yeoman.app %>/{,*//*}*.html',
57+
'<%%= yeoman.app %>/<%%= yeoman.views %>/{,*//*}*.html',
5758
'{.tmp,<%%= yeoman.app %>}/styles/{,*//*}*.css',
5859
'{.tmp,<%%= yeoman.app %>}/scripts/{,*//*}*.js',
5960
'<%%= yeoman.app %>/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}',
@@ -98,6 +99,7 @@ module.exports = function (grunt) {
9899
dot: true,
99100
src: [
100101
'.tmp',
102+
'<%%= yeoman.views %>/*',
101103
'<%%= yeoman.dist %>/*',
102104
'!<%%= yeoman.dist %>/.git*'
103105
]
@@ -188,13 +190,13 @@ module.exports = function (grunt) {
188190
}
189191
},
190192
useminPrepare: {
191-
html: '<%%= yeoman.app %>/index.html',
193+
html: '<%%= yeoman.app %>/<%%= yeoman.views %>/index.html',
192194
options: {
193195
dest: '<%%= yeoman.dist %>'
194196
}
195197
},
196198
usemin: {
197-
html: ['<%%= yeoman.dist %>/{,*/}*.html'],
199+
html: ['<%%= yeoman.views %>/{,*/}*.html'],
198200
css: ['<%%= yeoman.dist %>/styles/{,*/}*.css'],
199201
options: {
200202
assetsDirs: ['<%%= yeoman.dist %>']
@@ -248,9 +250,9 @@ module.exports = function (grunt) {
248250
},
249251
files: [{
250252
expand: true,
251-
cwd: '<%%= yeoman.app %>',
252-
src: ['*.html', 'views/*.html'],
253-
dest: '<%%= yeoman.dist %>'
253+
cwd: '<%%= yeoman.app %>/<%%= yeoman.views %>',
254+
src: ['*.html', 'partials/*.html'],
255+
dest: '<%%= yeoman.views %>'
254256
}]
255257
}
256258
},
@@ -284,7 +286,8 @@ module.exports = function (grunt) {
284286
dot: true,
285287
dest: 'heroku',
286288
src: [
287-
'<%%= yeoman.dist %>/**'
289+
'<%%= yeoman.dist %>/**',
290+
'<%= yeoman.views %>/**'
288291
]
289292
}, {
290293
expand: true,
@@ -331,7 +334,7 @@ module.exports = function (grunt) {
331334
},
332335
cdnify: {
333336
dist: {
334-
html: ['<%%= yeoman.dist %>/*.html']
337+
html: ['<%%= yeoman.views %>/*.html']
335338
}
336339
},
337340
ngmin: {

Diff for: templates/common/_package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
"name": "<%= _.slugify(appname) %>",
33
"version": "0.0.0",
44
"dependencies": {
5-
"express": "~3.4.3"<% if (mongo) { %>,
6-
"mongoose": "~3.5.5",
5+
"express": "~3.4.3",
6+
"ejs": "~0.8.4"<% if (mongo) { %>,
7+
"mongoose": "~3.5.5",
78
"async": "~0.2.9"<% } %>
89
},
910
"devDependencies": {

Diff for: templates/common/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<head>
77
<meta charset="utf-8">
88
<meta http-equiv="X-UA-Compatible" content="IE=edge">
9+
<base href="/"/>
910
<title></title>
1011
<meta name="description" content="">
1112
<meta name="viewport" content="width=device-width">
File renamed without changes.

Diff for: templates/express/index.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
5+
exports.partials = function(req, res) {
6+
var requestedView = path.join('./', req.url);
7+
res.render(requestedView, function(err, html) {
8+
if(err) {
9+
res.render('404');
10+
} else {
11+
res.send(html);
12+
}
13+
});
14+
};
15+
16+
exports.index = function(req, res) {
17+
res.render('index');
18+
};

Diff for: templates/express/server.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,44 @@ fs.readdirSync(modelsPath).forEach(function (file) {
1919
// Populate empty DB with dummy data
2020
require('./lib/db/dummydata');
2121
<% } %>
22-
// Controllers
23-
var api = require('./lib/controllers/api');
2422

2523
// Express Configuration
26-
app.configure(function(){
27-
app.use(express.logger('dev'));
28-
app.use(express.bodyParser());
29-
app.use(express.methodOverride());
30-
app.use(app.router);
31-
});
32-
3324
app.configure('development', function(){
3425
app.use(require('connect-livereload')());
3526
app.use(express.static(path.join(__dirname, '.tmp')));
3627
app.use(express.static(path.join(__dirname, 'app')));
3728
app.use(express.errorHandler());
29+
app.set('views', __dirname + '/app/views');
3830
});
3931

4032
app.configure('production', function(){
41-
app.use(express.favicon(path.join(__dirname, 'public/favicon.ico')));
33+
app.use(express.favicon(path.join(__dirname, 'public', 'favicon.ico')));
4234
app.use(express.static(path.join(__dirname, 'public')));
35+
app.set('views', __dirname + '/views');
4336
});
4437

45-
// Routes
38+
app.configure(function(){
39+
app.engine('html', require('ejs').renderFile);
40+
app.set('view engine', 'html');
41+
app.use(express.logger('dev'));
42+
app.use(express.bodyParser());
43+
app.use(express.methodOverride());
44+
45+
// Router needs to be last
46+
app.use(app.router);
47+
});
48+
49+
// Controllers
50+
var api = require('./lib/controllers/api'),
51+
controllers = require('./lib/controllers');
52+
53+
// Server Routes
4654
app.get('/api/awesomeThings', api.awesomeThings);
4755

56+
// Angular Routes
57+
app.get('/partials/*', controllers.partials);
58+
app.get('/*', controllers.index);
59+
4860
// Start server
4961
var port = process.env.PORT || 3000;
5062
app.listen(port, function () {

Diff for: templates/javascript-min/app.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use strict';
22

33
angular.module('<%= scriptAppName %>', [<%= angularModules %>])
4-
.config(['$routeProvider', function ($routeProvider) {
4+
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
55
$routeProvider
66
.when('/', {
7-
templateUrl: 'views/main.html',
7+
templateUrl: 'partials/main.html',
88
controller: 'MainCtrl'
99
})
1010
.otherwise({
1111
redirectTo: '/'
1212
});
13+
$locationProvider.html5Mode(true);
1314
}]);

Diff for: templates/javascript/app.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use strict';
22

33
angular.module('<%= scriptAppName %>', [<%= angularModules %>])
4-
.config(function ($routeProvider) {
4+
.config(function ($routeProvider, $locationProvider) {
55
$routeProvider
66
.when('/', {
7-
templateUrl: 'views/main.html',
7+
templateUrl: 'partials/main.html',
88
controller: 'MainCtrl'
99
})
1010
.otherwise({
1111
redirectTo: '/'
1212
});
13+
$locationProvider.html5Mode(true);
1314
});

Diff for: test/test-file-creation.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('Angular generator', function () {
7272
'server.js',
7373
['bower.json', /"name":\s+"temp"/],
7474
'app/scripts/app.js',
75-
'app/index.html',
75+
'app/views/index.html',
7676
'app/scripts/controllers/main.js',
7777
'test/spec/controllers/main.js'
7878
];
@@ -100,7 +100,7 @@ describe('Angular generator', function () {
100100
'package.json',
101101
['bower.json', /"name":\s+"temp"/],
102102
'app/scripts/app.coffee',
103-
'app/index.html',
103+
'app/views/index.html',
104104
'app/scripts/controllers/main.coffee',
105105
'test/spec/controllers/main.coffee'
106106
];
@@ -221,7 +221,7 @@ describe('Angular generator', function () {
221221
angular.run([], function (){
222222
angularView.run([], function () {
223223
helpers.assertFiles([
224-
['app/views/foo.html']
224+
['app/views/partials/foo.html']
225225
]);
226226
done();
227227
});
@@ -241,7 +241,7 @@ describe('Angular generator', function () {
241241
angular.run([], function (){
242242
angularView.run([], function () {
243243
helpers.assertFiles([
244-
['app/views/foo/bar.html']
244+
['app/views/partials/foo/bar.html']
245245
]);
246246
done();
247247
});

Diff for: view/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ var Generator = module.exports = function Generator() {
1919
util.inherits(Generator, yeoman.generators.NamedBase);
2020

2121
Generator.prototype.createViewFiles = function createViewFiles() {
22-
this.template('common/view.html', path.join(this.env.options.appPath, 'views', this.name + '.html'));
22+
this.template('common/view.html', path.join(this.env.options.appPath, 'views', 'partials', this.name + '.html'));
2323
};

0 commit comments

Comments
 (0)