前言

前段时间,SegmentFault 低调上线了 技术号 模块,方便用户对数据进行集中管理。在开发过程中,第一次引入了 MV* 框架。

SF 的基本架构还是后端路由,这也使得页面频繁地整体请求,体验非常不好。而技术号这个模块,不依赖 SEO,侧边导航又具有非常强烈的可切换性,所以适当地引入一个 MV* 框架是非常合适的。基于此考虑,决定在这个模块的开发中引入 Vue.js。

SF 目前的前端架构是非常传统的,jQuery+BootStrap+Requirejs+Gulp 的开发组合,r.js 做上线前的打包。如何将 Vue.js 应用进入目前的架构?其实非常简单,遵循一个原则即可,r.js 最后打包成一个 js 文件,而 webpack 最后也是打包成一个 js 文件。

我们用 webpack-dev-server 起前端 server 后,在内存中生成的 js 的路径类似 localhost:8080/xxx.js,然后在后端模版中引用这个 js 即可。值得注意的是,必须写死绝对路径,所以只能指定端口,目前我还没有找到更好的办法解决这个问题。

图片引用

其他部分的开发,比如 js 和 css 都没有什么大的问题,图片的引用成了问题。在第一次上线时我用了线上的绝对路径,这显然是不合理的。

之前的图片引用,其实是依赖后端的。前端上线时,会有一个文件夹包含所有的 js、css 以及图片文件,然后将这个文件夹重命名(重命名成一个哈希版本号),再上传到 CDN。所以如果独立打开 js、css 或者图片文件,其实路径上是会有一个版本号的。

那么目前线上是如何解决的?目前应用图片的地方主要是后端模版文件以及 css。如果是后端模版文件,引用图片时会先调用一个后端函数,这个函数会返回图片路径,很显然开发环境和线上环境这个路径的结果是不同的。同样,js 和 css 的引入,都会被这个函数先调用才返回引用路径。而在 css 中引用图片就没啥问题了,只是个相对路径的事。

而将图片引用放入前端了呢?图片的路径和 js 的路径具有某种联系,本质是需要获取这个哈希版本号。问题在于,如何获取正在执行的 js 文件的路径?其实这很像是一道脑筋急转弯,如果习惯了 Node 的方式,可能会从 __dirnameprocess.cwd() 去入手,但是很遗憾虽然客户端也能引入 process 、path 等包,但是获取不到类似的值。答案也很简单,直接获取 script 的 dom 节点,然后取 src 即可,就是完美的绝对路径。另外还有个方法,可以用 document.currentScript.getAttribute('src'),但是 src 赋值的字符串是什么,它就是什么,而且在实际开发中莫名报错,所以我用了前者。

cdn: src => {
  let jsPath = document.getElementById('indexScript').src.replace(/script.*/, 'img/')
  src = jsPath + src
  return src
}

这样就粗暴地解决了线上图片引用的问题。

开发 VS 线上

但是本地开发引用图片的问题还没有解决。

综上所述,本地开发起的前端 server,其实是用了绝对地址 localhost:8080/xxx.js,如果用以上规则获取图片,很显然获取的还是 localhost:8080 域名下的图片,我们需要将其切换到后端路由的测试域名下。

也就是规则类似 localhost:8080/build/xxx/img/xxx.png 的请求都需要转到另外一个域名下(实际开发中是 sf.testapp.org),chrome 下有个神器 ReRes 可以轻易做到。

配置如下:

// If URL match
http://localhost:8080/build/(.*)/img/
// Response
http://sf.testapp.org/build/$1/img/

这样就粗暴解决了开发环境引用不到图片的问题。

待续

这并不是终点。其实目前的图片是放在最终上线的静态文件文件夹中,和 Vue.js 整个开发项目剥离,这并不是一个好的方式。最好的方式肯定是放在 Vue.js 项目中,比如 assets 或者 static 文件夹下。这就需要在前端引用图片的时候判断是开发还是线上环境,分别引用不同地址,开发完后,打包前需要将项目中的图片同步到需要上线的静态文件文件夹中。还有另一种方案,开发和线上引用一个地址,但是开发环境引用时再做一次映射,跳到 Vue.js 项目内。

目前还没考虑这点,因为这只是 MV* 的第一次尝试,文件目录的结构还没最终确定。

思考

这个功能的开发其实不具有典型的参考意义,我称之为 "走 SF 特色的一次开发尝试"。毕竟需要前后端路由混杂,而且还和最终线上打包方式有关,只能因地制宜,走自己的路。

这让我想到了之前一位前辈对我说的话:

前端的主要竞争力还是学习能力,程序员的竞争力是解决问题的能力。

共勉之

