如何在开发和生产中构建JavaScript应用程序

时间:2011-12-22 14:50:22

标签: javascript architecture

我正在构建我的第一个(非意大利面)大型JavaScript应用程序。虽然为JavaScript引入RequireJS和其他依赖关系管理框架可以更容易地分割文件,但我不清楚如何将大型代码库推向生产。我想要的是使用诸如Ready.jsUglifyJS之类的东西来聚合和缩小/ uglify我的JavaScripts以进行生产的方法。或者其他一些方法,如果有意义的话。

生产中使用大型JavaScript应用的开发人员如何处理开发和生产中的结构?

例如,我可以在开发中使用RequireJS,然后使用Ready / Uglify进行聚合/缩小。但是,我的代码在整个过程中都会毫无意义require()'s。我确信有更好的方法。

我也对在这些文件中包含jQuery感到困惑。我应该在他们自己的$(document).ready(function(){...})内包装每个单独的jQuery文件(例如使用jQuery的Backbone视图)吗?这似乎非常不干。

3 个答案:

答案 0 :(得分:2)

您可以使用RequireJS optimizer。即使在压缩的应用程序中,这些要求也毫无意义,因为您始终必须获得对模块的引用。优化器文档还说,它不会包含已加载变量的模块,如

var mods = someCondition ? ['a', 'b'], ['c', 'd'];
require(mods);

我认为RequireJS应该等到DOM准备就绪所有模块都已加载,所以你不需要包装每个文件。

那就是说,我最喜欢的包经理仍然是StealJS。它可以在生产构建中启动不必要的调用,并且模块总是封装在一个闭包中,该闭包将传递jQuery对象并等待直到DOM准备好并且所有脚本都已加载。不幸的是,它还没有与CommonJS模块规范兼容。

答案 1 :(得分:1)

我发现YUI Builder对我很有用。如果你没有使用YUI 3,我不确定它是多么有用,但你很有可能根据你的需要调整它。

另一方面,你看过RequireJS Optimizer吗?

关于document.ready处理;我认为最好不要让模块中的代码在初始化或调用之前做任何事情。所以我在页面底部的$(document).ready()标签中会有一个<script>,它会“粘合”该页面上所需的模块。

答案 2 :(得分:0)

反意大利面方式

为了有效地开发和轻松维护JavaScript应用程序,而不是大量的临时脚本或低于非透明的自动化,您可以使用native Qooxdoo application。如果不写太多,就不可能覆盖Qooxdoo,但是对于本机应用程序(不要将术语与C或Java混淆,Qooxdoo是纯JavaScript),它被描述为:

  

对于使用基于HTML / CSS的自定义GUI而不是qooxdoo的小部件图层的应用程序。

因此,此类应用程序不使用任何Qooxdoo UI层,而只使用代码结构工具和构建工具。 Qooxdoo中的代码按类组织,每个文件一个,如Java。我可能看起来像这样:

/**
 * @use(website.library.MosaicFlow)
 */
qx.Class.define('website.controller.Gallery', {

  extend : website.controller.Abstract,

  members : {

    _baseUrl : 'https://picasaweb.google.com/data/feed/api',


    _render : function(photos)
    {
      q('.preloader').remove();

      q.template.get('gallery-template', {'photos': photos}).appendTo('#gallery-container');
      var gallery = window.jQuery('#gallery-container .gallery').mosaicflow({
        'minItemWidth'    : 256,
        'itemSelector'    : '.photo',
        'autoCalculation' : false
      });
      gallery.trigger('resize');
    },

    _convert : function(item, index)
    {
      try
      {
        return {
          'url'     : item.content.src,
          'summary' : item.summary.$t,
          'thumb'   : item.media$group.media$thumbnail[0]
        };
      }
      catch(ex)
      {
        this.debug('failed to convert', index, item);
        return null;
      }
    },

    _onLoadSuccess : function(event)
    {
      var request  = event.getTarget();
      var response = request.getResponse();
      if(!qx.lang.Type.isObject(response) || !('feed' in response))
      {
        request.debug('Malformed response received');
      }
      else
      {
        this._render(response.feed.entry.map(this._convert, this).filter(function(item)
        {
          return !!item;
        }));
      }
    },

    _onLoadFail : function()
    {
      this.debug('Picasa search failed');
    },

    main : function()
    {
      var query   = /^\/gallery\/(\w+)$/.exec(window.location.pathname);
      var request = new qx.io.request.Jsonp(qx.lang.String.format('%1/all', [this._baseUrl]));
      request.setRequestData({
        'q'           : query[1],
        'thumbsize'   : 300,
        'max-results' : 20,
        'alt'         : 'json'
      });
      request.setTimeout(16000);
      request.setCache(false);
      request.addListener('fail',    this._onLoadFail,    this);
      request.addListener('success', this._onLoadSuccess, this);
      request.send();
    }

  }

});

Qooxdoo对象模型充分利用了这两个方面。具有Java等成熟平台的特性,同时具有现代和动态,提供类,继承,接口,混合,事件,属性,数据绑定等。因为每个类都有一个已定义的名称并位于命名空间树中,所以Qooxdoo生成器可以利用它。它解析您的类并构建其语法树。然后它解决了依赖关系。即当你引用另一个类时,比如website.controller.Abstract。这导致依赖图,用于按正确顺序加载脚本。请注意,对于开发人员来说,这一切都是自动且透明的,文件按原样加载。在CommonJS的情况下没有任何让步,没有像AMD这样的包装代码的丑陋样板。

正如您在上面的示例中所看到的,可以处理外部非qooxdoo库。您只需要为库编写一个虚拟包装器,以便在构建过程中包含它。

开发和生产环境

您开发构建应用程序(仅在代码中引入新依赖项时才需要构建),并使用所谓的源目标。您的应用程序文件按依赖顺序逐个加载。框架文件可以逐个加载,或者哪个是更好的选项,它们构建在几个大块中。在生产环境中,您的应用程序代码使用构建目标构建。您可以选择生成单个输出文件,或者具有部分生成,其中代码在大文件中分块(您可以控制它们的大小)。部分构建可能看起来像这样(优化/ gzip):

├── [127/64kB]  website.f6ffa57fc541.js
├── [100/33kB]  website.f86294b58d1a.js
└── [361/110kB] website.js

请注意,部件是在需要它们的页面上按需加载的。

http://example.com/
└── website.js
http://example.com/article
└── website.js
http://example.com/form
└── website.js
    └── website.f86294b58d1a.js
http://example.com/gallery
└── website.js
    └── website.f6ffa57fc541.js
http://example.com/geo
└── website.js

由于Qooxdoo尚未针对成熟的网站构建,但仅提供本机应用程序类型的平台,您需要编写应用程序的条目和一些基础知识,如引导,URL路由等。我试过使用qooxdoo-website-skeleton解决此问题,以上哪些示例属于。您可以自由使用它,也可以自己编写。

最后请注意,它可能不像普通的JavaScript库那样容易,但复杂性与最终的好处成正比。

相关问题