为多个 SPA 配置 durandal
Configure durandal for multiple SPA
我有一个网站,从技术上讲,它由许多独立的 SPA 组成。
App/Admin
App/Signup
App/MainApp
我应该如何组织 App 文件夹和 gulp 构建,使其成为 3-4 个单独的文件/模块,在需要时加载。
因为我不得不花一整天的时间来让它工作,所以我会回答我自己的问题。
首先,准备一个loader
站点。这将是实际加载的主要站点,负责加载所有其他站点。
App/main.js - Contains the requirejs setup
In this we would run app.setRoot('shell', 'entrance');
App/shell.js - 包含路由器配置
return router.map([
{ route: 'Admin/*all', moduleId: "Admin/index", nav: true },
{ route: 'Signup/*all', moduleId: "Signup/index", nav: true },
{ route: '*all', moduleId: "MainApp/index", nav: true }
])
.buildNavigationModel()
.activate();
App/shell.html - contains the router usage and common header/footer/loading shield
<div style="height: 100%" data-bind="css: { loading: isLoading }">
<!-- ko compose: 'loading.html'--><!-- /ko -->
<div class="header">...</div>
<!-- ko router: { transition:'entrance' } --><!-- /ko -->
</div>
App/*.js - Files shared among all the SPAs
App/MainApp/index.js - Contains the sub router for that SPA
define(["require", "exports", "plugins/router"], function (require, exports, router) {
"use strict";
var childRouter = router.createChildRouter()
.makeRelative({
moduleId: 'MainApp',
fromParent: false //<!----- FALSE for MainApp, TRUE for other SPA
})
.map([
{ route: '', moduleId: "viewmodels/test", nav: true },
])
.mapUnknownRoutes("viewmodels/err", 'err')
.buildNavigationModel();
return (function () {
function class_1() {
this.router = childRouter;
}
return class_1;
}());
});
App/MainApp/index.html - Uses the router, and performs any rendering of submenues or whatever. Here the bare minimum:
<div data-bind="router: { }"></div>
App/Admin/index.js
Is identical to the MainApp.js
, except for the fromParent
set to true and moduleId
set to the SPAs name.
现在在调试模式下应该可以正常工作。
gulp 设置变为:
gulpfile.js
var durandal = require('gulp-durandal');
gulp.task('build', [], function () {
return gulp.start(['build-admin', 'build-signup', 'build-mainapp', 'build-base']);
});
function buildModule(name) {
var path = name + '/';
return durandal({
baseDir: 'App',
output: name + '.js',
minify: true,
almond: false,
verbose: false,
moduleFilter: function (moduleName) {
return moduleName.indexOf(path) > -1;
},
rjsConfigAdapter: function (config) {
config.stubModules = config.exclude;
config.exclude = ["main"];
config.stubModules.push('text');
return config;
}
})
.pipe(gulp.dest('dist'));
}
gulp.task('build-admin', [], function () {
return buildModule('Admin');
});
gulp.task('build-signup', [], function () {
return buildModule('Signup');
});
gulp.task('build-mainapp', [], function () {
return buildModule('MainApp');
});
gulp.task('build-base', [], function () {
return durandal({
baseDir: 'App',
output: 'main.js',
minify: true,
verbose: false,
moduleFilter: function (moduleName) {
return moduleName.indexOf('Admin/') === -1 && moduleName.indexOf('MainApp/') === -1 && moduleName.indexOf('Signup/') === -1;
},
rjsConfigAdapter: function (config) {
config.stubModules = config.exclude;
config.exclude = [];
return config;
}
})
.pipe(gulp.dest('dist'));
});
这将导致
dist/main.js
dist/Admin.js
dist/MainApp.js
dist/Signup.js
在你的default.html
(或者你怎么称呼它)中,你需要告诉它如何加载这些文件:
<script>window.require = {
bundles: { 'MainApp': ['MainApp/index'],'Signup': ['Signup/index'], 'Admin': ['Admin/index'] }
};</script>
<script type="text/javascript" data-main="main" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
之所以出现在 html 文件而不是 main.js
中,是因为这些包仅用于编译版本。
我有一个网站,从技术上讲,它由许多独立的 SPA 组成。
App/Admin
App/Signup
App/MainApp
我应该如何组织 App 文件夹和 gulp 构建,使其成为 3-4 个单独的文件/模块,在需要时加载。
因为我不得不花一整天的时间来让它工作,所以我会回答我自己的问题。
首先,准备一个loader
站点。这将是实际加载的主要站点,负责加载所有其他站点。
App/main.js - Contains the requirejs setup
In this we would run
app.setRoot('shell', 'entrance');
App/shell.js - 包含路由器配置
return router.map([
{ route: 'Admin/*all', moduleId: "Admin/index", nav: true },
{ route: 'Signup/*all', moduleId: "Signup/index", nav: true },
{ route: '*all', moduleId: "MainApp/index", nav: true }
])
.buildNavigationModel()
.activate();
App/shell.html - contains the router usage and common header/footer/loading shield
<div style="height: 100%" data-bind="css: { loading: isLoading }">
<!-- ko compose: 'loading.html'--><!-- /ko -->
<div class="header">...</div>
<!-- ko router: { transition:'entrance' } --><!-- /ko -->
</div>
App/*.js - Files shared among all the SPAs
App/MainApp/index.js - Contains the sub router for that SPA
define(["require", "exports", "plugins/router"], function (require, exports, router) {
"use strict";
var childRouter = router.createChildRouter()
.makeRelative({
moduleId: 'MainApp',
fromParent: false //<!----- FALSE for MainApp, TRUE for other SPA
})
.map([
{ route: '', moduleId: "viewmodels/test", nav: true },
])
.mapUnknownRoutes("viewmodels/err", 'err')
.buildNavigationModel();
return (function () {
function class_1() {
this.router = childRouter;
}
return class_1;
}());
});
App/MainApp/index.html - Uses the router, and performs any rendering of submenues or whatever. Here the bare minimum:
<div data-bind="router: { }"></div>
App/Admin/index.js
Is identical to the
MainApp.js
, except for thefromParent
set to true andmoduleId
set to the SPAs name.
现在在调试模式下应该可以正常工作。
gulp 设置变为:
gulpfile.js
var durandal = require('gulp-durandal');
gulp.task('build', [], function () {
return gulp.start(['build-admin', 'build-signup', 'build-mainapp', 'build-base']);
});
function buildModule(name) {
var path = name + '/';
return durandal({
baseDir: 'App',
output: name + '.js',
minify: true,
almond: false,
verbose: false,
moduleFilter: function (moduleName) {
return moduleName.indexOf(path) > -1;
},
rjsConfigAdapter: function (config) {
config.stubModules = config.exclude;
config.exclude = ["main"];
config.stubModules.push('text');
return config;
}
})
.pipe(gulp.dest('dist'));
}
gulp.task('build-admin', [], function () {
return buildModule('Admin');
});
gulp.task('build-signup', [], function () {
return buildModule('Signup');
});
gulp.task('build-mainapp', [], function () {
return buildModule('MainApp');
});
gulp.task('build-base', [], function () {
return durandal({
baseDir: 'App',
output: 'main.js',
minify: true,
verbose: false,
moduleFilter: function (moduleName) {
return moduleName.indexOf('Admin/') === -1 && moduleName.indexOf('MainApp/') === -1 && moduleName.indexOf('Signup/') === -1;
},
rjsConfigAdapter: function (config) {
config.stubModules = config.exclude;
config.exclude = [];
return config;
}
})
.pipe(gulp.dest('dist'));
});
这将导致
dist/main.js
dist/Admin.js
dist/MainApp.js
dist/Signup.js
在你的default.html
(或者你怎么称呼它)中,你需要告诉它如何加载这些文件:
<script>window.require = {
bundles: { 'MainApp': ['MainApp/index'],'Signup': ['Signup/index'], 'Admin': ['Admin/index'] }
};</script>
<script type="text/javascript" data-main="main" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
之所以出现在 html 文件而不是 main.js
中,是因为这些包仅用于编译版本。