前端的模块化开发也经历过很长时间的发展, 今天来对模块化的发展和使用进行总结,加深理解和记忆。
模块化开发
- JS模块化
- 命名空间
// 库名.类别名.方法名=>解决命名冲突的问题 var NameSpace = {} NameSpace.type = NameSpace.type || {} NameSpace.type.method = function () { }
- 标准的模块化方案
- 服务器node端:common.js
// 一个文件一个模块:通过 module.exports 暴露模块接口,通过 require 引入模块,同步加载。 var http = require('http'); // Expose `createApplication`; exports = module.exports = createApplication;
- 浏览器端:
- AMD(require.js)
- common.js所有的模块是同步加载,服务端由于都是本地文件可以承受这样的一个加载开销,而我们的浏览器端呢?如果要求用户来承担这一个同步加载所有模块的开销,一定会影响到用户的浏览网页的速度。AMD 正是为了解决这一点而生。
- 特点:依赖前置,提前执行Async Module Definition
- define定义模块,require加载模块
- 一个文件一个模块
define( // 模块名 "alpha", // 依赖 ["require","exports","beta"], // 模块输出 function (require, exports, beta) { exports.verb = function () { return beta.verb(); //Or; return require("beta").verb(); } } ) // 省略模块名 define( ["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { // 相当于提前声明了要使用的模块 if (false){ // 即使在调用中没有用到,单还是提前执行 b.foo() } } )
- CMD(sea.js)
- Common Module Definition 通用模块定义
- define定义模块,require加载模块
- 一个文件一个模块
- 尽可能的懒执行
// define模块定义 define(function(require, exports, module) { // 通过require 引入依赖 var $ = require('jquery'); var Spinning = require('./spinning'); // 通过 exports 对外提供接口 exports.doSomething = ... // 或者通过module.exports对外提供整个接口 module.exports = ... // exports只不过是对 module.exports的引用,同时存在时起作用的是module.exports })
- UMD
- Universal Module Definition(通用解决方案)
- 三个判断
- 判断是否支持 AMD
- 判断是否支持 CommonJS
- 判断是否支持 CommonJS
// if the module has no dependencies, the above pattern can be simplified to (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD Register as a anonymous modules. define([], factory); }else if (typeof exports === 'object') { // Node does not work with strict Common.js, but only CommonJS-like environments that support module.exports,like node module.exports = factory(); }else { root.returnExports = factory(); } }(this, function () { // just return a value to define the module export.This example returns an object, but module can return a function as the exported value. return {}; }))
- ES6模块化
- export/import 导出/导入模块
- 一个模块一个文件
// Default exports and named exports import theDefault, {named1,named2} from 'src/mylib'; // equal import theDefault from 'src/mylib'; import {named1, named2} from 'src/mylib'; // Renaming: import named1 as myNamed1 import {named1 as myNamed1,named2} from 'src/mylib'; // import the module as an object // (with on property per named export) import * as mylib form 'src/mylib'; // only load the module, don't import anything import 'src/mylib';
// export defined variable export var myVar1 = ''; export let myVar2 = ''; export const MY_CONST = ''; // export method export function myFunc() { } export function* myGeneraorFunc() { } export class MyClass {} // export default content from the module export default 123; export default function (x) { return x; } export default x=>x; export default class { constructor(x,y) { this.x = x; this.y = y; } } // common use const MY_CONST = ''; function myFunc() { }; export {MY_CONST, myFunc}; export {MY_CONST as CONST, myFunc as Func}; export * from 'src/other_module'; export {foo, bar} from 'src/other_module'; export {foo as myFoo, bar} from 'src/other_module';
- AMD(require.js)
- 服务器node端:common.js
- 命名空间
- css模块化
- OOCSS
- OOCSS是object-oriented CSS的缩写. 主要有两个意思:结构和设计分离,容器和内容分离,使用这种结构, 开发人员获得可以在不同地方使用的CSS类.
- 优点:通过复用来减少代码量(DRY原则)
- 缺点:维护非常困难(复杂). 当你修改某一个具体的元素的样式的时候, 大部分情况下, 除了修改CSS本身(因为多数的CSS类是通用的), 你还不得不添加更多的标记类(markup).
- SMACSS
- SMACSS是可扩展和模块化结构CSS的简称. 该方法的主要目标是减少代码量并简化代码维护.
- Jonathan Snook把它归纳为5个部分:
- 基本规则(Base rules): 这些是网站的主要元素的样式, 如body, input, button, ul, ol等. 在这一步中我们主要使用HTML标签和属性选择器, 在特殊情况下, 使用CSS类(如: 如果您有JavaScript-Style选择);
- 布局规则(Layout rules): 主要是些全局元素, 顶部, 页脚, 边栏等模块的大小. Jonathan建议使用ID选择器, 因为这些模块不太可能在同一个页面上出现多次. 然而, 本文作者认为这是个很不好的习惯(每当ID出现在样式文中, 感觉世界顿时变得灰暗, 有一股莫名的哀伤).
- 模块规则(Modules rules): 模块(类似于卡片布局)可以在一个页面中使用多次. 对于模块CSS类, 不建议使用ID和tag选择器(这是为了方便重用以及上下文独立).
- 状态规则(State rules): 在这一步中, 规定了模块的各种状态以及网站的基础部分. 这是唯一允许使用”!important”的地方.
- 主题规则(Theme rules): 设计您可能需要更换的样式.
- Atomic CSS
- Atomic CSS是CSS架构的一种方法, 它的好处是写出基于视觉功能的小的, 单用途CSS类.
- 使用Atomic CSS, 为每个可重用的属性创建单独的CSS类. 例如, margin-top: 1px; 就可以创建一个类似于mt-1的CSS类, 或者width: 200px; 对应的CSS类为w-200.这种样式允许您通过重用声明来最大程度地减少您的CSS代码数量, 并且也能很轻松的更改模块, 例如, 更改以技术任务时.
- CSS类名是属性名称的描述, 而不是元素的自然语义. 这种想象很容易使人在开发过程中变得迷茫. 开发本身也十分容易复杂化.直接在HTML中进行显示设置.
- MCSS
- 将css进行分层化
- BEM
- Block:header, container, menu, checkbox, input=>代表块
- Element:menu item, list item, checkbox caption, head title=>块内容
- Modifier:disabled, highlighted, checked, fixed, size big, color red=>状态
- CSS Modules
import styles from './style.css'; element.innerHTML = '<div class="' + styles.className + '">';
.className { color: green; } .style_className_1FU0U { color: green; }
- OOCSS