开发者社区> 技术小甜> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

JS 实现完美include

简介:
+关注继续查看

  js为什么需要include?让我们想想这样1个场景,a.js 需要用到1个公用的common.js,当然你可以在用到a.js的页面使用<script src="common.js">,但假设有5个页面用到了a.js,你是不是要写5遍<script。而且要是以后a.js 又需要引用common2.js,你是不是又的修改5个页面了?

 

已有js include的一些问题

    在写这个之前在网上搜索了些资料,发现以前写的include都存在2个问题,这也是include需要解决的比较重要的2个问题。

   1、相对路径的问题:  在a.js中使用include("../js/common.js");  include 函数中肯定是使用相对路径,是相对a.js的路径。而a.js在html中使用<script>嵌入有可能是相对路径,有可能是绝对路径。  include函数如何才能真正确定common.js的绝对路径,或者是相对html的相对路径。网上一些为了解决这个问题,还需要加一些js变量,不方便。  

   2、引用的问题。  网上include函数的实现几乎都是使用下面2种方式插入common.js     

      document.write("<script src='" + .. + "></script>")  

    或者    

      var s = document.createElement("script");    

      s.src = ...;    

      head.insertAfter(s,...);    

    document.write 输出的脚本会在a.js后面加载,而createElement("script")创建的脚本是非阻塞加载。  所以如果在common.js加载完毕之前,a.js中调用了common.js的函数就会报错。

 

实现

     解决上面2个问题,就可以实现js include。  

   第1个问题,我的方法是先获取到a.js在html中的绝对路径(如果是相对路径,就转为绝对路径),然后再把common.js的路径转为绝对路径。  

   第2个问题,采用同步的ajax来请求common.js,这样就不会出现引用问题。

 

  实现代码如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 根据相对路径获取绝对路径
function getPath(relativePath,absolutePath){
    var reg = new RegExp("\\.\\./","g");
    var uplayCount = 0;     // 相对路径中返回上层的次数。
    var m = relativePath.match(reg);
    if(m) uplayCount = m.length;
     
    var lastIndex = absolutePath.length-1;
    for(var i=0;i<=uplayCount;i++){
        lastIndex = absolutePath.lastIndexOf("/",lastIndex);
    }
    return absolutePath.substr(0,lastIndex+1) + relativePath.replace(reg,"");
}      
 
function include(jssrc){
    // 先获取当前a.js的src。a.js中调用include,直接获取最后1个script标签就是a.js的引用。
    var scripts = document.getElementsByTagName("script");
    var lastScript = scripts[scripts.length-1];
    var src = lastScript.src;
    if(src.indexOf("http://")!=0 && src.indexOf("/") !=0){     
        // a.js使用相对路径,先替换成绝对路径
        var url = location.href;
        var index = url.indexOf("?");
        if(index != -1){
            url = url.substring(0, index-1);
        }
         
        src = getPath(src,url);
    }
    var jssrcs = jssrc.split("|");  // 可以include多个js,用|隔开
    for(var i=0;i<jssrcs.length;i++){
        // 使用juqery的同步ajax加载js.
        // 使用document.write 动态添加的js会在当前js的后面,可能会有js引用问题
        // 动态创建script脚本,是非阻塞下载,也会出现引用问题
        $.ajax({type:'GET',url:getPath(jssrc,src),async:false,dataType:'script'});
    }
}

 

  在a.js中直接使用 include("../js/common.js");

 

多请求的问题

  使用上面的include看上去挺爽的,不过却带来另外1个严重的问题,就是多发送了1个ajax的请求。

  我们常常为了WEB性能,而合并js,减少请求。但使用include后却偏偏多了请求。如果这个问题不解决,相信很多人都不会在正式产品中使用include的了,除非是局域网产品。

 

  如何解决这个多请求的问题,我也思考很久,最后觉的单单使用客户端js是没办法解决了。所以就想到了使用服务端代码来解决

  还记的我之前有文章介绍 "js、css的合并、压缩、缓存管理"的时候,就通过服务器端代码在程序启动时候去合并js。

 

  所以我把include多请求的解决方案也加到里面去。就是在程序启动的时候去查找所有的js,发现有使用include的就把include中common.js的源代码替换该include函数。这样a.js中在运行的时候就没有include函数,而是真真包含了common.js的内容的js文件

 

后语

  丫的。说到最后,怎么又把所有的include都替换掉了,哪之前说的那么多不白说了。

 

  个人觉得,每个产品都应该要区分开发环境和产品环境(一般通过配置文件进行区分),在开发环境应该以开发效率为首要,而产品环境则以性能为首。所以这里的inlcude就应该要区分对待,在开发环境中使用js include来提高开发和维护效率,而在产品环境中则自动把所有include替换成真真的js文件的内容。

 












本文转自BearRui(AK-47)博客园博客,原文链接:  http://www.cnblogs.com/BearsTaR/archive/2010/08/05/js_include.html  ,如需转载请自行联系原作者



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
剑指Offer——正则表达式匹配(JS实现)
剑指Offer——正则表达式匹配(JS实现)
68 0
剑指Offer——I. 斐波那契数列(JS实现)
剑指Offer——I. 斐波那契数列(JS实现)
74 0
剑指Offer——数值的整数次方(JS实现)
剑指Offer——数值的整数次方(JS实现)
83 0
剑指Offer——剪绳子II(JS实现)
剑指Offer——剪绳子II(JS实现)
63 0
剑指Offer——把字符串转换成整数(JS实现)
剑指Offer——把字符串转换成整数(JS实现)
101 0
剑指Offer——表示数值的字符串(JS实现)
剑指Offer——表示数值的字符串(JS实现)
50 0
剑指Offer——打印从1到最大的n位数(JS实现)
剑指Offer——打印从1到最大的n位数(JS实现)
57 0
HOT100——两数相加(JS实现)
HOT100——两数相加(JS实现)
58 0
HOT100——无重复字符的最长子串(JS实现)
HOT100——无重复字符的最长子串(JS实现)
62 0
+关注
10136
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载