我正在使用MVC5 / Durandal,并想知道捆绑/缩小durandal应用程序的推荐方法是什么。 我见过有关使用Weyland的文档,但是将部署到Azure网站,并且没有看到如何在基于.net的部署过程中利用它。 在部署到Azure时,如何配置我的durandal应用程序的自动捆绑/缩小?
我花了一些时间试图为荷兰最大的银行之一优化AngularJS应用程序。 虽然它不是Durandal,但这可能仍然会给你一些想法。
那么我们用什么来捆绑和缩小呢? ASP.NET MVC(来自system.web.optimization
命名空间)的开箱即用的捆绑和缩减
你需要得到一些东西来利用这个:
整理文件
以易于捆绑的方式组织您的代码文件。 我们在Web项目的/app
文件夹下有一个大型树结构。 就像是:
- App
|- Modules
| |-Common
| | |- Directives
| | |- Templates
| | |- Filters
| --User
| ...
| app.js
所以应用程序框架在app.js
,应用程序需要所有其他JS文件。 要点:所有SPA代码都与供应商javscript文件分开,其余当然
在bundle配置中设置budling
现在这是轻而易举的,只需从Global.asax.cs
进行常规旧捆绑:确保Application_Start()
有一行: BundleConfig.RegisterBundles(BundleTable.Bundles);
调用BundleConfig
类,只需要1个bundle来打包整个/app
文件夹:
bundles.Add(new ScriptBundle("~/bundles/app")
.Include("~/app/*.js")
.IncludeDirectory("~/app", "*.js", true));
我们首先需要加载app.js
- 因此我们将它明确地放在顶部。 别担心,它不会被要求两次。
对于捆绑 - 只有文件序列才是重要的。 但是,通过明确地包含该文件,我们可以控制它,它就像一个魅力。
缩小
现在为了缩小,我们不得不做一些代码更改。 AngularJS可以使用不同类型的语法 - 其中一些可以缩小,另一些则会产生问题。
例:
angular.module('myapp').controller(function($http,$scope) { ... });
不可能被缩小。 minifyer将更改$http
的名称,以便更短的时间,之后注入器不能再执行依赖注入,因为它只知道名为$http
和$scope
而不是缩小的变量名称。
因此对于Angular,您需要使用不同的语法:
angular.module('myapp').controller(['$http', '$scope', function($http,$scope) { ... }]);
有了这个,注入器将知道函数的第一个参数是'$ http',因为这是数组中的第一个字符串变量。 好的,但那是Angular而你正在寻找Durandal。
我听说Durandal使用AMD吧? 所以在一个模块中,缩小不应该是一个问题,因为它应该足够聪明。 但是,如果您正在使用外部事物,则需要确保一切仍然有效。 我在这里读到你要为你的AMD使用以下语法:
define("someModule", ["jquery", "ko"], function($,ko) { ... });
这使我们减少了80%的请求,并且Javascript负载的数量大致相同。
添加了AngularJS奖金
这可能不是您感兴趣的,但也许对其他读者而言。 我们没有将请求减少99%的原因是因为AngularJS使用了一种叫做“指令”的东西。 这些就像HTML模板。 每次使用时都需要下载这些HTML模板。
它们也包含在我们的/app
文件夹中 - 因此我们必须在routeconfig中添加一个IgnoreRoute:
routes.IgnoreRoute("app/");
我用Google搜索,但找不到Durandal的任何相似内容。 所以Angular会去获取所有的小HTML文件,但首先会检查它的$templatecache
。 如果HTML内容不在缓存中,则会将其下载并下载并将其放入缓存中,因此只需下载一次。
我,我,写了一个T4生成器,输出一个JS文件,其中/ app文件夹中的所有HTML文件都被添加到$templatecache
。 所以输出看起来像:
angular.module('myapp').run(function($templateCache) {
/// For all *.html files in the /app folder and its children
$templateCache.put('...filename...', '...content of html file ...');
});
因为这个.JS文件位于/ app文件夹中,所以它会立即与应用程序捆绑在一起,不再需要配置。 这使我们对整个应用程序的请求降低到只有1.由于HTML的数量非常少,所以执行1个更大的请求,然后是多个更小的请求似乎更快。
要点是:如果Durandal有类似的东西,它会寻找一些模板,找到缓存机制(因为它会拥有它)并尝试利用它。
控制捆绑和缩小
我引用这个网站: http : //www.asp.net/mvc/overview/performance/bundling-and-minification
通过在Web.config文件中的编译元素中设置debug属性的值来启用或禁用捆绑和缩小。 在以下XML中,debug设置为true,因此禁用了捆绑和缩小。
<system.web>
<compilation debug="true" />
</system.web>
所以对于你的发布版本 - 不应该设置这个标志,因此捆绑+缩小应该发生。 但是,当然,您需要在本地进行测试 - 您可以从web.config中删除它,也可以使用BundleTable.EnableOptimizations = true;
覆盖它BundleTable.EnableOptimizations = true;
部署到Azure
然后你提到Azure的部署。 我不知道这与部署到本地服务器有什么不同。 我们使用了web-deploy。 捆绑和缩小不会发生构建时间,因此构建过程中没有任何更改。 此外,优化框架正在与站点一起部署 - 因此部署也不困难。
也许有一件事:您可以考虑为您正在使用的库添加CDN:
bundles.Add(new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js")
如果jQuery的CDN位置已经被客户端的浏览器缓存,您将保存另一个请求。
测量性能很简单:只需在Chrome上打开网络选项卡并重新加载页面(确保它不是缓存)。 检查请求总数和下载的数据总量。 就像我说的:我们看到了巨大的进步。
好吧,希望它有助于或指向正确的方向。
以下答案非常复杂。 我刚才通过一个简单的(r)方法来解决这个问题:
https://lifelibertycode.wordpress.com/2015/04/14/how-to-bundle-up-your-mvc-durandal-app/
以下步骤:
第1步:安装节点
第2步:安装Gulp
$ npm install --global gulp
$ npm install --save-dev gulp
第3步:创建gulpfile.js
这应该是项目的根目录,最初应该包含:
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
});
第4步:安装gulp-durandal
npm install gulp-durandal --save-dev
第5步:更新您的gulpfile.js
var durandal = require('gulp-durandal');
gulp.task('durandal', function(){
durandal({
baseDir: 'app', //same as default, so not really required.
main: 'main.js', //same as default, so not really required.
output: 'main.js', //same as default, so not really required.
almond: true,
minify: true
})
.pipe(gulp.dest('dir/to/save/the/output'));
});
第6步:向项目添加post-build事件
if '$(Configuration)'=='Release' (
cd $(ProjectDir)
gulp durandal
)
第7步:向项目添加预构建事件
我需要这个,因为在现有版本的基础上生成新的main-built.js时偶尔会挂起gulp。 所以我只是在构建开始之前删除旧版本:
if '$(Configuration)'=='Release' (
cd $(ProjectDir)/app
del main-built.js
del main-built.js.map
)
现在,当您构建项目时,每次可以向客户提供服务时,您将生成一个新的main-built.js文件。 甜。
此时,您可能有一些顾虑。
我在调试时如何保持文件解包?
@if (HttpContext.Current.IsDebuggingEnabled) {
<script type="text/javascript" src="~/Scripts/require.js" data-main="/App/main"></script>
} else {
@Scripts.Render("~/Scripts/main-built")
}
在BundleConfig中定义'main-built'的位置:
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/app/main-built.js"));
当我有新东西要发货时,我如何破坏缓存?
如果您使用上述方法,捆绑将为您处理此问题。 ASP.NET将检测对main-built.js文件的更改,并在捆绑包中附加唯一标识符以破坏缓存。
如果我的客户已下载我的SPA,然后我发送更新,该怎么办? (过时的)客户端代码是否会在刷新之前一直存在?
对。 除非您利用构建版本控制来告诉客户端何时过时,然后告诉用户。