首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >捆绑和缩小Durandal应用程序

捆绑和缩小Durandal应用程序
EN

Stack Overflow用户
提问于 2015-02-08 10:42:05
回答 3查看 1.8K关注 0票数 4

我正在使用MVC5/Durandal,并且想知道捆绑/缩小一个durandal应用程序的推荐方法是什么。我已经看到了使用Weyland的文档,但将部署到Azure网站,不知道如何在基于.Net的部署过程中利用这一点。在部署到Azure时,我如何开始配置我的硬件应用程序的自动捆绑/缩减?

EN

回答 3

Stack Overflow用户

发布于 2015-02-13 01:28:27

我花了一些时间为荷兰最大的银行之一优化AngularJS应用程序。虽然它不是Durandal,但它仍然可能给你一些想法。

那么我们使用了什么来进行捆绑和缩小呢?来自ASP.NET MVC (来自system.web.optimization命名空间)的开箱即用的捆绑和精简

为了利用这一点,你需要做几件事:

整理您的文件

以一种易于捆绑的方式组织代码文件。我们在web项目的/app文件夹下有一个很大的树形结构。类似于:

代码语言:javascript
复制
- 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文件夹:

代码语言:javascript
复制
        bundles.Add(new ScriptBundle("~/bundles/app")
            .Include("~/app/*.js")
            .IncludeDirectory("~/app", "*.js", true));

我们需要先加载app.js --因此我们明确地把它放在了最前面。不要担心,它不会被请求两次。

对于捆绑-只有文件的顺序才是重要的。但是,通过显式地包含该文件,我们可以控制它,它就像一个护身符一样工作。

Minification

现在,为了简化,我们必须做一些代码更改。AngularJS可以与不同类型的语法一起使用--其中一些语法可以简化,另一些则会产生问题。

示例:

代码语言:javascript
复制
angular.module('myapp').controller(function($http,$scope) { ... });

不能被缩小。缩微器将$http的名称改为更短的名称,之后注入器将不能再进行依赖注入,因为它只知道名为$http$scope的东西,而不知道缩小的变量名。

因此,对于Angular,您需要使用不同的语法:

代码语言:javascript
复制
angular.module('myapp').controller(['$http', '$scope', function($http,$scope) { ... }]);

这样,注入器将知道函数的第一个参数是'$http‘,因为这是数组中的第一个字符串变量。好吧,但那是Angular你要找的是Durandal。

我听说Durandal使用AMD,对吗?因此,在模块中,缩小应该不是问题,因为它应该足够智能。然而,如果你使用的是外部的东西,你需要确保所有东西都能正常工作。我读过here,你会想要为你的AMD使用以下语法:

代码语言:javascript
复制
define("someModule", ["jquery", "ko"], function($,ko) { ... });

这使我们减少了80%的请求,而Javascript有效负载的请求数量大致相同。

添加了AngularJS bonus

您可能对此不感兴趣,但其他读者可能会感兴趣。我们没有得到99%的请求减少的原因是因为AngularJS使用了一种叫做“指令”的东西。这些类似于HTML模板。这些HTML模板在每次使用时仍然需要下载。

它们也包含在我们的/app文件夹中-因此我们必须在routeconfig中添加一个IgnoreRoute:

代码语言:javascript
复制
routes.IgnoreRoute("app/");

我用谷歌搜索了一下,但找不到任何与Durandal类似的信息。因此Angular将获取所有小的HTML文件,但首先会检查它的$templatecache。如果HTML内容不在缓存中,它会出去下载并将其放入缓存中,因此只需要下载一次。

我们编写了一个T4生成器,输出一个JS文件,其中/app文件夹中的所有HTML文件都添加到$templatecache中。因此,输出将如下所示:

代码语言:javascript
复制
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,因此绑定和缩小被禁用。

代码语言:javascript
复制
<system.web>
    <compilation debug="true" />
</system.web>

因此,对于你的发布版本,这个标志不应该被设置,因此应该发生捆绑+最小化。当然,您需要在本地进行测试-您可以将其从web.config中删除,也可以使用BundleTable.EnableOptimizations = true;覆盖它

到Azure部署

然后你提到部署到Azure。我不知道这与部署到本地服务器有什么不同。我们使用web部署。捆绑和缩小不会在构建时发生,因此构建过程中不会发生任何更改。此外,优化框架将与站点一起部署-因此部署起来也不是什么难事。

也许有一件事:你可以考虑为你正在使用的库添加CDN:

代码语言:javascript
复制
bundles.Add(new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js")

如果客户端的浏览器已经缓存了jQuery的CDN位置,您将保存另一个请求。

测量性能很简单:只需打开Chrome上的网络选项卡,然后重新加载页面(确保它没有缓存)。检查请求总数和下载的数据总量。就像我说的:我们看到了巨大的进步。

好吧,希望它能帮到你或者给你指明一个正确的方向。

票数 4
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
$ npm install --global gulp
$ npm install --save-dev gulp

第3步:创建您的gulpfile.js

它应该位于项目的根目录中,并且最初应该包含以下内容:

代码语言:javascript
复制
var gulp = require('gulp');

gulp.task('default', function() {
  // place code for your default task here
});

第4步:安装gulp-durandal

代码语言:javascript
复制
npm install gulp-durandal --save-dev

第5步:更新gulpfile.js

代码语言:javascript
复制
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步:向项目添加生成后事件

代码语言:javascript
复制
if '$(Configuration)'=='Release' (
    cd $(ProjectDir)
    gulp durandal
)

第7步:向项目添加预构建事件

我之所以需要这样做,是因为在现有版本之上生成新的main-built.js时,偶尔会出现吞咽挂起的情况。因此,我只是在构建开始之前删除旧版本:

代码语言:javascript
复制
if '$(Configuration)'=='Release' (
    cd $(ProjectDir)/app
    del main-built.js
    del main-built.js.map
)

现在,当您构建项目时,每次都将生成一个新的main-built.js文件,该文件可以向下提供给您的客户端。甜。

在这一点上,您可能有一些担忧。

如何在调试时将文件解包?

代码语言:javascript
复制
@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中定义的:

代码语言:javascript
复制
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
    "~/app/main-built.js"));

当我有新东西要发货时,如何建立缓存?

如果您使用上述方法,bundling将为您解决此问题。ASP.NET将检测到对main-built.js文件的更改,并将唯一标识符附加到包中以清除缓存。

如果我的客户端下载了我的SPA,然后我发送了更新,该怎么办?(过时的)客户端代码不会一直保留到刷新吗?

是啊。除非您利用构建版本控制来告诉客户端它何时过期,然后再告诉用户。

票数 3
EN

Stack Overflow用户

发布于 2015-02-20 21:15:20

我碰巧写了一篇关于这方面的博客文章:

https://javascriptkicks.com/articles/4230

希望这能帮到你

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28390006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档