├── .gitignore ├── img ├── cd.jpg ├── pwa-2.jpg ├── ssr.png ├── tfc-1.png ├── tfc-2.png ├── pwa-1.jpeg └── architech.png ├── blog ├── webpack-plugin.md ├── ie7compatible.md ├── postcss.md ├── CI.md ├── git-vscode.md ├── TFC.md ├── vue-test.md ├── AC.md ├── bem.md ├── jsonp.md ├── iframe-height.md ├── vue-startup.md └── perfomance.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .idea -------------------------------------------------------------------------------- /img/cd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/cd.jpg -------------------------------------------------------------------------------- /img/pwa-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/pwa-2.jpg -------------------------------------------------------------------------------- /img/ssr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/ssr.png -------------------------------------------------------------------------------- /img/tfc-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/tfc-1.png -------------------------------------------------------------------------------- /img/tfc-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/tfc-2.png -------------------------------------------------------------------------------- /img/pwa-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/pwa-1.jpeg -------------------------------------------------------------------------------- /img/architech.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaicFE/blog/HEAD/img/architech.png -------------------------------------------------------------------------------- /blog/webpack-plugin.md: -------------------------------------------------------------------------------- 1 | # webpack插件 2 | 3 | - [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader) 4 | - [multipage-webpack-plugin](https://github.com/mutualofomaha/multipage-webpack-plugin) 5 | - [ejs-compiled-loader](https://github.com/bazilio91/ejs-compiled-loader) -------------------------------------------------------------------------------- /blog/ie7compatible.md: -------------------------------------------------------------------------------- 1 | # ie 7兼容想法 2 | 3 | nodejs express Nunjucks less bootstrap2 jquery1 require.js gulp 4 | 5 | 正因为是兼容ie7或者ie8以上的pc端的页面,我在整个项目的计划中,因为ie7不支持了es5的语法。直接和react和vue等框架说“byebye”。虽然网上有很多的兼容的方法,但是怕一旦使用了整个过程就变得很尴尬。 6 | 7 | 这时,我第一反应就是用express和模版语言,实现动态的数据单项绑定,技术有点旧,但是保证了兼容性以及组件化的拆分。而js的模块化则是用require.js和gulp的自动化操作。 -------------------------------------------------------------------------------- /blog/postcss.md: -------------------------------------------------------------------------------- 1 | # POSTCSS使用技巧 2 | 3 | postcss的发展非常快,它可以对css进行逻辑的控制,变量的提取,更像一个插件平台,提高项目的开发效率。 4 | 5 | ## [autoprefixer](https://github.com/postcss/autoprefixer) 6 | 7 | 不同浏览器的样式会有不同的前缀,如果在构建项目的过程当中,我们需要一个一个浏览器考虑兼容,确实不符合我们的开发效率。 8 | 9 | 10 | 11 | ## BEM 12 | 13 | BEM分别代表着Block,Element,Modifier。 14 | 15 | Block指的是块,我们可以理解为组件。整个网站是由很多个块组成。 16 | 17 | Element可以理解为块里面的一个元素。使用`__` 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /blog/CI.md: -------------------------------------------------------------------------------- 1 | # 持续集成 2 | 3 | 产品迭代的过程,我们需要成熟的整个持续集成的流程。 4 | 5 | > 持续集成的优点 6 | 7 | >(1)快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。 8 | >(2)防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。 9 | 10 | 11 | > Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。" 12 | 13 | ## 持续部署和持续交付 14 | 15 |  16 | 17 | 它俩的区别在于主要是在完成编码,测试,集成,测试后,部署到生产环境的这一个过程是自动还是人为的。人为有人为的好处。 18 | 19 | ## Jenkins 20 | 21 | 22 | 23 | ## Travis 24 | 25 | ## Gitlab 26 | 27 | [Continuous Deployment of Node.js Applications](https://blog.risingstack.com/continuous-deployment-of-node-js-applications/) -------------------------------------------------------------------------------- /blog/git-vscode.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 提交信息 4 | 5 | `git commit`提交信息的规范,建议在提交信息头部加上这几个类型。 6 | 7 | - 增加功能 8 | - 更新功能 9 | - 删除功能 10 | - 优化代码 11 | - 合并代码 12 | - 修复bug 13 | 14 | ## ITREM + OH MY ZSH的相关操作 15 | 16 | #### 安装 17 | 18 | **via curl** 19 | 20 | ```bash 21 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 22 | ``` 23 | 24 | **via wget** 25 | 26 | ```bash 27 | sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)" 28 | ``` 29 | 30 | #### 环境变量的配置 31 | 32 | ```bash 33 | vim ~/.zshrc 34 | ``` 35 | 36 | ```bash 37 | alias code='/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code' 38 | alias subl='/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl' 39 | alias ngrok='~/software/ngrok' 40 | ``` 41 | 42 | ## vscode关于eslint配置 43 | 44 | ```javascript 45 | "eslint.validate": [ 46 | "javascript", 47 | "javascriptreact", 48 | "html", 49 | "vue" 50 | ], 51 | "eslint.options": { 52 | "plugins": ["html"] 53 | }, 54 | "git.confirmSync": false 55 | ``` 56 | 57 | 参考[【译】让人倾倒的 11 个 npm trick](https://segmentfault.com/a/1190000006804410) 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog 2 | Blog for PAIC FE Team 3 | 4 | - [【技术分享】Vue的选型和Webpack的入门](https://github.com/PaicFE/blog/issues/1) by 项伟平 5 | - [【技术研究】如何动态获取跨域iframe高度](https://github.com/PaicFE/blog/issues/2) by 项伟平 6 | - [【技术分享】国内开发加速方法合集](https://github.com/PaicFE/blog/issues/3) by 项伟平 7 | - [【技术分享】JSONP和跨域](https://github.com/PaicFE/blog/issues/8) by 项伟平 8 | - [【技术研究】性能优化之路](https://github.com/PaicFE/blog/issues/9) by 项伟平 9 | - [【技术分享】参加腾讯Web前端大会体验](https://github.com/PaicFE/blog/blob/master/blog/TFC.md) by 项伟平 10 | - [【技术分享】手牵手使用Husky & Nodejs自定义你的Git钩子](https://github.com/PaicFE/blog/issues/10) by 杨凯 11 | - [mocha的单元测试](https://github.com/PaicFE/blog/issues/11) by 项伟平 12 | - [入门BEM](https://github.com/PaicFE/blog/issues/12) by 项伟平 13 | - [AlloyTeam 前端大会的技术一览](https://github.com/PaicFE/blog/issues/13) by 项伟平 14 | - [Vue的自动化测试](https://github.com/PaicFE/blog/issues/14) by 项伟平 15 | - [Phantomjs教你如何实现浏览器截图并上传截图文件](https://github.com/PaicFE/blog/issues/15) by 杨凯 16 | - [多页面打包框架(mpa)](https://github.com/PaicFE/blog/issues/16) by 项伟平 17 | - [PWA技术分享会](https://github.com/Cainankun/cainankun.github.io/issues/1) by 蔡南坤 18 | - [webpack版本的差异性](https://www.jianshu.com/writer#/notebooks/9046660/notes/22174344) by 项伟平 19 | 20 | 21 | 22 | 欢迎点击watch订阅我们博客。 23 | 24 | -------------------------------------------------------------------------------- /blog/TFC.md: -------------------------------------------------------------------------------- 1 | # 【技术分享】参加腾讯Web前端大会体验 2 | 3 | 我是第一次参加那么正式的前端技术交流大会。趁着“前端”的这点热度,我也来抽个热闹。这里讲讲我自己比较印象深刻的几点感受。 4 | 5 | ## Nicolás Bevacqua的 The Future of Writing Javascript 6 | 7 | 我看了一下来自阿根廷布宜诺斯艾利斯的[Nicolás Bevacqua](https://github.com/bevacqua/)的github。他真是javascript界的大牛,他参与的组织和他提交的代码量挺疯狂的,项目随便都是上万星的,简直就是偶像。 8 | 9 |  10 | 11 |  12 | 13 | 14 | 虽然他的英语口音非常重,但是他讲的内容还是相当友好浅显的。es6已经成为我们项目的标配,但是我相信很多同事还没有完全懂的如何使用es6的新语法。何况es2017已经渐渐到来。Nicolas讲述了整个javascript从讨论,提案,草案,候选,完成的过程。不同的stage都完成这不同的特性。让我们感受到javascrit还在快速的发展,据我了解“面向对象如今支持私有变量”。在实际的应用当中,我们更应该用上新语法特性提高开发效率。它具体介绍了以下几个特性。 15 | 16 | - Promise的finally方法 17 | - 类的修饰器 18 | - 正则表达式的命名捕获 19 | - 正则表达式的后行断言 20 | - async和await 21 | 22 | ## 玉龙大大的初创公司前端工程体系建设 23 | 24 | 玉龙大大的干货真是非常实用,没有什么最热门的前端框架的讨论,更多是后端渲染的模版。语言简练却富含实战性。 25 | 26 | 给我影响深刻的是Gitlab CI的持续集成和dom diff的测试提交。 27 | 28 | #### Gitlab CI的持续集成 29 | 30 | 我们公司更多是使用Jenkins去完成自动集成,主要原因是因为后端大部分是JAVA语言。Jenkins其实还是能保证一个很好的部署效率,但是明显更不上时代的节奏。现在的持续继承技术非常强大。 31 | 32 | 玉龙大大指出的多个测试域名的“思路”,也是让我“叹为观止”。为每个feature的实现独立设置域名,保证了每个功能开发的完整性,同时,提高了测试的效率。保证每个开发者有独立的测试环境,无形地提高了“并行”开发的可能性。 33 | 34 | #### dom diff的测试提交 35 | 36 | 我认为我们组的测试效率不高,很大一部分是**show case**的质量很差。业务和产品经常改需求,导致测试的效率大大降低。native的测试占用了大量的时间,留给H5的并不多。所以我们需要的是提高show case的效率。把每个dom的变化分类提交。 37 | 38 | ## JustJavaC的V8性能优化 39 | 40 | sorry,我才疏学浅没怎么听懂。大概是混合语言的部分更多是数据类型的转换。V8的性能优化更多是数据类型的转化。 41 | 42 | ## PWA和AMP 43 | 44 | 我认为这是我在TFC的又一大收获。PWA是一个相对成熟的技术,受到的影响更多是因为ios暂不支持的阻碍。我个人认为像react native或者weex等混合语言开发的,需要非常大地学习成本。react到react native的改造不是一两天能完成的,但是PWA的改造是完全可以通过一两个小时完成,只需要你了解servive worker的接口。在如今流行的前端框架中,vue,react和preact都有支持pwa的模版。 45 | 46 | - vue 47 | 48 | ```bash 49 | vue init pwa my-project 50 | ``` 51 | 52 | ```bash 53 | 54 | ``` 55 | 56 | 57 | -------------------------------------------------------------------------------- /blog/vue-test.md: -------------------------------------------------------------------------------- 1 | # Vue的自动化测试 2 | 3 | Vue官方脚手架会自带测试配置,但是我们知道国内的前端友人大多不写测试,也不会写测试。 4 | 5 | **为什么我们需要测试?** 6 | 7 | > 让产品可以快速迭代,同时还能保持高质量 -- [阮一峰 持续集成是什么?](http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html?utm_source=tuicool&utm_medium=referral) 8 | 9 | **什么是持续集成?** 10 | 11 | **它和持续部署有什么区别?** 12 | 13 | 代码集成到主分支的时候,需要经过一系列的自动化测试,当测试都通过之后,可以完成自动化部署。只要一个测试用例不通过,就不能集成。这说明了自动化测试的重要性,有时候我们不能等测试工程师去发现问题。 14 | 15 | 在Vue脚手架当中,Karma和NightWatch分别对应着单元测试和e2e测试。单元测试更多是面向JS功能逻辑的检验,而NightWatch更多是面对业务逻辑的检验。 16 | 17 | ## Karma 18 | 19 | [Karma](https://github.com/karma-runner/karma)是一个专门的测试运行器(runner),它不是一个测试框架框架,也不是以一个断言库。 20 | 21 | Karma兼容[Jasmine](https://github.com/karma-runner/karma-jasmine),[Mocha](https://github.com/karma-runner/karma-mocha)和[QUnit](https://github.com/karma-runner/karma-qunit),可以集成mocha,webpack等功能,成为以Karma为平台的单元测试。它拥有一些测试插件: 22 | 23 | - [karma-webpack](https://github.com/webpack-contrib/karma-webpack) 用webpack预处理文件 24 | - [karma-coverage](https://github.com/karma-runner/karma-coverage) 测试覆盖率 25 | - [karma-mocha](https://github.com/karma-runner/karma-mocha) 接入mocha测试框架 26 | - [karma-spec-reporter](https://github.com/mlex/karma-spec-reporter) 输出报告 27 | - [karma-phantomjs-launcher](https://github.com/karma-runner/karma-phantomjs-launcher) 控制PhantomJS 28 | - [karma-phantomjs-shim](https://github.com/tschaub/karma-phantomjs-shim) 给PhantomJS兼容的控制 29 | 30 | karma-coverage是基于[istanbul](https://github.com/gotwarlost/istanbul)。这些插件可以集成为一个测试平台,把webpack打包的vue项目,在测试里面的组件实现的功能。包括独立的组件库,业务逻辑和请求范围。 31 | 32 | 33 | ## NightWatch 34 | 35 | NightWatch是一个专门的端对端测试运行器(runner)。 36 | 37 | 它依赖于浏览器控制器selenium,而selenium是一个`.jar`后缀的文件,需要java的运行环境。所以你需要安装java并配置好环境变量。然而,selenium需要对应的driver配合来操控浏览器。 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /blog/AC.md: -------------------------------------------------------------------------------- 1 | AlloyTeam Conf是一个干货非常集中的前端大会。就前端的技术,我分享一下前端大会的内容,谈谈自己的想法。 2 | 3 | ## 面向亿万级用户的Web同构直出 4 | 5 | 直出技术也就是传说中的服务端渲染“SSR”技术,Web首屏页面的加载速度能得到极大提升。AlloyTeam采用的是React技术栈同构直出,我们采用Vue技术栈的同构直出。 6 | 7 | 主讲人李强用实战经历说明了手Q在高访问量的直出表现,他说道,直出其实减轻了浏览器的负担,但是增加了服务器的负担,大概是以前的5倍。这个在生产环境实现起来事有难度的。 8 | 9 | #### 实现原理 10 | 11 | 12 |  13 | 14 | 15 | SSR技术说白了就是在服务端和浏览器端各有一个入口,共用一份代码。服务端会把内容拼接好,缓存起来,提高首屏效率。代码的差异性需要处理,例如生命周期不同。 16 | 17 | > 由于没有动态更新,所有的生命周期钩子函数中,只有 beforeCreate 和 created 会在服务器端渲染(SSR)过程中被调用。这就是说任何其他生命周期钩子函数中的代码(例如 beforeMount 或 mounted),只会在客户端执行。 18 | 19 | 所以有些浏览器相关的内容要在 mounted 底下写。简而言之,SSR的vue项目需要注意的点和普通项目不同,迁移会带来成本。 20 | 21 | 因为涉及到更多的服务端,SSR会带来更大的服务器宕机的风险。腾讯的做法事监测服务器的负载,负载过高的情况有柔错处理,也就是服务器会指向“Plan B”非SSR的页面。这样,也就是你一套代码要打包出两套页面(SSR和非SSR)。 22 | 23 | 24 | ## 大型Web项目可用性提升 - 零脚本错误的实战 25 | 26 | 脚本错误对于前端开发者一点都不陌生。测试工程师手上机型有限,一旦发生脚本错误,轻则影响页面的一些功能,重则直接导致页面白屏。大众用户处在不同的网络情况、不同的浏览器。也有可能是后台改了数据类型等,更新数据出错都有可能反应在前端。 27 | 28 | 高效的错误收集分类是非常重要,有这么一个平台可以收集到很多数据,从而进一步优化整个页面,这是一个良性的反馈。[Sentry](https://github.com/getsentry/sentry)是有名的错误上报平台,服务端是python写的,提供很多款语言的SDK,进行定制化的错误分类分析。 29 | 30 | 同时,他提到在测试环境做了错误定位组件,也非常有实用价值。 31 | 32 | ## 高效H5动画设计与性能优化 33 | 34 | h5的动画是随着flash正式退出历史舞台,它需要一个重要的蜕变。它包含了动图,css3动画,canvas,webgl等。要让页面变得生动活泼起来,绝对不是一件简单的事情。在那些场景用动图,那些场景用css3,那些场景用canvas,其中的选型变得非常重要。 35 | 36 | css3动画可以采用GPU加速,“willchange”等能够挽回一些安卓低端机型的劣势,但是过分的滥用会同样会造成资源浪费。 37 | 38 | 39 | ## 后函数式编程 40 | 41 | 函数式变成离我们产品的需求应该是最远。函数式编程,带来的是代码高维护性和观察者模式。rx.js,cycle.js应该在项目中可以有可以没有。在数据同步和响应方面更多可以从需求的复杂程度下手。我另外一个受益点,即是纯函数的编写,纯函数的结果不受外部的变量影响,可以缓存,可以测试,有助于代码的编写。 42 | 43 | ## Service Worker与PWA展望 44 | 45 | 相比与其他技术,Service Worker是离我们投入生产环境最近。随着很多厂家逐渐兼容PWA技术,例如安卓微信浏览器。PWA技术的优势在于不需要大范围改代码,而且轻松兼容旧浏览器。 46 | 47 | 48 |  49 | 50 | 51 | Service Worker更像一个“媒介”“代理”。检查着静态资源的更新情况,优先价值离线资源,旧的资源将会被更新,其中包括了html,js,css还有fetch请求等。整个执行会有“安装”“激活”的过程,其实非常简单,完成即可从浏览器读取数据。结合多页面的Vue框架,将会是成为我下一年的一个重点工作目标。 52 | 53 | 54 |  55 | 56 | 57 | ## 总结 58 | 59 | 我在AlloyTeam Conf的收获还是特别多,我认为能够和自己工作能联系在一起的技术,才是真正的“好技术”,继续加油。 60 | -------------------------------------------------------------------------------- /blog/bem.md: -------------------------------------------------------------------------------- 1 | # 【技术分享】入门BEM 2 | 3 | ## 前言 4 | 5 | **为什么不用ID标识符** 6 | 7 | 主要考虑到样式重用性以及与页面的耦合性。ID本来就是唯一的而且权值那么大,还不如写在行内样式。 8 | 9 | ``` 10 | #button { 11 | text-decoration: underline; 12 | } 13 | ``` 14 | 15 | **为什么不用大于三层嵌套选择器** 16 | 17 | 嵌套选择器增加了代码耦合,使重用变得不可能,过多的嵌套会导致显示性能下降。简洁的选择器不仅可以减少css文件大小,提高页面的加载性能,让浏览器解析时也会更加高效。同时也会提高开发人员的开发效率,降低了维护成本。子代选择器不好的地方还在于,如果层次关系过长,逻辑不清晰,非常不利于维护。 18 | 19 | css的匹配原理**不是从左到右的,而是从右到左的**,从右边开始匹配是为了尽早过滤掉一些无关的样式规则和元素。 20 | 21 | ```css 22 | .button_hovered .button__text { 23 | text-decoration: underline; 24 | } 25 | ``` 26 | 27 | **为什么不用组合选择器** 28 | 29 | 组合选择器的耦合性更强,而且可维护性更加差。 30 | 31 | ```css 32 | .button.button_theme_islands { 33 | text-decoration: underline; 34 | } 35 | ``` 36 | 37 | ## 介绍 38 | 39 | BEM是**Block,Element,Modifier**的缩写。下面分别来介绍一下这三个概念: 40 | 41 | - 块(Block)是一个块级元素,可以理解为组件块,比如头部是个block,内容也是block,一个block可能由几个子block组成。 42 | - 元素(Element)element是block的一部分完成某种功能,element依赖于block,比如在logo中,img是logo的一个element,在菜单中,菜单项是菜单的一个element。 43 | - 修饰符(Modifier)modifier是用来修饰block或者element的,它表示block或者element在外观或行为上的改变,例如actived。 44 | 45 | 这里引用[BEM的定义](http://www.w3cplus.com/css/bem-definitions.html)一文中的两张图: 46 | 47 |  48 | 49 |  50 | 51 | 我们通过BEM命名法写样式如下: 52 | * .block{} 53 | * .block__element{} 54 | * .block--modifier{} 55 | * .block__element--modifier{} 56 | 57 | BEM解决了的问题, 58 | 59 | - 页面CSS模块化,每个block就是一个模块,模块间相互独立,不会造成污染 60 | - 多级的class命名,避免选择器的嵌套结构 61 | - 减少通配符*或者类似[hidden="true"]这类选择器的使用 62 | - 巧妙运用scss的特性,保证了样式的可维护性 63 | 64 | BEM将页面解析为block和element,然后根据不同的状态使用modifier来设置样式,在scss的属性帮助下,其实,写BEM并不麻烦。 65 | 66 | ## 使用scss写BEM 67 | 68 | #### 灵活的& 69 | 70 | 当嵌套使用`&`时,它会直接抓取父选择器的类名,自动拼接上元素名字,避免CSS文件中组件样式的冲突。这样,我们可以得到一个完整的BEM结构的类名,这样有效利用scss的嵌套特性避免CSS文件中组件样式的冲突。 71 | 72 | 示例: 73 | 74 | ```scss 75 | .header { 76 | &__text { 77 | text-decoration: underline; 78 | } 79 | &__image { 80 | background-color: steelblue; 81 | } 82 | } 83 | ``` 84 | 85 | #### 强大的@extend 86 | 87 | `@extend`是scss的继承语法,它可以将父级的属性继承到子级。主要使用在modifier上,因为改变状态的属性和原来的基本保持一致。你可以弄少一个classname。 88 | 89 | 示例: 90 | 91 | ```html 92 | 100 | ``` 101 | 102 | ```scss 103 | .nav { 104 | background-color: steelblue; 105 | &__container { 106 | display: flex; 107 | justify-content: space-between; 108 | } 109 | &__item { 110 | color: white; 111 | &--active { 112 | @extend .nav__item; 113 | border-bottom: 1px solid red; 114 | } 115 | } 116 | } 117 | ``` 118 | 119 | 120 | ## 参考 121 | 122 | - [BEM的定义](http://www.w3cplus.com/css/bem-definitions.html) 123 | - [如何更好的使用BEM](http://www.w3cplus.com/preprocessor/getting-sass-y-with-bem.html) 124 | - [CSS性能分析,如何优化CSS提高性能](http://www.cnblogs.com/xiaoloulan/p/5801663.html) 125 | -------------------------------------------------------------------------------- /blog/jsonp.md: -------------------------------------------------------------------------------- 1 | # 【技术分享】 JSONP和跨域 2 | 3 | 撰稿人:项伟平 4 | 5 | 跨域是一位前端工程师经常面对的问题。 6 | 7 | 面试的时候,面试官会问你一个问题,“解释一下什么是跨域?”,其实百分之八十的面试者都会回答jsonp。如果你回答了jsonp,又会出现很多问题,例如“jsonp的实现原理”,“不用jquery怎么实现jsonp”,“jsonp的安全问题”。如果你回答CORS,也会出现很多问题,例如“CORS的实现原理”,“CORS较jsonp的优点在哪里”,“为什么CORS不用jsonp”。 8 | 9 | ## jsonp是什么? 10 | 11 | ### jsonp的实现原理 12 | 13 | jsonp是一个很老的技术,为啥现在还在使用?很大一部分原因是因为相对来说配置相对简单,后端工程师偷了懒。实现原理用自己的话说就是使用HTML的动态脚本的漏洞。在js端构建一个``,通过一个callback参数构建一种关系,你想得到的参数通过函数回调完成。 14 | 15 | 为了生动形象地展示一下jsonp,我用koa写一个简单的实现。 16 | 17 | ```javascript 18 | const Koa = require('koa'); 19 | const querystring = require('querystring'); 20 | const app = new Koa(); 21 | 22 | const main = ctx => { 23 | var data = { 24 | "name": "Monkey" 25 | }; 26 | var qs = querystring.parse(ctx.request.url.split('?')[1]); 27 | data = JSON.stringify(data); 28 | var callback = qs.callback+'('+data+');'; 29 | ctx.response.body = callback; 30 | }; 31 | 32 | app.use(main); 33 | app.listen(3000); 34 | ``` 35 | 36 | ### 不用jquery怎么实现jsonp 37 | 38 | [jquery](https://github.com/jquery/jquery)或者[zepto](https://github.com/madrobby/zepto)实现jsonp跨域操作非常简单,在设置`dataType`字段时设置为jsonp即可。但是,如果没有了jquery,怎么去实现jsonp,你可能会选择去创建一个动态脚本。把参数和callback拼在url上。 39 | 40 | 如果你使用的是Vue的项目,你应该不会使用jquery,那你怎么使用jsonp? 41 | 42 | - [vue-resource](https://github.com/vuejs/vue-resource) 是支持jsonp 43 | - [axios](https://github.com/mzabriskie/axios) 不支持jsonp 44 | 45 | axios因为在node.js端和browser端同时都支持,而且长期支持。axios的维护者并不打算支持jsonp,正因为它存在着安全性隐患,如果你希望兼容jsonp的接口,可以使用这个库[webmodules/jsonp](https://github.com/webmodules/jsonp)替代部分的功能。vue-resource相对来说,曾经被官方放弃,从设计方面vue-resource相对来说考虑得比较全面,全面兼容jsonp。 46 | 47 | ### jsonp的安全问题 48 | 49 | 从[webmodules/jsonp](https://github.com/webmodules/jsonp)这个库,我们可以看到它的实现方式。jsonp的漏洞在于callback函数,它可以植入脚本影响后端代码。[JSONP 安全攻防技术](http://blog.knownsec.com/2015/03/jsonp_security_technic/)里面介绍了在使用jsonp存在的安全性问题,一方面是json挟持,另一方面是callback植入脚本的漏洞。解决漏洞的方法可以在头文件中加上`Content-Type: application/json`,但是在老版本的ie还是会出现编码安全问题,还需要限制编码`charset=utf-8`。 50 | 51 | > 1. 严格安全的实现 CSRF 方式调用 JSON 文件:限制 Referer 、部署一次性 Token 等。 52 | > 2. 严格安装 JSON 格式标准输出 Content-Type 及编码( Content-Type : application/json; charset=utf-8 )。 53 | > 3. 严格过滤 callback 函数名及 JSON 里数据的输出。 54 | > 4. 严格限制对 JSONP 输出 callback 函数名的长度(如防御上面 flash 输出的方法)。 55 | > 5. 其他一些比较“猥琐”的方法:如在 Callback 输出之前加入其他字符(如:/**/、回车换行)这样不影响 JSON 文件加载,又能一定程度预防其他文件格式的输出。还比如 Gmail 早起使用 AJAX 的方式获取 JSON ,听过在输出 JSON 之前加入 while(1) ;这样的代码来防止 JS 远程调用 56 | 57 | ## CORS是什么? 58 | 59 | CORS即是跨域资源共享(全称为Cross-origin resource sharing)。它的实现需要后端配合,可以针对域名,端口和请求方式等作出限制。这样保证了跨域请求的安全性。阮一峰老师的[跨域资源共享 CORS 详解](http://www.ruanyifeng.com/blog/2016/04/cors.html)详细地介绍了两类请求,简单请求(simple request)和非简单请求(not-so-simple request)。 60 | 61 | ### CORS的实现原理 62 | 63 | CORS的实现需要浏览器和服务器同时支持,IE浏览器不能低于IE10。所以对于老版本的IE需要jsonp接口的兼容。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样,主要是服务器配置的附加头文件。 64 | 65 | 下面是非简单请求CORS在express上的具体实现方式: 66 | 67 | ```javascript 68 | app.all('*', function(req, res, next) { 69 | res.header("Access-Control-Allow-Origin", "http://localhost:3333"); 70 | res.header("Access-Control-Allow-Headers", "X-Requested-With"); 71 | res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); 72 | res.header("X-Powered-By",' 3.2.1') 73 | res.header("Content-Type", "application/json;charset=utf-8"); 74 | next(); 75 | }); 76 | ``` 77 | 78 | - Access-Control-Allow-Origin 必需,是对域名的限制 79 | - Access-Control-Allow-Methods 必需,是支持跨域请求的方法 80 | - Access-Control-Allow-Credentials 是否允许发送coookie 81 | - Access-Control-Allow-Headers 服务器支持的所有头信息字段 82 | - Access-Control-Max-Age 预检的有效时间 83 | 84 | ### CORS比jsonp的优点在哪里 85 | 86 | JSONP只支持GET请求,CORS支持所有类型的HTTP请求。相比之下,CORS的兼容性稍逊一筹,但是它在安全性上更有保障,如果是新版接口尽可能使用CORS方式跨域。 87 | 88 | -------------------------------------------------------------------------------- /blog/iframe-height.md: -------------------------------------------------------------------------------- 1 | # 【技术研究】如何动态获取跨域iframe高度 2 | 3 | 撰稿人:项伟平 4 | 5 | ## 引言 6 | 7 | iframe是一个“好东西”,但是又会带给你很多头疼的“问题”,特别是在ios的兼容性问题。在ios当中,iframe里的页面不会随着外层的网页大小自适应弹性缩放。相比之下,PC浏览器浏览器和安卓的浏览器则是可以实现缩放,这导致了差异性。这时候第一时刻,想到的是兼容的写法。专门针对ios专门设置iframe的scrolling属性为“no”,其他浏览器为“yes”,如下方源码。但是如果iframe子页面中存在响应式部件tab,高度进行变化,则会引起重绘重排,导致页面突然跳到顶部。 8 | 9 | ```html 10 |
11 | ``` 12 | 13 | ```css 14 | html, body{ 15 | height: 100%; 16 | } 17 | 18 | #url-wrapper{ 19 | margin-top: 51px; 20 | height: 100%; 21 | } 22 | 23 | #url-wrapper iframe{ 24 | height: 100%; 25 | width: 100%; 26 | } 27 | 28 | #url-wrapper.ios{ 29 | overflow-y: auto; 30 | -webkit-overflow-scrolling:touch !important; 31 | height: 100%; 32 | } 33 | 34 | #url-wrapper.ios iframe{ 35 | height: 100%; 36 | min-width: 100%; 37 | width: 100px; 38 | *width: 100%; 39 | } 40 | ``` 41 | 42 | ```javascript 43 | function create_iframe(url){ 44 | 45 | var wrapper = jQuery('#url-wrapper'); 46 | 47 | if(navigator.userAgent.match(/(iPod|iPhone|iPad)/)){ 48 | wrapper.addClass('ios'); 49 | var scrolling = 'no'; 50 | }else{ 51 | var scrolling = 'yes'; 52 | } 53 | 54 | jQuery('