Pergunta

I'm building multiple applications using Durandal JS. All those applications are located on the same server under the same document root and share some common code. For example they all use the same model & view for login.

How can i reuse/share the login model & view in all those applications without just copy & pasting the files to the projects?

I already tried something with the following folder structure:

ProjectsDir/Project1/app/durandal/..
                        /models/Shell.js, Main.js, ...
                        /views/Shell.html, Main.html, ...
                        /main.js
                        /main-built.js

ProjectsDir/Project2/app/durandal/..
                        /models/Shell.js, Main.js, ...
                        /views/Shell.html, Main.html, ...
                        /main.js
                        /main-built.js

ProjectsDir/ProjectsBase/app/models/Login.js
                            /views/Login.html

This way it would be possible to reference the same login model & view in my ProjectsBase from all other projects by setting the correct route to it in the respective shell.js. This route could look something like this:

router.map([
    {
        url: 'Login',
        moduleId: '../../ProjectsBase/app/models/Login',
        name:'Login',
        visible: true
    },
    {
        url: 'Main',
        moduleId: 'models/Main',
        name:'Main',
        visible: true
    }
]);

This works as expected during debugging but building the production version with the durandal optimizer unfortunately doesn't work. Actually building does work (it produces the main-built.js just fine) but when i launch the site with the production file referenced i get the following error:

Uncaught Error: undefined missing durandal/../../../MPBase/durandal-app/models/Login

I'd really appreciate any ideas on how I could make the built production file work with the setup I described above.

Of course I'm also open for other ideas on how to make models & views reusable/sharable between multiple projects.

Thanks

Foi útil?

Solução

With some help from Durandals Google Group I found a solution.

It's not possible to use the provided optimizer.exe but it's quite easy to create a custom r.js config which can handle the setup I described in the question:

First of all I ran the optimizer.exe which created a basic config file (app.build.js) that i used as a starting point. This config file automatically included all necessary files from the project itself (e.g. Project1).

The only things that are missing in this config file are the references to my shared code (the login files from the ProjectsBase directory). Therefore I added them manually along with a new path.

Custom app.build.js (3 changes highlighted with a comment, the rest is how it was built from the optizimer.exe):

{
  "name": "durandal/amd/almond-custom",
  "inlineText": true,
  "stubModules": [
    "durandal/amd/text"
  ],
  "paths": {
    "text": "durandal/amd/text",
    "projectsbase": "../../ProjectsBase/" // New path to folder with shared files
  },
  "baseUrl": "ProjectsDir\\Project1\\app",
  "mainConfigFile": "ProjectsDir\\Project1\\app\\main.js",
  "include": [
    "main",
    "durandal/app",
    "durandal/composition",
    "durandal/events",
    "durandal/http",
    "text!durandal/messageBox.html",
    "durandal/messageBox",
    "durandal/modalDialog",
    "durandal/system",
    "durandal/viewEngine",
    "durandal/viewLocator",
    "durandal/viewModel",
    "durandal/viewModelBinder",
    "durandal/widget",
    "durandal/plugins/router",
    "durandal/transitions/entrance",
    "projectsbase/app/models/Login", // Include for login model
    "models/Main",
    "models/Shell",
    "text!projectsbase/app/views/Login.html", // Include for login view
    "text!views/Main.html",
    "text!views/Shell.html"
  ],
  "exclude": [],
  "keepBuildDir": true,
  "optimize": "uglify2",
  "out": "ProjectsDir\\Project1\\app\\main-built.js",
  "pragmas": {
    "build": true
  },
  "wrap": true,
  "insertRequire": [
    "main"
  ]
}

Now I only had to update my Shell.js to use the correct routes to the Login model & view by also adding a path to requirejs and using it correctly when setting the routes:

Add path at the very beginning of Shell.js:

requirejs.config({
    paths: {
        'projectsbase': '../../ProjectsBase/'
    }
});

Set correct routes in activate method of Shell.js:

router.map([
    { url: 'Login', moduleId: 'projectsbase/app/models/Login', name:'Login', visible: true },
    { url: 'Main', moduleId: 'models/Main', name:'Main', visible: true }
]);

Now i can build my main-built.js which bundles & minifies all relevant files by opening the node js command line, browsing to the directory where the r.js config file is and create the build (the main-built.js) with the following command:

node r.js -o app.build.js

This way everything is included correctly when I'm working with the debug files and it's also working with the build main-built.js which also includes my shared files from the ProjectsBase.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top