I'm currently evaluating Durandal for use in an enterprise ASP.NET MVC application.
However the default conventions used by Durandal seem to conflict with the MVC conventions I've grown accustomed to.
The HotTowel MVC template by John Papa is great, but this too seems to "do away" with MVC conventions in favour of Durandals by putting things in an App folder.
A couple of the issues I have with these conventions are:
- Views are potentially split across two locations (/App/views and /Views).
- Scripts are also split across two locations (/App/durandal and /Scripts).
- Views are not in the default MVC locations for the
RazorViewEngine
.
I would prefer to keep each element contained in the appropriate MVC conventions e.g.
/Controllers/
---- HomeController
---- AdminController
/Scripts/
---- durandal/
---- viewmodels/
-------- Home
-------- Admin
/Views/
---- Home
---- Admin
My questions are:
Is it possible to configure Durandal to achieve the above (or something similar)?
Is it wise to venture away from the default Durandal conventions?
What are the potential issues in doing so?
1. Is it possible to configure Durandal to achieve the above (or something similar)?
Yes, you can have any folder structure your heart desires. Durandal does not impose any folder structure on your application but it does have a default convention which is completely overridable.
If you are using Durandals router then you will want to look into how to configure it to find modules. There are many ways of doing this, I prefer to create my own convention by overriding the router.autoConvertRouteToModuleId
.
If you are not using the router plugin then you will have to manage the uris for your modules yourself and this is done by following requirejs' convention and using this convention along w/ durandals composition module.
Also, you can override how it finds the views to bind to your modules by overriding the viewlocators convention. Durandal provides an very simplistic way of structuring small applications right out of the box but if you need to build larger applications then it is recommended you create your own conventions.
2. Is it wise to venture away from the default Durandal conventions? 3. What are the potential issues in doing so?
So, there are the conventions of how to discover modules and how to discover views which are completely overridable. And I recommend you do override these and choose a way that suites you best. But, as for placing durandal inside your scripts folder as you have listed above I dont think its a good idea.
The reason I dont recommend this is because I see the scripts folder as a place for all your third party scripts that are NON-AMD modules. This is because Durandal also comes with an optimizer.exe which makes minifying/compressing/uglifying all your html/css/js (amd) files into 1 file.
If you keep your entire application under an app folder and then have the durandal folder inside your app folder the optimizer just works because it lives inside the app/durandal/amd folder. So, when you execute it, it will transverse up 2 directories to your app folder and then scan every subfolder to create a app.build.js requirejs optimization file.. and then it will compress your entire application to one file for you.
This beats having to hand edit an app.build.js file everytime you add a new file to your project. Sure.. there are other tools out there which can do this too.. but you will have to spend time learning their api and how to configure them. If you dont feel like devoting the time to learning something like grunt then this optimizer is kick ass. Personally, I like the ability to just double click something and have my whole application built for me.
As for placing all your third party libraries which are non-amd in a seperate scripts folder I would look into compressing those seperately like using MVC's bundling. The reason I would bundle those seperately is because you know those files arnt changing very often and if you bundle those into a seperate js file they can be cached by the browser seperately. Whereas if your spa is changing, which it it probably will.. then you want the browser to cache that seperately so it only has to re-download your compressed application.
What we do (this is what I have seen Rob doing too:) is that to create folders inside the /App folder depending on the functional areas of the app. Then just create view and view model file inside these folders.
Trick is to have a "viewUrl" property in each view model to tell durandal which view to use.
This way of structuring the application is useful for large projects where there are many views/view models ; avoids confusion when your project grows.
define(['durandal/app', 'durandal/system', 'plugins/router'],
function (app, system, router) {
var vm = {
viewUrl: 'myfolder/myview.html',
};
return vm;
}
);
You can still use viewLocator.useConvention(); when you bootstrap your application; durandal will still find the view as long as you have viewUrl property.