客户端包含与服务器端包含哪个更好?

9
我们有一个包含多个
块的HTML页面。我们想将这些div分离成多个文件,然后将它们合并成一个单独的文件 - 最好使用服务器端包含(在我们的情况下是JSP)还是客户端包含?请注意,我们正在使用JQuery - 不确定JQuery是否有巧妙的方法来执行包含操作。
5个回答

4
在性能方面,如果在服务器上进行此类处理,则远远优于在客户端上进行排序所需的额外HTTP请求的I/O和处理成本将是相当大的。 在服务器上包含其他内容将导致用户毫秒级的延迟;而在客户端上执行此操作将需要更多的时间。 编辑根据Luke Schafer's comment,这假定正在组合的内容可以即时生成(例如通过从服务器包括平面文件)。 如果需要时间(例如较长的数据库调用),则可能适合加载页面的主要部分并使用jQuery添加额外的内容。 最好的解决方案始终取决于您的特定情况。

3

实际上,客户端包含有一个非常有用的属性:客户端浏览器具有缓存!如果您的某些内容不经常更改,并且每个客户端经常加载页面的某个片段,则客户端包含是一个好主意,因为可以利用客户端浏览器缓存。

想法是您的完整页面包含一堆占位符div,其中将放置客户端包含。通过AJAX调用加载HTML片段。如果片段的HTTP响应标头指定了很久以后的Expires和/或Cache-Control,当您的客户端访问下一个页面时,AJAX请求将从缓存中服务,而不是实际地到服务器。


您能使浏览器缓存HTML文件/片段吗?如果可以的话,包含主要导航(如果对整个站点相同)似乎是不错的选择,对吗? - Julix
如果您的片段是通过单独的HTTP请求获取的,那么是的。浏览器可以缓存整个HTTP响应(前提是响应的Expires和Cache-Control头已经正确指定),但它们不会缓存响应的部分。这就是为什么我提到了AJAX调用。对AJAX调用的响应包含了您想要在浏览器上缓存的HTML片段。 - LordOfThePigs

1

我不确定自己在客户端与服务器端辩论中属于哪一方。现在流行的做法似乎是在客户端处理事情。也许两者的结合最好。为了完全在客户端尝试它,我决定启动一个对象,异步执行客户端包含操作,但缓存文本以供以后使用。有一个加载函数,它将回调函数作为参数调用成功加载时。还有一个将对象的内部HTML设置为加载的文本的函数。该对象需要先前包含jquery。

/**
 * An object to manage client side includes. 
 * 
 * Loads of text are asynchronous but the result will be cached for later use.
 * 
 * @param urlText - the url of the inlcude text
 * @returns an Include object
 */
function Include(urlText)
{
    var self;
    var loaded;
    var txt;
    var url;

    /**
     * Sets the url for the include.
     * 
     * Will unload a previously set include.
     * 
     * @param url
     */
    this.setUrl = setUrl;
    function setUrl(url)
    {
        if (self.url != url)
        {
            unload();
        }
        self.url = url;
    }

    /**
     * 
     * @returns the url
     */
    this.getUrl = getUrl;
    function getUrl()
    {
        return self.url;
    }

    /**
     * Unloads the current url.
     */
    this.unload = unload;
    function unload()
    {
        self.txt = null;
        self.loaded = false;
    }

    /**
     * Loads the current url asynchronously
     * 
     * @param fnPostLoad function to call on successful completion
     */
    this.load = load; 
    function load(fnPostLoad)
    {

        if (self.loaded)
        {
            if (fnPostLoad != null)
            {
                fnPostLoad.call();
            }
            return;
        }

        $.ajax({
            type : "GET",
            dataType : "text",
            url : self.url,
            success : function(data) {
                self.txt = data;
                self.loaded = true;
                if (fnPostLoad != null)
                {
                    fnPostLoad.call();
                }
            },
            error : function(){
                alert("An error occurred accessing client side include located at: " + self.url);
            }
        });         
    };

    /**
     * Sets the inner html of a given object to be the text of this include.
     * 
     * Will load the url if not loaded.
     * 
     * @param obj
     */
    this.setInnerHtmlOf = setInnerHtmlOf;
    function setInnerHtmlOf(obj)
    {
        load(function(){obj.html(self.txt);})
    }

    // initialize members
    self = this; // must be done first
    loaded = false;
    txt = null;
    setUrl(urlText);    
}

要使用这个对象,您可以这样做:

var foo = new Include("foo.inc");
var bar = new Include("bar.inc");
foo.setInnerHtmlOf($('#treeMargin'));
bar.setInnerHtmlOf($('#mainMargin'));

我还没有做太多的测试,但它似乎运行得相当不错。


1

我必须同意其他人的看法,服务器端是最好的选择,但有一个例外。

如果你的部分包含需要较长时间加载的内容,比如每个部分都需要从不同的Web服务调用中获取内容,那么使用JQuery通过get方法异步加载它们可能会更有益,因为在加载部分时可以同时加载页面的其余部分。

除此之外,确实...应该在服务器端处理。


+1 我完全同意这一点,并将其作为我的答案的一个警告添加了进去。谢谢。 - lonesomeday

-1

我会说是服务器端。如果jQuery没有加载或用户关闭了JavaScript,怎么办?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接