资讯专栏INFORMATION COLUMN

写了十年JS却不知道模块化为何物?

LittleLiByte / 2698人阅读

摘要:于是模块化的需求也就产生了。现存的规范还真不少,不知道能否终结这场混战和分别是和定义的标准。是使用的模块化标准。的模块化声明的方式与类似,只是更进一步,天然隔离了命名空间。其他,关于前端化趋势模块化意味着什么更强大的前端,技术整体前移。

作者:肖光宇
野狗科技联合创始人,先后在猫扑、百度、搜狗任职,爱折腾的前端工程师。
野狗官博:https://blog.wilddog.com/
野狗官网:https://www.wilddog.com/
公众订阅号:wilddogbaas

转载请保留以上信息。


模块化这个问题并非一开始就存在,WWW刚刚问世的时候,html,JavaScript,CSS(JS和CSS都是后来在网景被引进浏览器的)都是极其简单的存在,不需要模块化。

模块化的需求是规模的产物,当web page进化到web application,浏览器端处理的逻辑越来越复杂,展现的样式和动画越来多,对于工程的要求也就越来越高。于是模块化的需求也就产生了。模块化的意义:

组件的复用,降低开发成本和维护成本

组件多带带开发,方便分工合作

模块化遵循标准,方便自动化依赖管理,代码优化,部署

JavaScript长久以来被认为是简单的脚本语言,实际上情况早就发生来变化,在最新版的ECMA-262(ES6)文档中强调JavaScript是通用编程语言而不是脚本语言。脚本语言,比如shell并不是用来完成复杂功能的,只是用来做一些自动化控制,是不需要模块化的。而用于构建复杂系统通用编程语言(比如Java)一般都有模块的实现。

1.模块化标准

ES6之前,JavaScript并没有原生的模块机制,好在JavaScript非常灵活,有很多种写法可以将代码天然隔离,起到模块化的功能:

//define
var modules = {}  
modules.mod1 = {  
  foo : function(){...},
  bar : function(){...}
  ...
}
//call
modules.mod1.foo()  

在客户端这种方式基本是够用的,然而问题依然存在:你无法管理依赖,所有的代码都必须load到内存中,需要哪些模块必须由人工处理。分模块是工程化的产物,也是自然发展的结果,自然有很多尝试。很显然,模块之间互相依赖需要编写模块的时候遵循一定的规范。现存的规范还真不少,不知道ES6 能否终结这场混战:

AMD

CMD

closure

CommonJS

ES6

AMD和CMD分别是requireJS和seaJS定义的标准。使用纯原生的ES5语法意味者其只能使用闭包,书写和阅读都很怪异。值得一提的是AngularJS也使用类似的方式,以至于Angular的作者们都受不了,决定在AngularJS 2 使用新的语言AtScript,前端轮子太多,又造了一个,好在这个轮子造的比较好,兼容ES6 TypeScript规范,扯的远了,看看AMD长得啥样:

AMD:

define(["./a", "./b"], function(a, b) {  
  ...
})

Closure是google出品的前端工具,Closure提供了一系列工具和库,谷歌自己的多个项目都是使用Closure开发的。closure compiler通过模块间依赖的声明把所有被依赖的文件打包到一起,而且Closure的一大优势是如果采用破坏性压缩(ADVANCED)压缩率极高。

//文件A
goog.provide("module1")  
com.foo.bar = {  
   ...
}
....

//文件B
goog.require("module1")  
var a = com.foo.bar;  

然而Closure并不完美,不同的文件共享同一个全局对象,所以你不得不这样写 a.b.c=...。

CommonJS是Node.js使用的模块化标准。Node.js对于前端开发者来说不仅仅可以提供一个Server,还是一个完美的开发平台,在Node上使用Grunt/gulp构建web项目是件很爽的事情。Node的模块化声明的方式与Closure类似,只是更进一步,天然隔离了命名空间。上面的代码如果使用CommonJS的模块化规范可以这么写

//文件A
module.exports = {...}  
....

//文件B
var a = require("./foo/bar")

browserify让使用CommonJS模块化规范的代码可以运行在客户端上。(browserify原理分析)

2.静态加载与动态加载

在看ES6之前我们先看模块加载的两种方式:

静态加载:在编译阶段进行,把所有需要的依赖打包到一个文件中

动态加载:在运行时加载依赖

AMD标准是动态加载的代表,而CommonJS是静态加载的代表。AMD的目的是用在浏览器上,所以是异步加载的。而NodeJS是运行在服务器上的,同步加载的方式显然更容易被人接收,所以使用了CommonJS。同样的道理,如果静态加载,那就使用同步的加载方式,如果动态加载就必须用异步的加载方式。

那么ES6采用何种加载机制?

ES6既希望用简单的声明方式来完成静态加载,又不愿放弃动态加载的特性,而这两种方式几乎不可能简单的同时实现,所以ES6提供了两种独立的模块加载方法。

2.1 声明的方式

import {foo} from module1  

2.2 通过System.import API的方式

System.import("some_module")  
    .then(some_module => {
        // Use some_module
    })
    .catch(error => {
        ...
    });

再看下export的语法,与CommonJS很像,只不过没有了module这个对象,而直接调用export。 可以export任何一个 函数,变量,对象

