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 相关文章推荐
json简单介绍
Jun 10 Javascript
JS location几个方法小姐
Jul 09 Javascript
基于jQuery的获得各种控件Value的方法
Nov 19 Javascript
JS操作数据库的实例代码
Oct 17 Javascript
解析jquery easyui tree异步加载子节点问题
Mar 08 Javascript
Node.js操作redis实现添加查询功能
May 25 Javascript
Javascript调试之console对象——你不知道的一些小技巧
Jul 10 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
Sep 13 Javascript
vue组件从开发到发布的实现步骤
Nov 11 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
Jan 06 Javascript
JS实现的检验身份证格式并输出出生日期,年龄,性别,出生地示例
May 17 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 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
咖啡知识 咖啡养豆要养多久 排气又是什么
2021/03/06 新手入门
PHP使用redis实现统计缓存mysql压力的方法
2015/11/14 PHP
基于PHP生成简单的验证码
2016/06/01 PHP
PHP实现生成带背景的图形验证码功能
2016/10/03 PHP
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】
2017/03/25 PHP
php 从指定数字中获取随机组合的简单方法(推荐)
2017/04/05 PHP
Laravel 6 将新增为指定队列任务设置中间件的功能
2019/08/06 PHP
PHP大文件分割分片上传实现代码
2020/12/09 PHP
jQuery 获取对象 根据属性、内容匹配, 还有表单元素匹配
2010/05/31 Javascript
JavaScript 浏览器验证代码(来自discuz)
2010/07/17 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
2013/07/29 Javascript
JavaScript将页面表格导出为Excel的具体实现
2013/12/27 Javascript
纯jquery实现模仿淘宝购物车结算
2015/08/20 Javascript
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
2017/08/16 Javascript
详解Vue取消eslint语法限制
2018/08/04 Javascript
4 种滚动吸顶实现方式的比较
2019/04/09 Javascript
微信小程序开发之点击按钮退出小程序的实现方法
2019/04/26 Javascript
浅谈layui 表单元素的选中问题
2019/10/25 Javascript
jQuery zTree如何改变指定节点文本样式
2020/10/16 jQuery
[02:04]2014DOTA2国际邀请赛 DK一个时代的落幕
2014/07/21 DOTA
初学python数组的处理代码
2011/01/04 Python
利用Python批量压缩png方法实例(支持过滤个别文件与文件夹)
2017/07/30 Python
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
Python简单生成随机数的方法示例
2018/03/31 Python
Python的iOS自动化打包实例代码
2018/11/22 Python
Tensorflow 实现释放内存
2020/02/03 Python
Html5写一个简单的俄罗斯方块小游戏
2019/12/03 HTML / CSS
Canvas 帧动画吃苹果小游戏
2020/08/05 HTML / CSS
韩语专业本科生求职信
2013/10/01 职场文书
教师节宣传方案
2014/05/23 职场文书
个人作风建设心得体会
2014/10/22 职场文书
出生证明格式
2015/06/15 职场文书
解除合同协议书范本
2016/03/21 职场文书
Nginx的rewrite模块详解
2021/03/31 Servers
Dubbo+zookeeper搭配分布式服务的过程详解
2022/04/03 Java/Android