前端模块化总结

前端模块化总结

Posted by SkioFox on November 7, 2017

前端的模块化开发也经历过很长时间的发展, 今天来对模块化的发展和使用进行总结,加深理解和记忆。

模块化开发

  • 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)
          1. common.js所有的模块是同步加载,服务端由于都是本地文件可以承受这样的一个加载开销,而我们的浏览器端呢?如果要求用户来承担这一个同步加载所有模块的开销,一定会影响到用户的浏览网页的速度。AMD 正是为了解决这一点而生。
          2. 特点:依赖前置,提前执行Async Module Definition
          3. define定义模块,require加载模块
          4. 一个文件一个模块
             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)
          1. Common Module Definition 通用模块定义
          2. define定义模块,require加载模块
          3. 一个文件一个模块
          4. 尽可能的懒执行
                 // 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
          1. Universal Module Definition(通用解决方案)
          2. 三个判断
            • 判断是否支持 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模块化
          1. export/import 导出/导入模块
          2. 一个模块一个文件
                 // 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';
            
            
  • css模块化
    • OOCSS
      • OOCSS是object-oriented CSS的缩写. 主要有两个意思:结构和设计分离,容器和内容分离,使用这种结构, 开发人员获得可以在不同地方使用的CSS类.
      • 优点:通过复用来减少代码量(DRY原则)
      • 缺点:维护非常困难(复杂). 当你修改某一个具体的元素的样式的时候, 大部分情况下, 除了修改CSS本身(因为多数的CSS类是通用的), 你还不得不添加更多的标记类(markup).

      avatar

    • SMACSS
      • SMACSS是可扩展和模块化结构CSS的简称. 该方法的主要目标是减少代码量并简化代码维护.
      • Jonathan Snook把它归纳为5个部分:
        1. 基本规则(Base rules): 这些是网站的主要元素的样式, 如body, input, button, ul, ol等. 在这一步中我们主要使用HTML标签和属性选择器, 在特殊情况下, 使用CSS类(如: 如果您有JavaScript-Style选择);
        2. 布局规则(Layout rules): 主要是些全局元素, 顶部, 页脚, 边栏等模块的大小. Jonathan建议使用ID选择器, 因为这些模块不太可能在同一个页面上出现多次. 然而, 本文作者认为这是个很不好的习惯(每当ID出现在样式文中, 感觉世界顿时变得灰暗, 有一股莫名的哀伤).
        3. 模块规则(Modules rules): 模块(类似于卡片布局)可以在一个页面中使用多次. 对于模块CSS类, 不建议使用ID和tag选择器(这是为了方便重用以及上下文独立).
        4. 状态规则(State rules): 在这一步中, 规定了模块的各种状态以及网站的基础部分. 这是唯一允许使用”!important”的地方.
        5. 主题规则(Theme rules): 设计您可能需要更换的样式.

        avatar

    • Atomic CSS
      • Atomic CSS是CSS架构的一种方法, 它的好处是写出基于视觉功能的小的, 单用途CSS类.
      • 使用Atomic CSS, 为每个可重用的属性创建单独的CSS类. 例如, margin-top: 1px; 就可以创建一个类似于mt-1的CSS类, 或者width: 200px; 对应的CSS类为w-200.这种样式允许您通过重用声明来最大程度地减少您的CSS代码数量, 并且也能很轻松的更改模块, 例如, 更改以技术任务时.
      • CSS类名是属性名称的描述, 而不是元素的自然语义. 这种想象很容易使人在开发过程中变得迷茫. 开发本身也十分容易复杂化.直接在HTML中进行显示设置.

      avatar

    • MCSS
      • 将css进行分层化

      avatar

    • 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=>状态

      avatar

    • CSS Modules
            import styles from './style.css';
            element.innerHTML = '<div class="' + styles.className + '">';
      
            .className {
                color: green;
            }
            .style_className_1FU0U {
                color: green;
            }