//expt.js
export function abc(){}//export 一个命名的function  
export default function(){} //export default function  
export num=123 //export 一个数值  
export obj={}  
export { obj as default };

//import
import expt from "expt"//default export  
import {default as myModule} from "expt" //rename  
import {abc,num,obj} from "expt" 

更多细节可以看这篇文章:http://www.2ality.com/2014/09/es6-modules-final.html

目前来看,使用预编译的方式显然要好于使用动态加载,浏览器对ES6语法支持还很差,如果使用动态加载ES6,在浏览器端要做ES6到ES5的翻译工作,这个显然是重复低效的。但是随着浏览器对ES6支持增强,尤其是浏览器实现了动态加载API后,动态加载的优势就会展现:

更流畅的用户体验,动态加载可以实现类似lazyload的加载方式,将download的时间分散

更简洁的项目,无需预编译,项目可以少配置很多工具

HTTP/2的普及更倾向于使用多个小的请求,适合动态加载

3.实践

如果现在使用ES6,可以选择动态加载模块system.js 或者browserify的预编译方法。

使用system.js+babel动态加载依赖。system.js 是ES6动态模块加载的一个实现。写了一个小DEMO:

项目初始化

bower install babel system.js --save 

index.html

...
    

    

...

main.js

export default {  
  sayHello : function(){
    console.log("hello")
  }
}

项目的地址在: https://github.com/stackOverMind/demo-system.js

使用gulp+browserify+babel预编译。gulp是一个Node.js平台上的任务管理平台。预编译要做很多配置,非常繁琐,推荐使用yeoman来生成项目骨架。比如使用generator-es6-webapp。

生成非常简单,在项目目录中执行

yo es6-webapp  

缺少依赖的化安装依赖就好。

4.其他,关于前端化趋势

ES6模块化意味着什么?

更强大的前端,Web技术整体前移。HTML5的发展和某些优秀浏览器的支持让web技术整体前移,以前像渲染这种工作在后端进行是由于浏览器薄弱,且有老IE这种拖后腿捣乱的选手。

简化编程模型,人工管理JS依赖和将多个JS打包这种工作可以不需要了,而配合WebComponents标准,开发Web将不再借助模板引擎和预编译引擎。

前端化还有更深远的影响--在过去浏览器是个工具,现在浏览器是个重要的工具,在未来浏览器就是用户唯一的操作系统。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86170.html

相关文章

  • 中国云计算十年,期待“少年郎”

    摘要:而在中国,云计算也经历了十年来风起云涌的发展历程。在季昕华看来,中国云计算将进入指数级的增量市场,优秀的企业将在千淘万漉之后脱颖而出。他认为就中国来看,从年进入云计算行业到现在,年间,已经沉淀了一批比较优秀的云计算企业。十年之前,云计算还属于一门曲高和寡的新兴技术,从认识到认可,随着云计算技术发展与应用的普及,也带来了更大的市场潜力。来自Gartner的数据显示,到2021年,全球公共云服务...

    lunaticf 评论0 收藏0
  • 2019年云计算将进入“成人时代”

    摘要:去年,预测,云计算将从根本上加速全球企业的数字化转型。该公司预测,到年,云计算将迎来成人时代,为企业应用程序带来创新的开发服务,而不仅仅是提供更便宜的临时服务器和存储。年,云计算将坚定地确立自己的地位,并成为未来企业应用平台的基础设施。去年,Forrester预测,云计算将从根本上加速全球企业的数字化转型。云计算为中小企业的成功提供了十年的动力,并为创新性企业与全球巨头开展竞争提供了所需的工...

    WelliJhon 评论0 收藏0
  • 学习Python编程的书籍Top7

    摘要:关于作者是软件基金会的成员,也是巴西第一个黑客空间的联合创始人。他曾在巴西媒体,银行和政府部门教授开发,并在,,和上发表演讲。他是一位自学成才的程序员,也是使用学习编程一系列书的作者。 showImg(https://segmentfault.com/img/remote/1460000018926735); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slogan | ...

    ccj659 评论0 收藏0
  • 十五年了,蚂蚁为何执着攻坚这两个技术堡垒?

    摘要:阿里妹导读近日,蚂蚁金服副胡喜应邀做了蚂蚁金服十五年技术架构演进之路的演讲,分享蚂蚁金服对金融科技未来的判断,并首次对外公开蚂蚁金服技术人才培训体系以及项目。 showImg(https://segmentfault.com/img/remote/1460000019158592); 阿里妹导读:近日,蚂蚁金服副CTO 胡喜应邀做了《蚂蚁金服十五年技术架构演进之路》的演讲,分享蚂蚁金...

    terasum 评论0 收藏0
  • 十五年了,蚂蚁为何执着攻坚这两个技术堡垒?

    摘要:阿里妹导读近日,蚂蚁金服副胡喜应邀做了蚂蚁金服十五年技术架构演进之路的演讲,分享蚂蚁金服对金融科技未来的判断,并首次对外公开蚂蚁金服技术人才培训体系以及项目。 showImg(https://segmentfault.com/img/remote/1460000019158592); 阿里妹导读:近日,蚂蚁金服副CTO 胡喜应邀做了《蚂蚁金服十五年技术架构演进之路》的演讲,分享蚂蚁金...

    ymyang 评论0 收藏0

发表评论

0条评论

LittleLiByte

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<