前端工程化概述

前端工程化概述

什么是工程化

定义

  • 工程化即系统化、模块化、规范化的一个过程。
  • 如果说计算机科学要解决的是系统的某个具体问题,或者更通俗点说是面向编码的,那么工程化要解决的是如何提高整个系统生产效率。
  • 与其说软件工程是一门科学,不如说它更偏向于管理学和方法论。

解决什么问题

  • 工程化解决的问题是,如何提高编码、测试、维护阶段的生产效率。

什么是前端

*

前端Front-end和后端back-end是描述进程开始和结束的通用词汇。

前端作用于采集输入信息,后端进行处理。计算机程序的界面样式,视觉呈现属于前端。

百度百科

前端对于网站来说,通常是指,网站的前台部分包括网站的表现层和结构层。

因此前端技术一般分为前端设计和前端开发,前端设计一般可以理解为网站的视觉设计,
前端开发则是网站的前台代码实现,包括基本的HTML和CSS以及JavaScript/ajax,现在最新的高级版本HTML5、CSS3,以及SVG等。

__

前端发展史

1. 简单明快的早期时代

适合小项目,不分前后端,页面由JSP、PHP等在服务端生成,浏览器负责展现。

前端工程化概述

2. 后端为主的 MVC 时代

为了降低复杂度,以后端为出发点,有了Web Server层的架构升级,比如Structs、Spring MVC等。

前端工程化概述

前两个阶段存在的问题
  1. 前端开发重度依赖开发环境。
  2. 前后端职责依旧纠缠不清,可维护性越来越差。

3. Ajax 带来的 SPA 时代

2005年Ajax正式提出,前端开发进入SPA(Single Page Application 单页面应用)时代。

前端工程化概述

Ajax时代面临的挑战
  1. 前后端接口的约定。
  2. 前端开发的复杂度控制。SPA应用大多以功能交互型为主,大量 JS 代码的组织,与 View 层的绑定等,都不是容易的事情。

4. 前端为主的 MVC、MV* 时代

为了降低前端开发复杂度,Backbone、EmberJS、KnockoutJS、AngularJS、React、Vue等大量前端框架涌现。

前端工程化概述

5. Node 带来的全栈时代

随着Node.js的兴起,为前端开发带来一种新的开发模式。

业界比较出名的实践是,阿里巴巴的中途岛计划。

前端工程化概述

后两个步骤带来的好处
  1. 前后端职责很清晰。
  2. 前端开发的复杂度可控,通过合理的分层,让项目更可维护。
  3. 部署相对独立,产品体验可以快速改进。

前端工程化要解决什么

1. 制定各项规范,让工作有章可循

  1. 统一团队成员的编码规范,便于团队协作和代码维护

    • 目录结构,文件命名规范
    • 编码规范:eslint, stylelint
  2. 开发流程的规范

    • 使用敏捷,增强开发进度管理和控制
    • 应对各项风险,需求变更等
    • code review 机制
    • UAT 提升发布的需求的质量
  3. 前后端接口规范,其他文档规范

2. 使用版本控制工具,高效安全的管理源代码

  • 使用 git 版本控制工具
  • Git分支管理
  • Commit描述规范,例如:task-number + task 描述
  • 创建 merge request,code review 完毕之后方可合并代码

3. 使用合适的前端技术和框架,提高生产效率,降低维护难度

目标: 职责分离、降低耦合,增强代码的可读性、维护性和测试性。


  1. 采用模块化的方式组织代码

    • JS 模块化:AMD、CommonJS、UMD、ES6 Module
    • CSS 模块化:less、sass、stylus、postCSS、css module
  2. 采用组件化的编程思想,处理 UI 层

    • react、vue、angular
  3. 将数据层分离管理

    • redux、mbox
  4. 使用面向对象或者函数编程的方式组织架构

4. 提高代码的可测试性,引入单元测试,提高代码质量

5. 通过使用各种自动化的工程工具,提升整个开发、部署效率


JavaScript 对模块化的现实需要

  • js设计之初,主要用于处理简单的页面效果和逻辑验证之类的简单工作。
  • 被过于随意的设计,缺乏模块化一直是其缺陷之一。
  • 随着单页应用与富客户端的流行,不断增长的代码库也急需合理的代码分割与依赖管理的解决方案,这就是我们在软件工程领域所熟悉的模块化。
  • 模块化主要解决的问题:解决代码分割、增强维护性、提高代码重用、作用域隔离、模块之间的依赖管理、发布的自动化打包与处理等多个方面。

主要的模块化方案

  • 直接声明依赖(Directly Defined Dependences)
  • 命名空间(Namespace Pattern)
  • 模块模式(Module Pattern)
  • 依赖分离定义(Detached Dependency Definitions)
  • 沙盒(Sandbox)
  • 依赖注入(Dependency Injection)
  • 标签化模块(Labeled Modules)
  • CommonJS、AMD、UMD、ES 2015 Modules
