"Webgis Series" Typescript+webgl+webpack Development environment construction

Source: Internet
Author: User

The current mainstream technologies for web-vector rendering include SVG, VML, and WebGL. In contrast, VML is an older technology that, although not a standard, is widely used by earlier IE browsers (IE9) and Microsoft Office, and is now far from the browser battlefield. So there's only SVG and WebGL left to choose from. SVG is a subset of XML, adhering to the principle that a label corresponds to a data, which is often used for Web projects with smaller data volumes, than tables and Metro maps. The data volume of Web vector maps is very large, for example, as shown in a 512px*512px tile, whose data is a two-dimensional array of nearly 5-bit numbers. This tile is simply the simplest of continents and oceans, with a larger amount of data in the same size street map.

Processing a large amount of data must be very demanding in terms of performance, and because of the middle of a browser, the Web map does not fully utilize the CPU's computing power. With a limited amount of CPU resources, if you are able to leverage other computing resources, the WEBGL that can invoke GPU resources becomes the only option.

There are two main reasons why SVG is not suitable for developing web vector maps:

    • Unable to improve performance with GPU;
    • Web maps interact very often, such as moving, zooming, rotating, and so on, and if you use SVG, you need to do it with frequent manipulation of the DOM, and DOM operations are the most performance-consuming behavior of the browser.
Technology selection

After identifying the underlying technology-WEBGL, the next step is to select the appropriate assistive technology, with two points for the target:

    • Javascript
    • Build tools

WebGL rendering has nothing to do with CSS, so the selection of CSS development frameworks has minimal impact on the overall, skipping over.

WebGL can be understood as a variant of OpenGL in a browser environment, preserving the semantics and specifications of OpenGL ES and providing a relatively concise JavaScript API. The vast majority of shader can be shared with WebGL and OpenGL. The language GLSL for developing WEBGL shader is a strongly typed programming language that is syntactically close to C. This is a bit of a tweak for front-end developers who are accustomed to JavaScript. Since it is an adjustment, it may be a complete adjustment: introduce the concept of strong type to the whole development . There are two types of mainstream frameworks that currently support the introduction of strong types in javascript: Typescript and Flow.js. Typescript is a strongly-typed superset of JavaScript, and flow is closer to a type annotation or annotation tool. By contrast, the cost of introducing flow is lower, and you are free to decide which files to turn on or off type checking, just add a line of comments at the top of the file:

// @flow

So flow is ideal for migrating existing projects, and if you use typescript, you need to rewrite all of your source code. Fortunately, the current project does not have a historical burden, so this advantage of flow is not a decisive factor in technology selection.

The reasons for the final selection of typescript are as follows:

    • Grammar is more rigorous even some cumbersome, but the habit is very handy;
    • Rich in ecology, most mainstream third-party libraries now offer typescript support.

ES6 formally introduced the typed array standard, but before ES6, the browser that supports WebGL already provides a strongly typed array of APIs to improve computational performance.

The choice of building tools is relatively more, Webpack, Rollup, gulp are very good tools. The reason for the final selection of Webpack is very simple: relatively cooked.

Build configuration

The Webpack configuration is roughly the same as a regular Web project, with two points to note:

    • The cooperation between Typescript and Babel
    • The construction of shader
Typescript&babel

The typescript itself supports compiling to ES5 or ES3, and tsconfig.json the upcoming compilation selection target is modified to "es5"/"es3" :

{  "compilerOptions": {    "target": "es5"  }}

typescript compiler for the translation function of the syntax specification can satisfy most of the ES6 new functions, but its function of the comprehensiveness compared Babel still some shortcomings, so in order to more precise control of the compilation, the project adopted in the program is typescript first translated into ES6 syntax, Again with the help of Babel to translate it to ES5, the tsconfig.json setting in the compilerOptions.target set to "es6" , Webpack configuration is as follows:

module: {    rules: [{      test: /\.ts$/,      exclude: /node_modules/,      use: ['babel-loader','awesome-typescript-loader']    }}

Webpack compiled typescript loader There are two: ts-loader and awesome-typescript-loader . The final reason for choosing the latter is not because it has a name awesome , but rather to awesome-typescript-loader provide some more convenient features, such as a alias-alias, relative to the former.

If the directory structure of the source code is more complex, referencing a module may require a long path name, such as:

import Utils from '../../../utils';

To make the code more readable, we often use some tools to set the module's reference to a shorter alias. Webpack also has this feature, by resolve Configuring the alias of the module:

resolve: {  alias: {    'utils': path.resolve(__dirname,'src/utils')  }}

Unfortunately ts-loader and awesome-typescript-loader can not directly use the Webpack alias configuration, the source code directly using the module alias will throw an not found error, please note that this error is typescript compiler thrown rather than webpack. The solution is simple: tsconfig.json Configure the module alias in. As follows:

{  "paths": {    "utils/*": ["src/utils/*"]  }}

But this is not the final solution, because if used ts-loader as Webpack integration, Webpack cannot get tsconfig.json the alias configuration, that is, Webpack will throw an not found error. A awesome-typescript-loader good solution to this problem, it can tsconfig.json map the alias configuration to Webpack resolve.alias . Of course, if you still insist on using ts-loader it can be solved, if you are not afraid of trouble: in the Webpack manual configuration of the same resolve.alias .

It is also important to note that the awesome-typescript-loader corresponding plugins need to be created in the Webpack resolve :

const TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;module.exports = {  module: {    rules: [{      test: /\.ts$/,      exclude: /node_modules/,      use: ['babel-loader','awesome-typescript-loader']    },    // other rules    ]  },  resolve: {    plugins: [      new TsConfigPathsPlugin({        configFileName: Path.resolve(__dirname,'../tsconfig.json')      })    ]  }}
Shader

The process for WebGL to create shader is:

    1. First, create a shader instance of the specified type;
    2. Bind the shader source code with the instance;
    3. Compile the shader.

The sample code is as follows:

const source = `precision mediump float;attribute vec2 a_pos;uniform vec4 u_color;uniform vec2 u_resolution;uniform vec2 u_translate;varying vec4 v_color;void main() {    vec2 real_poistion = (a_pos+u_translate) / u_resolution * 2.0 - 1.0;    gl_Position = vec4(real_poistion * vec2(1, 1), 0, 1);    v_color = u_color;}`;// 创建shader实例const Shader = gl.createShader(gl.VERTEX_SHADER);// 绑定shader源码gl.shaderSource(Shader,source);// 编译gl.compileShader(Shader);

The source code of shader is bound to the shader instance in the form of a string, that is, regardless of shader source code is written in what programming language (such as can be written in the above code with a JavaScript string, can also be written directly in GLSL language), Be sure to introduce the shader source module in the form of a string. Adhering to this principle, the simplest shader build scenario is the string form in the code above. For example, the above example code in the shader source separately extracted as vertex.js follows:

export default `precision mediump float;attribute vec2 a_pos;uniform vec4 u_color;uniform vec2 u_resolution;uniform vec2 u_translate;varying vec4 v_color;void main() {    vec2 real_poistion = (a_pos+u_translate) / u_resolution * 2.0 - 1.0;    gl_Position = vec4(real_poistion * vec2(1, 1), 0, 1);    v_color = u_color;}`;

Then introduce the following in the main file:

import VertexShaderSource from './vertex.js';// 创建shader实例const Shader = gl.createShader(gl.VERTEX_SHADER);// 绑定shader源码gl.shaderSource(Shader,VertexShaderSource);// 编译gl.compileShader(Shader);

The advantage of this notation is that no configuration is required for Webpack, but it is tantamount to abandoning the IDE's accessibility to GLSL syntax highlighting, error correcting, and so on. If there are only a few lines of shader source code is not a big problem, but for a few hundred lines of coding if there is no highlighting AIDS can seriously affect the development efficiency.

There are two ways to solve this problem:

    • Enable Webpack to compile GLSL code correctly;
    • Enables typescript to fuse the GLSL module with the TS module.

The first problem is well solved, because our goal is to introduce the GLSL module into the JS module and use it as a string, so webpack to do is to build GLSL source code as a string:

{  test: /\.glsl$/,  loader: 'raw-loader'}

raw-loaderThe function is to convert the introduced file contents to a string.

In addition to the development paradigm shift brought by strong typing, the biggest problem with typescript is that it is not possible to automatically identify any type of module other than TS, even the most common JSON. For example, the following code will report an error in the typescript environment not found :

import Data from '../data.json';

This is the time to use the Typescript declaration file. The function of declaring a file is simply to tell the typescript compiler some necessary information to be correctly identified. For example, declare some global types (type), interfaces (interface), modules, and so on.

By default, the Typescript compiler automatically recognizes the source code and node_modules @types the declaration files within folders in the directory, or you can tsconfig.json specify the compilerOptions.typeRoots file directory in the configuration. For the above mentioned Typescript does not recognize the GLSL and JSON module problems, we create a declaration file in the source directory @types folder global.d.ts , the contents are as follows:

declare module '*.glsl';declare module '*.json';declare type WidthAndHeight = {  width: number;  height: number;};

Three messages are declared in the code above:

    • A glsl file that declares a suffix type is a recognizable module;
    • A json file that declares a suffix type is a recognizable module;
    • Declares a global type WidthAndHeight , which will be used directly in any source file.

On the basis of the above configuration there is also a note: Unlike ES6 modules, Typescript introduces declare a non-TS module that does not automatically convert its contents to the default export, that is export default . For example, a JSON file is introduced in the ES6 environment:

import JsonData from './data.json';

In the typescript environment, the following syntax is required:

import * as JsonData from './data.json';
Sample code

Specific code can refer to the demo:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.