填坑:在 SegmentFault 开发单页应用之图片引用的问题探索的更多相关文章

  1. Laravel 5.5 + Vue 开发单页应用

    上次我用 laravel5.3 + Vue 开发了一个简单的单页应用,这次我打算将其升级到 laravel5.5,在升级的过程中,做一下记录,其源码放在 github 上面,源码地址   开发环境 软 ...

  2. 使用Vue快速开发单页应用

    本文所涉及代码全在vue-cnode 单页应用,即在一个页面集成系统中所有功能,整个应用只有一个页面.因为路由的控制在前端,单页面应用在页面切换时比传统页面更快,从而在前端体验更好. 将逻辑从后端转移 ...

  3. 【前端vue开发架构】vue开发单页项目架构总结

    为营销活动设计的前端架构 主要的技术栈为 Vuejs,Webpack,请自行阅读如下技术或者框架的文档: 一.基础说明: node (https://nodejs.org/en/) npm (http ...

  4. 基于环信SDK的IM即时通讯填坑之路(vue)

    公司最近使用第三方环信SDK的进行通信聊天,基本已完成.记录下填坑之路 1.可以通过以下方式引用 WebSDK 1.安装 npm install easemob-websdk --save 2. 先 ...

  5. Android Tips – 填坑手册

    出于: androidChina   http://www.androidchina.net/3595.html 学习 Android 至今,大大小小的坑没少踩,庆幸的是,在强大的搜索引擎与无私奉献的 ...

  6. webapp填坑记录[更新中]

    网上也有许多的 webapp 填坑记录了,这几个月,我在公司正好也做了2个,碰到了一些问题,所以我在这里记录一下我所碰到的问题: meta 头部声明在开发的时候,刚刚创建 HTML 文件,再使用浏览器 ...

  7. webapp填坑记录

    网上也有许多的 webapp 填坑记录了,这几个月,我在公司正好也做了2个,碰到了一些问题,所以我在这里记录一下我所碰到的问题: meta 头部声明在开发的时候,刚刚创建 HTML 文件,再使用浏览器 ...

  8. 微信公众号支付备忘及填坑之路-java

    一.背景 最近公司给第三方开发了一个公众号,其中最重要的功能是支付,由于是第一次开发,遇到的坑特别的多,截止我写博客时,支付已经完成,在这里我把遇到的坑记录一下(不涉及退款).不得不吐槽一下,腾讯这么 ...

  9. css 填坑常用代码分享

    以下是常用的代码收集,没有任何技术含量,只是填坑的积累.转载请注明出处,谢谢. 因为提交比较麻烦,后来转置github:https://github.com/jsfront/src/blob/mast ...

随机推荐

  1. SpringBoot(一)走进Springboot的世界

    什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员 ...

  2. bzoj 3874: [Ahoi2014]宅男计划

    Description  [故事背景] 自从迷上了拼图,JYY就变成了个彻底的宅男.为了解决温饱问题,JYY 不得不依靠叫外卖来维持生计. [问题描述] 外卖店一共有N种食物,分别有1到N编号.第i种 ...

  3. HDU 2546 饭卡(01背包裸题)

    饭卡 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  4. BZOJ 1083: [SCOI2005]繁忙的都市【Kruscal最小生成树裸题】

    1083: [SCOI2005]繁忙的都市 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2925  Solved: 1927[Submit][Sta ...

  5. c语言_FILE结构体解释及相关操作

    1. 文件和流的关系 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件 ...

  6. 关于OELD屏显示电池电量的简易方法

    如何采集电源电压大家可能都熟悉,stm32的ADC+DMA能很方便迅速的帮我们采集到自己想要的电压数据.使用DMA进行数据搬运也能很好的减轻CPU的一部分压力.但是这样只是第一步--数据. 用户想看到 ...

  7. GBK,UTF8是什么?有什么区别,做网站选择哪种好?

    GBK包含全部中文字符: UTF-8则包含全世界所有国家需要用到的字符. GBK是在国家标准GB2312基础上扩容后兼容GB2312的标准(好像还不是国家标准) UTF-8编码的文字可以在各国各种支持 ...

  8. HTML 5  标签

    HTML 5 标签 标签定义文档中的节(section.区段).比如章节.页眉.页脚或文档中的其他部分. E 9+.Firefox.Opera.Chrome 和 Safari 标签. 注释:IE 8 ...

  9. 为什么选择.NETCore?

    为什么.NETCore? 学习新的开发框架是一项巨大的投资.您需要学习如何在新框架中编写,构建,测试,部署和维护应用程序.作为开发人员,有许多框架可供选择,很难知道什么是最适合的工作.即使您正在使用. ...

  10. Android 双卡获取当前使用流量在线卡的信息

    最近接触了一个项目,需要获取在线流量卡的信息,下面的方式,可以获取大部分手机的正确手机卡信息. 一  获取获取IMEI public static String getDeviced(int solt ...