模块化JavaScript开发

前端开发的节奏真是日新月异。。。短短几年竟然发展如此迅速,JavaScript 的各种框架库可以说比其他语言的总和还多。Google 家的 AngularJS,和 Facebook 的 React 各领风骚。自己写的前端项目也越来越复杂,单纯的面向过程开发和单文件已经不能满足现有的需求。虽然 ES6 早就引入模块化特性,但是目前的浏览器还没有实现。还需要借助其它前端工具进行编译。。。下面我就顺便介绍下 Web 开发的历史。。。

# Server Rendered

以前开发 Web 项目,全部是服务器来渲染页面,从数据库读入数据,浏览器只负责解释页面,这种情况下不考虑交互性,其实完全不用写任何 JS 代码。但是缺点也很大,处理全部交给服务器,服务器压力大。而且每次都是刷新加载,所以用户体验也不是很好。

# Server-Rendered + AJAX

后来使用 AJAX 无刷新技术,对于简单的登录交互我们没有必要刷新页面,而是直接使用 JS 发送认证数据进行交互和登录。一定程度上减少了服务器的压力。

# Single Page App

后来出现了谷歌的 AngularJS 这样的富客户端 JS 框架,做到了真正的页面和数据分离。全部使用 JavaScript 进行页面的渲染和交互,只向服务器请求必要的数据,并使用 JSON 的数据格式来传输。这样不仅有利于减少服务器压力,而且还可以复用到各种平台。但是 JavaScript 代码变得越来越多和复杂,必须考虑合适的架构和模块化开发才有利于之后的维护。

# Webpack 模块化工具

webpack 模块化工具可以把你写的符合模块化规范的代码进行打包和整合到一个单子文件,这样就可以模块化自己的项目。但是官方文档实在是很难学习,自己琢磨了一段时间才算稍微能上手。并且还遇到点小问题,在此记录下,我们可以使用命令$ npm install webpack -g 安装 webpack.但是我们使用的时候经常还是遇到找不到 webpack 的问题,是因为缺少环境变量NODE_PATH 可以通过设置export NODE_PATH="/usr/lib/node_modules来解决。

# 相关学习资料

webpack 指南 (opens new window)

webpack-howto (opens new window)

WebGL渲染的知识介绍

来到日本导师的研究方向是计算机图形学,由于我比较擅长 Web 开发,便选择了 WebGL 进行图形渲染的研究课题。学习了大半年,也该写点东西介绍下自己对 WebGL 的理解,如有错误,欢迎批评指正。

# WebGL 介绍

WebGL 是基于 OpenGL ES 2.0 文档进行开发的,所以想了解相关 API 的话,直接查阅官方的OpenGL ES 2.0 文档 (opens new window)即可.WebGL 的一大优势是可以使用 GPU 资源来进行图形渲染和相关的计算,但是使用 GPU 资源的话必须使用对于 GPU 友好的语言来进行编写,WebGL 使用GLSL (opens new window)来编写用于 GPU 渲染的着色器。 JavaScript 主要负责整个渲染流程的控制和 GPU 与 CPU 之间的数据交互,繁重的坐标变换计算全部交给 GPU 来处理。

# WebGL 渲染管道

# 获取 WebGL

WebGL 是基于 canvas 画布来进行渲染的,首先我们要使用getContext方法来获取 gl 对象。并判断浏览器是否支持 WebGL.

var gl = null;
try {
  gl = canvas.getContext('experimental-webgl');
  if (gl == null) {
    gl = canvas.getContext('webgl');
  }
} catch (error) {}

