JS 实现完美include载入实现代码


Posted in Javascript onAugust 05, 2010

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,这样就不会出现引用问题。

实现代码如下:

// 根据相对路径获取绝对路径 
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)

Javascript 相关文章推荐
javascript String 对象
Apr 25 Javascript
调试Javascript代码(浏览器F12及VS中debugger关键字)
Jan 25 Javascript
JavaScript 模拟类机制及私有变量的方法及思路
Jul 10 Javascript
JavaScript实现维吉尼亚(Vigenere)密码算法实例
Nov 22 Javascript
可恶的ie8提示缺少id未定义
Mar 20 Javascript
html的DOM中document对象forms集合用法实例
Jan 21 Javascript
使用ReactJS实现tab页切换、菜单栏切换、手风琴切换和进度条效果
Oct 17 Javascript
利用js+css+html实现固定table的列头不动
Dec 08 Javascript
jQuery实现页面顶部下拉广告
Dec 30 Javascript
vue项目中使用Hbuilder打包app 设置沉浸式状态栏的方法
Oct 22 Javascript
JavaScript&quot;模拟事件&quot;的注意要点详解
Feb 13 Javascript
微信小程序实现下滑到底部自动翻页功能
Mar 07 Javascript
使用ExtJS技术实现的拖动树结点
Aug 05 #Javascript
JavaScript 获取当前时间戳的代码
Aug 05 #Javascript
firefox事件处理之自动查找event的函数(用于onclick=foo())
Aug 05 #Javascript
Js获取事件对象代码
Aug 05 #Javascript
zeroclipboard复制到剪切板的flash
Aug 04 #Javascript
jQuery Study Notes学习笔记 (二)
Aug 04 #Javascript
JQuery Study Notes 学习笔记(一)
Aug 04 #Javascript
You might like
PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
2011/08/11 PHP
部署PHP时的4个配置修改说明
2015/10/19 PHP
JqGrid web打印实现代码
2011/05/31 Javascript
js 调用父窗口的具体实现代码
2013/07/15 Javascript
js改变embed标签src值的方法
2015/04/10 Javascript
jquery ajax分页插件的简单实现
2016/01/27 Javascript
AngularJS实现与后台服务器进行交互的示例讲解
2018/08/13 Javascript
vue组件定义,全局、局部组件,配合模板及动态组件功能示例
2019/03/19 Javascript
vue缓存的keepalive页面刷新数据的方法
2019/04/23 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
浅谈vue-props的default写不写有什么区别
2020/08/09 Javascript
JavaScript canvas实现文字时钟
2021/01/10 Javascript
vue-resource 拦截器interceptors使用详解
2021/01/18 Vue.js
[43:58]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第二局
2016/02/27 DOTA
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
在Python中的Django框架中进行字符串翻译
2015/07/27 Python
在pandas中一次性删除dataframe的多个列方法
2018/04/10 Python
使用Scrapy爬取动态数据
2018/10/21 Python
python 多线程将大文件分开下载后在合并的实例
2018/11/09 Python
django框架创建应用操作示例
2019/09/26 Python
Pytorch提取模型特征向量保存至csv的例子
2020/01/03 Python
python中sympy库求常微分方程的用法
2020/04/28 Python
Python2与Python3关于字符串编码处理的差别总结
2020/09/07 Python
在python中对于bool布尔值的取反操作
2020/12/11 Python
美国畅销的跑步机品牌:ProForm
2017/02/06 全球购物
BannerBuzz加拿大:在线定制横幅印刷、广告和标志
2020/03/10 全球购物
美国领先的宠物用品和宠物食品零售商:Petco
2020/10/28 全球购物
C#面试题
2016/05/06 面试题
光信息科学与技术专业职业生涯规划
2014/03/13 职场文书
阳光体育活动总结
2014/04/30 职场文书
合作协议书模板2014
2014/09/26 职场文书
扬州个园导游词
2015/02/06 职场文书
房地产工程部经理岗位职责
2015/04/09 职场文书
门店店长岗位职责
2015/04/14 职场文书
商场圣诞节活动总结
2015/05/06 职场文书
导游词之泉州崇武古城
2019/12/20 职场文书