捆绑和缩小Durandal应用程序

问题描述 投票:4回答:3

我正在使用MVC5 / Durandal,并想知道捆绑/缩小durandal应用程序的推荐方法是什么。 我见过有关使用Weyland的文档,但是将部署到Azure网站,并且没有看到如何在基于.net的部署过程中利用它。 在部署到Azure时,如何配置我的durandal应用程序的自动捆绑/缩小?

javascript single-page-application durandal durandal-2.0
3个回答
4
投票

我花了一些时间试图为荷兰最大的银行之一优化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上打开网络选项卡并重新加载页面(确保它不是缓存)。 检查请求总数和下载的数据总量。 就像我说的:我们看到了巨大的进步。

好吧,希望它有助于或指向正确的方向。


3
投票

以下答案非常复杂。 我刚才通过一个简单的(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,然后我发送更新,该怎么办? (过时的)客户端代码是否会在刷新之前一直存在?

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


0
投票

我碰巧写了一篇关于此的博文:

https://javascriptkicks.com/articles/4230

希望这会帮助你

© www.soinside.com 2019 - 2024. All rights reserved.