if (gl != null) {
  // WebGL is supported
} else {
  // WebGL is not supported
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 顶点着色器

WebGL 只支持绘制基本图元,复杂的图形也是有基本图元组合而成的,基本图元包括点、线段或三角形。三角形是最经常用来使用的,因为 3D 空间中的任何 3 个点都是一个三角形的顶点。顶点着色器一般用写在 HTML 中,并标上 HTML 无法识别的 type,这样浏览器就不会解释执行。 顶点的 X,Y,Z 轴的取值范围全部是-1 到 1 之间,所以要注意变换坐标。

<script id="vs" type="x-shader/x-vertex">
  attribute vec3 position;
  uniform   mat4 mvpMatrix;

  void main(void){
      gl_Position = mvpMatrix * vec4(position, 1.0);
  }
</script>
1
2
3
4
5
6
7
8

前面的 mvpMatrix 矩阵是坐标变换用的,因为我们在实际渲染可能要应用到很多的矩阵变换以渲染到屏幕上。这部分知识可以看看基本的图形学相关书籍,我看的是《DIRECTX.9.0.3D 游戏开发编程基础》,里面介绍了相关的矩阵概念和数学知识。顶点着色器负责绘制图元的顶点信息,接下来就要使用片段着色器绘制相关的颜色信息。

# 片段着色器

片段着色器接收到顶点着色器的顶点信息并在此位置绘制相应的颜色值。颜色的取值范围是 0 到 1.

<script id="fs" type="x-shader/x-fragment">
    void main(void){
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
</script>
1
2
3
4
5

使用片段着色器可以给相应的顶点设置颜色值,在顶点与顶点之间的位置使用插值法设置颜色值。

渲染管道可以参考这张比较形象的流程图:

WebGl Pipeline

# texture

GPU 运算里面有个非常常用的数据结构,那就是 texture,既可以存储图片数据,也可以存储 frame 数据。对于离屏渲染非常重要,不过在 GPU 运算里面非常重要的一点是一个变量不能既作为输入有作为输出。 在 CPU 运算里面我们经常写: a=a+1 但是在 GPU 运算里面是不能这样操作的,需要有一个临时变量存储输出的值,然后再传入到最终变量中。类似于:b=a+1;a=b这样。所以对于动画渲染,我们需要使用两个 framebuffer 相互交换进行渲染。

# 离屏渲染

对于复杂的图形渲染,可能一次描绘无法完成最终效果,这时候我们可以把渲染的中间效果存储到 framebuffer 里面,再下一次渲染的时候继续使用,只需要简单的在渲染之前绑定 framebuffer 即可。

gl.bindFramebuffer(gl.FRAMEBUFFER, Cube.FboHandle);
1

# 相关学习资料

WebGL MDN (opens new window)

WebGL 開発支援サイト (opens new window)

WebGL 入门 (opens new window)

关于JavaScript跨域请求的相关知识

2016 年已经过了 3 个月了,还没来得及更新博客...实在是惭愧惭愧...最近确实也很忙,一边要打工,一边要写论文,一边还要找工作...

最近百度的导出插件出了点小问题,导致很多人无法正常和 Aria2c 通讯.经过仔细的分析,发现问题出在跨域请求上,接下来就要详细说说 JavaScript 的跨域请求.

# JavaScript 跨域请求

跨域请求指得是发起请求的资源所在域不同于该请求所指向资源所在的域的 HTTP 请求.最常见的就是跨域载入图片,我们可以看到很多网站主站和网站所使用的图片 是不同的域名的.这样做的好处是请求图片的时候不会发送主站的 Cookies,因为不同域名嘛.而且还可以减少主站的服务器压力.但载入图片使用的是 GET 方法,比较简单.

# 跨域 POST 请求

我们经常使用 POST 请求发送各种指令数据,因为 POST 发送的数据没有长度限制.我们还可以在发送数据之前修改请求头,发送各种自定义的 HTTP Request Headers.但是 在跨域请求的时候 POST 的请求头被严格限制,被允许设置的请求头只有:

- Accept
- Accept-Language
- Content-Language
- Content-Type
1
2
3
4

并且允许的 Content-Type 只有一下三种:

- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
1
2
3

# Preflighted requests

当我们发送的请求不满足上面的条件时,就必须发送预请求给目的站点,来查明这个跨站请求对于目的站点是不是安全可接受的。以下条件会触发预请求的发送:

  • 请求以 GET, HEAD 或者 POST 以外的方法发起请求。或者使用 POST,但请求数据为 application/x-www-form-urlencoded, multipart/form-data 或者 text/plain 以外的数据类型。比如说,用 POST 发送数据类型为 application/xml 或者 text/xml 的 XML 数据的请求。
  • 使用自定义请求头(例如 Aria2c 的验证使用的 Authorization)

# 结论

本次 BUG 的出现,是由于代码验证不规范,对于不需要用户名和密码验证的 RPC 地址.仍然发送自定义的 Authorization 验证头.导致触发 OPTIONS 请求,但是本身不支持验证的 Aria2c 客户端无法识别 OPTIONS 请求,只能返回 500 错误.导致通讯失败,至此 BUG 分析完毕.

# 参考:

HTTP access control (CORS) (opens new window)

HTTP/1.1: Method Definitions (opens new window)