We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端非常特殊,特殊在由三种语言组成:HTML、CSS、JavaScript。
带来的问题就是资源类型多种多样,随着应用复杂度的提升,资源的类型和数量越来越多:
.html/.css/.js/.json/.svg/.jpg/.png/.less/.scss/.jsx ....
如何管理好这些资源,如何方便地复用,成为业界共同的问题,一路走来,实属不易。
早期的前端极其简单,一段 HTML,少量 CSS 加上少量 JS
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="main.css"> <script src="main.js"></script> </head> <body> <h1>Hello, world!</h1> </body> </html>
这个时期,应用非常简单,依赖的资源很少,所以不需要任何模块化管理方案,HTML 本身就能表示出整个模块的依赖关系。
但是随着应用复杂度的提升,依赖的资源越来越多:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="css/moduleA.css"> <link rel="stylesheet" href="css/moduleB.css"> <link rel="stylesheet" href="css/moduleC.css"> <link rel="stylesheet" href="css/moduleD.css"> <!-- D 依赖 A、B、C --> <script src="js/moduleA.js"></script> <script src="js/moduleB.js"></script> <script src="js/moduleC.js"></script> <script src="js/moduleD.js"></script> <script src="js/main.js"></script> </head> <body> <div class="moduleD"> moduleD html content </div> <div class="moduleD"> moduleD html content </div> </body> </html>
这种情况下暴露出很多问题:
此时,ServerJS 社区(CommonJS 的前称,发展史下阶段介绍)推出的 Modules/1.0 规范在 Node.js 等环境下比较成功
var module = require('./module') // do sth...
于是想在浏览器环境下推广,便将社区改名为 CommonJS,商讨下一版规范,但社区内部分歧较大,产生了三种流派:
AMD 规范一度非常流行,很大程度上解决了模块依赖的问题,典型的实现者 RequireJS 使用方式如下
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="css/moduleA.css"> <link rel="stylesheet" href="css/moduleB.css"> <link rel="stylesheet" href="css/moduleC.css"> <link rel="stylesheet" href="css/moduleD.css"> </head> <body> <div class="moduleD"> moduleD html content </div> <div class="moduleD"> moduleD html content </div> <script src="js/main.js"></script> </body> </html>
moduleD.js
define(['moduleA', 'moduleB', 'moduleC'], function(A, B, C) { // moduleD logic return moduleD })
main.js
require(['moduleD'], function(D) { // do sth... })
相比第一阶段的优势:
但 RequireJS 关注的主要是 JS 模块的管理,关联的其他类型的资源模块仍需手动管理(其实这个不属于 AMD 规范的问题,而是 RequireJS 没有去实现其他类型资源的依赖管理)。
随着 NodeJS 的兴起,写 JS 却用两套规范非常不方便,规范不一致,接口不一致,不利于模块共享。所以干脆在浏览器端也用 CommonJS 规范好了。
浏览器端不支持同步加载 JS,那么就在运行前打包好不就可以了,早期实现者 browserify 使用方式如下:
var moduleA = require('./moduleA.js') var moduleB = require('./moduleB.js') var moduleC = require('./moduleC.js') // moduleD logic module.exports = moduleD
var moduleD = require('./moduleD.js') // do sth...
$ browserify main.js -o bundle.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="css/moduleA.css"> <link rel="stylesheet" href="css/moduleB.css"> <link rel="stylesheet" href="css/moduleC.css"> <link rel="stylesheet" href="css/moduleD.css"> </head> <body> <div class="moduleD"> moduleD html content </div> <div class="moduleD"> moduleD html content </div> <script src="bundle.js"></script> </body> </html>
browserify 实现的仍然是 JS 模块管理,如何管理 CSS、图片、HTML 片段等资源呢?webpack 登场
webpack 可以管理所有类型资源的依赖,开发者再也不需要单独加载 JS 以外的依赖了
var moduleA = require('./moduleA') var moduleB = require('./moduleB') var moduleC = require('./moduleC') require('./moduleD.css') require('./moduleD.tpl') // moduleD logic module.exports = moduleD
var moduleD = require('./moduleD') // do sth...
$ webpack main.js bundle.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <div class="moduleD"></div> <div class="moduleD"></div> <script src="bundle.js"></script> </body> </html>
此时,moduleD 已经上升到组件的概念了,与外部唯一的接口就是DOM容器了。
但是调用组件、组件嵌套组件仍然需要手动与 DOM 树挂钩。
场景一,调用组件 ModuleD:
var ModuleD = require('./moduleD') var containers = document.querySelectorAll('.moduleD') new ModuleD({ el: containers[0] }) new ModuleD({ el: containers[1] })
场景二,ModuleD 嵌套 ModuleE:
moduleD.tpl
<div> <div>Hello, E</div> <div class="moduleE"></div> </div>
var ModuleE = require('./moduleE') new ModuleE({ el: moduleE-element })
使用起来非常繁琐,有没有一个组件化的类库来管理组件呢?比如最终代码可以这样写:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <moduleD> <div>Hello, E</div> <moduleE></moduleE> </moduleD> <moduleD></moduleD> <script src="bundle.js"></script> </body> </html>
其实,Web 组件化的概念早就提出,一些类库如 Polymer、React、Vue 等也已经实现。以 React 为例:
moduleD.jsx
var React = require('react') var ModuleA = require('./ModuleA') var ModuleB = require('./ModuleB') var ModuleC = require('./ModuleC') require('./ModuleD.css') var ModuleD = React.createClass({ render() { return ( <div> <ModuleA /> <ModuleB /> <ModuleC /> </div> ) } }) module.exports = ModuleD
main.jsx
var React = require('react') var ReactDOM = require('react-dom') var ModuleD = require('./ModuleD') var App = React.createClass({ render() { return ( <div> <ModuleD /> </div> ) } }) ReactDOM.render(<App />, document.getElementById('app'))
为什么把 HTML 放在 JS 中?
HTML 严格来说不属于编程语言,无法描述程序逻辑,所以如果要实现必然需要一些程序上的预处理等操作,与其在 HTML 上面附属一堆需要额外学习的逻辑语法:
<thead> <tr> <th v-for="key in columns" @click="sortBy(key)" :class="{active: sortKey == key}"> {{key | capitalize}} <span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"> </span> </th> </tr> </thead>
不如直接用纯粹的 JS 语法去描述。
<tr> {columns.map(function(item) { return <th>{item.name}</th> })} </tr>
也看个人喜好,各个类库设计思路不同罢了。
最终入口:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <div id="app"></div> <script src="bundle.js"></script> </body> </html>
2015年6月,ECMAScript 6 正式发布,终于,JavaScript 有了自己的模块化体系。
目前浏览器不支持,需要一些 transpiler 转换成已有的模块打包工具可识别的语法:
b.js
import a form './a' import './b.css' // do sth... export default b
转换后
var a = require('./a') require('./b.css') // do sth... module.exports = b
技术的发展总是由需求推动的:
前端模块不仅仅是 JS,HTML、CSS、图片等等一切资源都是模块,如何复用资源、如何以最小的成本使用,就是本文的目的。
Modules/1.0 CommonJS AMD
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前端模块化发展史
1 前言
前端非常特殊,特殊在由三种语言组成:HTML、CSS、JavaScript。
带来的问题就是资源类型多种多样,随着应用复杂度的提升,资源的类型和数量越来越多:
.html/.css/.js/.json/.svg/.jpg/.png/.less/.scss/.jsx ....
如何管理好这些资源,如何方便地复用,成为业界共同的问题,一路走来,实属不易。
2 HTML 直接管理
早期的前端极其简单,一段 HTML,少量 CSS 加上少量 JS
这个时期,应用非常简单,依赖的资源很少,所以不需要任何模块化管理方案,HTML 本身就能表示出整个模块的依赖关系。
但是随着应用复杂度的提升,依赖的资源越来越多:
这种情况下暴露出很多问题:
3 AMD 规范
此时,ServerJS 社区(CommonJS 的前称,发展史下阶段介绍)推出的 Modules/1.0 规范在 Node.js 等环境下比较成功
于是想在浏览器环境下推广,便将社区改名为 CommonJS,商讨下一版规范,但社区内部分歧较大,产生了三种流派:
AMD 规范一度非常流行,很大程度上解决了模块依赖的问题,典型的实现者 RequireJS 使用方式如下
moduleD.js
main.js
相比第一阶段的优势:
但 RequireJS 关注的主要是 JS 模块的管理,关联的其他类型的资源模块仍需手动管理(其实这个不属于 AMD 规范的问题,而是 RequireJS 没有去实现其他类型资源的依赖管理)。
4 CommonJS 规范
随着 NodeJS 的兴起,写 JS 却用两套规范非常不方便,规范不一致,接口不一致,不利于模块共享。所以干脆在浏览器端也用 CommonJS 规范好了。
浏览器端不支持同步加载 JS,那么就在运行前打包好不就可以了,早期实现者 browserify 使用方式如下:
moduleD.js
main.js
5 Web Components
browserify 实现的仍然是 JS 模块管理,如何管理 CSS、图片、HTML 片段等资源呢?webpack 登场
webpack 可以管理所有类型资源的依赖,开发者再也不需要单独加载 JS 以外的依赖了
moduleD.js
main.js
此时,moduleD 已经上升到组件的概念了,与外部唯一的接口就是DOM容器了。
但是调用组件、组件嵌套组件仍然需要手动与 DOM 树挂钩。
场景一,调用组件 ModuleD:
场景二,ModuleD 嵌套 ModuleE:
moduleD.tpl
moduleD.js
使用起来非常繁琐,有没有一个组件化的类库来管理组件呢?比如最终代码可以这样写:
其实,Web 组件化的概念早就提出,一些类库如 Polymer、React、Vue 等也已经实现。以 React 为例:
moduleD.jsx
main.jsx
为什么把 HTML 放在 JS 中?
HTML 严格来说不属于编程语言,无法描述程序逻辑,所以如果要实现必然需要一些程序上的预处理等操作,与其在 HTML 上面附属一堆需要额外学习的逻辑语法:
不如直接用纯粹的 JS 语法去描述。
也看个人喜好,各个类库设计思路不同罢了。
最终入口:
6 ES6 模块规范
2015年6月,ECMAScript 6 正式发布,终于,JavaScript 有了自己的模块化体系。
目前浏览器不支持,需要一些 transpiler 转换成已有的模块打包工具可识别的语法:
b.js
转换后
7 总结
技术的发展总是由需求推动的:
前端模块不仅仅是 JS,HTML、CSS、图片等等一切资源都是模块,如何复用资源、如何以最小的成本使用,就是本文的目的。
8 参考
Modules/1.0
CommonJS
AMD
The text was updated successfully, but these errors were encountered: