我正在使用MVC5/Durandal,并且想知道捆绑/缩小一个durandal应用程序的推荐方法是什么。我已经看到了使用Weyland的文档,但将部署到Azure网站,不知道如何在基于.Net的部署过程中利用这一点。在部署到Azure时,我如何开始配置我的硬件应用程序的自动捆绑/缩减?
发布于 2015-02-13 01:28:27
我花了一些时间为荷兰最大的银行之一优化AngularJS应用程序。虽然它不是Durandal,但它仍然可能给你一些想法。
那么我们使用了什么来进行捆绑和缩小呢?来自ASP.NET MVC (来自system.web.optimization命名空间)的开箱即用的捆绑和精简
为了利用这一点,你需要做几件事:
整理您的文件
以一种易于捆绑的方式组织代码文件。我们在web项目的/app文件夹下有一个很大的树形结构。类似于:
- App
|- Modules
| |-Common
| | |- Directives
| | |- Templates
| | |- Filters
| --User
| ...
| app.js因此,应用程序框架在app.js中,所有其他JS文件都是应用程序所需的。要点是:所有的SPA代码都与供应商的javscript文件和其他文件分开
在捆绑包配置中设置预算
现在轻而易举,只需从您的Global.asax.cs执行常规的旧捆绑:确保Application_Start()中有一行:BundleConfig.RegisterBundles(BundleTable.Bundles);
这会调用你的BundleConfig类,它只需要一个包就可以打包整个/app文件夹:
bundles.Add(new ScriptBundle("~/bundles/app")
.Include("~/app/*.js")
.IncludeDirectory("~/app", "*.js", true));我们需要先加载app.js --因此我们明确地把它放在了最前面。不要担心,它不会被请求两次。
对于捆绑-只有文件的顺序才是重要的。但是,通过显式地包含该文件,我们可以控制它,它就像一个护身符一样工作。
Minification
现在,为了简化,我们必须做一些代码更改。AngularJS可以与不同类型的语法一起使用--其中一些语法可以简化,另一些则会产生问题。
示例:
angular.module('myapp').controller(function($http,$scope) { ... });不能被缩小。缩微器将$http的名称改为更短的名称,之后注入器将不能再进行依赖注入,因为它只知道名为$http和$scope的东西,而不知道缩小的变量名。
因此,对于Angular,您需要使用不同的语法:
angular.module('myapp').controller(['$http', '$scope', function($http,$scope) { ... }]);这样,注入器将知道函数的第一个参数是'$http‘,因为这是数组中的第一个字符串变量。好吧,但那是Angular你要找的是Durandal。
我听说Durandal使用AMD,对吗?因此,在模块中,缩小应该不是问题,因为它应该足够智能。然而,如果你使用的是外部的东西,你需要确保所有东西都能正常工作。我读过here,你会想要为你的AMD使用以下语法:
define("someModule", ["jquery", "ko"], function($,ko) { ... });这使我们减少了80%的请求,而Javascript有效负载的请求数量大致相同。
添加了AngularJS bonus
您可能对此不感兴趣,但其他读者可能会感兴趣。我们没有得到99%的请求减少的原因是因为AngularJS使用了一种叫做“指令”的东西。这些类似于HTML模板。这些HTML模板在每次使用时仍然需要下载。
它们也包含在我们的/app文件夹中-因此我们必须在routeconfig中添加一个IgnoreRoute:
routes.IgnoreRoute("app/");我用谷歌搜索了一下,但找不到任何与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的数量非常少,因此似乎更快地处理一个较大的请求,而不是多个较小的请求。
重点是:如果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;覆盖它
到Azure的部署
然后你提到部署到Azure。我不知道这与部署到本地服务器有什么不同。我们使用web部署。捆绑和缩小不会在构建时发生,因此构建过程中不会发生任何更改。此外,优化框架将与站点一起部署-因此部署起来也不是什么难事。
也许有一件事:你可以考虑为你正在使用的库添加CDN:
bundles.Add(new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js")如果客户端的浏览器已经缓存了jQuery的CDN位置,您将保存另一个请求。
测量性能很简单:只需打开Chrome上的网络选项卡,然后重新加载页面(确保它没有缓存)。检查请求总数和下载的数据总量。就像我说的:我们看到了巨大的进步。
好吧,希望它能帮到你或者给你指明一个正确的方向。
发布于 2015-04-14 11:38:02
下面的答案相当复杂。我在这里用一个简单的(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步:向项目添加生成后事件
if '$(Configuration)'=='Release' (
cd $(ProjectDir)
gulp durandal
)第7步:向项目添加预构建事件
我之所以需要这样做,是因为在现有版本之上生成新的main-built.js时,偶尔会出现吞咽挂起的情况。因此,我只是在构建开始之前删除旧版本:
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")
}其中‘main-built’是在BundleConfig中定义的:
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/app/main-built.js"));当我有新东西要发货时,如何建立缓存?
如果您使用上述方法,bundling将为您解决此问题。ASP.NET将检测到对main-built.js文件的更改,并将唯一标识符附加到包中以清除缓存。
如果我的客户端下载了我的SPA,然后我发送了更新,该怎么办?(过时的)客户端代码不会一直保留到刷新吗?
是啊。除非您利用构建版本控制来告诉客户端它何时过期,然后再告诉用户。
发布于 2015-02-20 21:15:20
https://stackoverflow.com/questions/28390006
复制相似问题