1. 直接声明依赖

除了备注描述,什么问题都没解决

// file app.js
var helloInLang = {
  en: 'Hello world!'
};

// file hello.js

/* helloInLang defined in app.js */
function writeHello(lang) {
  document.write(helloInLang[lang]);
};
2. 命名空间

命名空间模式始于2002年,使用特殊的约定命名,用于避免命名冲突和全局作用域污染。

缺点:大型项目可维护性较差,没有解决模块间依赖管理的问题。

// file app.js
var app = {};

// file greeting.js
app.helloInLang = {
  en: 'Hello world!'
};

// file hello.js
app.writeHello = function (lang) {
  document.write(app.helloInLang[lang]);
};
3. 模块模型

封装了变量和function,和全局的namaspace不接触,松耦合

只暴露可用public的方法,其它私有方法全部隐藏

// file app.js
var app = {};

// file greeting.js
app = (function (app) {
    var _app = app || {};

    _app.helloInLang = {
      en: 'Hello world!'
    };

    return _app;
} (app));

// file hello.js
app = (function (app) {
    var _app = app || {};

    _app.writeHello = function (lang) {
      document.write(app.helloInLang[lang]);
    };

    return _app;
} (app));
4. 依赖注入

2009年 Angular 引入 Java 世界的依赖注入思想。

核心思想:某个模块不需要手动初始化某个依赖对象,只需要声明该依赖,并由外部框架自动实例化该对象,并传递到模块内。

// file greeting.js
angular.module('greeter', [])
  .value('greeting', {
    helloInLang: {
      en: 'Hello world!'
    },
    ayHello: function(lang) {
      return this.helloInLang[lang];
    }
  });

// file app.js
angular.module('app', ['greeter'])
  .controller('GreetingController', ['$scope', 'greeting', function($scope, greeting) {
    $scope.phrase = greeting.sayHello('en');
  }]);
5. CommonJS

服务器端 javascript 模块化解决方案,适用于同步模块加载。

// file greeting.js
var helloInLang = {
    en: 'Hello world!'
};
var sayHello = function (lang) {
    return helloInLang[lang];
}
module.exports.sayHello = sayHello;

// file hello.js
var sayHello = require('./lib/greeting').sayHello;
var phrase = sayHello('en');
console.log(phrase);
6. AMD

浏览器端 javascript 模块化解决方案,适用于异步模块加载。

// file lib/greeting.js
define(function() {
    var helloInLang = {
        en: 'Hello world!'
    };

    return {
        sayHello: function (lang) {
            return helloInLang[lang];
        }
    };
});

// file hello.js
define(['./lib/greeting'], function(greeting) {
    var phrase = greeting.sayHello('en');
    document.write(phrase);
});
7. UMD

UMD 允许在环境中同时使用 AMD 与 CommonJS 规范。

(function(define) {
    define(function () {
        var helloInLang = {
            en: 'Hello world!'
        };

        return {
            sayHello: function (lang) {
                return helloInLang[lang];
            }
        };
    });
}(
    typeof module === 'object' && module.exports && typeof define !== 'function' ?
    function (factory) { module.exports = factory(); } :
    define
));
8. ES2015 Modules

ES2015 Modules 作为 JavaScript 官方标准,日渐成为了开发者的主流选择。

// file lib/greeting.js
const helloInLang = {
    en: 'Hello world!'
};

export const greeting = {
    sayHello: function (lang) {
        return helloInLang[lang];
    }
};

// file hello.js
import { greeting } from "./lib/greeting";
const phrase = greeting.sayHello("en");
document.write(phrase);

增强可测试性

  1. 采用tdd的编程思想,引入单元测试

    • karma + mocha + chai、jest、ava
  2. 使用各种调试工具

    • web devtools、finddle

自动化工程工具的使用

  1. 使用前端构建工具

    • gulp、grunt、Broccoli
  2. javascript 编译工具

    • Babel、Browserify、Webpack
  3. 开发辅助工具

    • 数据 mock、livereload
  4. 使用CI集成工具

    • jenkins、Travis CI
  5. 使用脚手架工具

    • yeoman、create-app

客如云前端工程化实践

统一公司前端技术栈,根据职责创建不同项目。

  1. kryfe-boilerplate 脚手架项目
  2. kryfe-tools 通用工具库
  3. kryfe-lib 通用类库
  4. kryfe-component 公共组件库
  5. eslint-config-kryfe eslint规范
  6. stylelint-config-kryfe stylelint规范
  7. kryfe-docs 各种规范文档
  8. kryfe-style PC端样式库

参考资料

上一篇:处理同一页面中借助form+input[type="file"]上传图片出现的input无法清空问题


下一篇:HTML5实践 -- 如何使用css3完成google涂鸦动画