前段时间,SegmentFault 低调上线了 技术号 模块,方便用户对数据进行集中管理。在开发过程当中,第一次引入了 MV* 框架。css
SF 的基本架构仍是后端路由,这也使得页面频繁地总体请求,体验很是很差。而技术号这个模块,不依赖 SEO,侧边导航又具备很是强烈的可切换性,因此适当地引入一个 MV* 框架是很是合适的。基于此考虑,决定在这个模块的开发中引入 Vue.js。前端
SF 目前的前端架构是很是传统的,jQuery+BootStrap+Requirejs+Gulp 的开发组合,r.js 作上线前的打包。如何将 Vue.js 应用进入目前的架构?其实很是简单,遵循一个原则便可,r.js 最后打包成一个 js 文件,而 webpack 最后也是打包成一个 js 文件。webpack
咱们用 webpack-dev-server 起前端 server 后,在内存中生成的 js 的路径相似 localhost:8080/xxx.js,而后在后端模版中引用这个 js 便可。值得注意的是,必须写死绝对路径,因此只能指定端口,目前我尚未找到更好的办法解决这个问题。程序员
其余部分的开发,好比 js 和 css 都没有什么大的问题,图片的引用成了问题。在第一次上线时我用了线上的绝对路径,这显然是不合理的。web
以前的图片引用,实际上是依赖后端的。前端上线时,会有一个文件夹包含全部的 js、css 以及图片文件,而后将这个文件夹重命名(重命名成一个哈希版本号),再上传到 CDN。因此若是独立打开 js、css 或者图片文件,其实路径上是会有一个版本号的。chrome
那么目前线上是如何解决的?目前应用图片的地方主要是后端模版文件以及 css。若是是后端模版文件,引用图片时会先调用一个后端函数,这个函数会返回图片路径,很显然开发环境和线上环境这个路径的结果是不一样的。一样,js 和 css 的引入,都会被这个函数先调用才返回引用路径。而在 css 中引用图片就没啥问题了,只是个相对路径的事。segmentfault
而将图片引用放入前端了呢?图片的路径和 js 的路径具备某种联系,本质是须要获取这个哈希版本号。问题在于,如何获取正在执行的 js 文件的路径?其实这很像是一道脑筋急转弯,若是习惯了 Node 的方式,可能会从 __dirname
和 process.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 }
这样就粗暴地解决了线上图片引用的问题。架构
可是本地开发引用图片的问题尚未解决。app
综上所述,本地开发起的前端 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 特点的一次开发尝试"。毕竟须要先后端路由混杂,并且还和最终线上打包方式有关,只能因地制宜,走本身的路。
这让我想到了以前一位前辈对我说的话:
前端的主要竞争力仍是学习能力,程序员的竞争力是解决问题的能力。
共勉之