技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> CSS/HTML --> 关于静态资源打包后的相对路径问题

关于静态资源打包后的相对路径问题

浏览:2634次  出处信息

    将多个静态资源打包为单个资源以减少请求数目,是提高页面加载速度的常用手段。于是上个星期,我就在实现网站静态资源的自动打包功能,原以为是个比较简单的问题,实现起来也没有遇到什么障碍,不过在开发完毕投入使用的时候却让我跌了下眼镜。由于静态资源在打包以后,它们的访问路径势必会改变,这样其他一些依赖于原有路径的资源就访问不到了。这方面最常见的例子,便是CSS样式表中引用的图片路径是相对于CSS文件路径的。当意识到这个问题以后,还真是让人手忙脚乱了一把。

    例如,有一个描述对话框组件的CSS文件,它的原有访问路径为/styles/dialog/core.css,其中有行样式表为url(header.png),这意味这幅图片的访问路径为/styles/dialog/header.png。同样,在另一个文件/styles/menu/core.css中也有url(bg.png)这样的代码。那么好,如果我们将这两个文件打包在一起,叫做/packed/styles/dialog-menu.css,那么浏览器就会去加载/packed/styles下的header.png和bg.png,为什么?因为url(…)这段代码,在打包后出现的位置就不同了。

    解决这个问题似乎有多种办法,例如将资源文件复制到/packed/styles下面,但这就要处理文件重名的问题。如果使用组件化开发的方式,两个组件之间应该不去考虑资源的重名,否则就产生了依赖。另一种方式,是在CSS内部使用绝对路径,例如在/styles/menu/core.css中使用url(/styles/menu/bg.png)而不是url(bg.png)。这么做可以解决打包上的问题,但是却破坏了组件化的开发方式。例如此时dialog组件就不是独立的了,它的图片路径是死的。而在理想情况下,一个组件的CSS文件和图片等资源应该是统一的,并独立与其他条件,这也是CSS中url(…)含义的设计目的。

    当然,我并不是说这种“组件化”的实践是必须遵守的,如果只是在开发一个独立的项目,便可以将“绝对路径”作为项目中的约定。但是在实际情况下,这种组件化及相对路径的使用是客观存在的。例如jQuery成百上千的插件,它们的CSS样式中一定不会使用绝对路径。那么我们又该如何对它进行打包呢?

    其实路径问题也很容易解决,只要在“打包”的时候修改掉CSS文件内容里的路径即可。例如我们可以知道,如果浏览器是在/packed/styles/dialog-menu.css文件中,访问到原本在/styles/dialog/core.css里的内容,那么原本的url(bg.png)就必须改写成url(/styles/dialog/bg.png)这样的绝对路径,或者是url(../…/styles/dialog/bg.png)这样相对于新地址的“相对路径”。

    这样的修改其实并不复杂,例如在CSS中,似乎需要替换的也只有url(…)这样的地址了,一个普通的正则表达式便可以解决,而比较麻烦的可能是JavaScript文件了。在某些组件化的JavaScript中,它需要的一些资源也是根据脚本文件的地址相对计算出来的。此时,其中的路径可能只是一些普通的字符串而已,没有规律保险的替换规则。如果要解决这个问题,我们可以在项目中形成某种约定,例如,计算相对路径时都不是简单的字符串拼接,而是使用一个函数调用。而这个函数调用,在进行“打包”时便可以看作是一个待替换的标志。

    相对路径的问题似乎就这么解决了,我想前面这段描述也已经足够清楚,比写代码还要清楚,所以暂时就先不提供我在项目里使用的动态打包机制了。不过这里还有个小小的花絮可以一谈。

    负责前端开发的同事很重视静态资源的打包问题,因此也就一直催促我实现这方面的功能。之前他说,他需要一个工具,输入一个配置文件,便可以将指定文件打包,然后在正式站点发布时修改页面上引用的地址就行了。我说这样不行,会死人的。例如,一个组件会在多个页面上使用,那么它的更新会导致多次打包,还要修改多个页面文件,这对于站点的快速升级更新也是一个灾难。此外,在页面上所使用的静态资源信息,还需要在打包工具的配置文件中重复,这也是一种违反DRY的情况

    我理想中的打包机制要有以下几个条件:

  • 遵守DRY原则,例如,一张页面需要加载哪些脚本,此类信息只会出现在对应页面中。
  • 在开发系统和生产系统上部署同一套代码,而不会为了生产系统修改代码。
  • 自动打包,自动版本升级或回退。打包结果易于开发人员进行识别、分析及调试。
  • 简单,清晰,性能高。
  •     上周实现的解决方案似乎基本符合这些条件,有机会我再来分享吧。

    建议继续学习:

    1. perl打包的建议    (阅读:2548)
    2. 游戏资源的压缩、打包与补丁更新    (阅读:2437)
    3. JavaScript组件打包模式    (阅读:2196)
    4. 使用xctool自动打包,测试xcode项目    (阅读:2024)
    5. 移动互联网必备:各平台自助渠道打包手段公开    (阅读:1655)
    6. 好用的CSS模块化打包工具CSS-Combo    (阅读:1339)
    7. 谈谈 external 模式的打包    (阅读:854)
    QQ技术交流群:445447336,欢迎加入!
    扫一扫订阅我的微信号:IT技术博客大学习
    © 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

    京ICP备15002552号-1