捆绑和缩小Durandal应用程序

时间:2015-02-08 02:42:05

标签: javascript single-page-application durandal durandal-2.0

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

3 个答案:

答案 0 :(得分: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文件分开,其余当然是

在捆绑配置中设置萌芽

现在这很简单,只需从你的Global.asax.cs进行常规捆绑: 确保Application_Start()中有一行: BundleConfig.RegisterBundles(BundleTable.Bundles);

调用您的BundleConfig类,只需要1个包即可打包整个/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) { ... }]);

这样,注入器就会知道函数的第一个参数是&#39; $ http&#39;因为那是数组中的第一个字符串变量。好的,但是那个Angular,你正在寻找Durandal。

我听说Durandal使用AMD吗?因此,在一个模块中,缩小不应该是一个问题,因为它应该足够聪明。但是,如果您正在使用外部事物,则需要确保一切仍然有效。我已阅读here您希望为您的AMD使用以下语法:

define("someModule", ["jquery", "ko"], function($,ko) { ... });

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

添加了AngularJS奖金

这可能不是您感兴趣的,但可能对其他读者感兴趣。我们没有将请求减少99%的原因是因为AngularJS使用了一些名为&#39;指令&#39;。这些就像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;覆盖它

部署到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上的网络标签页并重新加载页面(确保它没有缓存)。检查请求总数和下载的数据总量。就像我说的那样:我们看到了巨大的进步。

嗯,希望它有助于或指出你正确的方向。

答案 1 :(得分: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步:在项目中添加构建后事件

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,然后我发送了更新,该怎么办? (过时的)客户端代码是否会在刷新之前保持不变?

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

答案 2 :(得分:0)

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

https://javascriptkicks.com/articles/4230

希望能帮到你