模块化

模块化

CommonJS ---> AMD ---> CMD ---> UMD ---> ES6Module

CommonJS && node.js

CommonJS规范,一个文件就是一个模块,采用同步加载模块,主要运行于服务端。require用于引入模块,module.exports输出的是值的拷贝

AMD && required.js

AMD规范,一个文件就是一个模块,模块和模块的依赖可以被异步加载,且申明依赖模块时,会第一时间加载并执行模块内的代码,主要用于浏览器。define(id?, dependencies?, factory)用来定义模块,require用于引入其他模块

// mA.js
define(['jQuery', 'lodash'], function ($, _) {
    var name = 'name1'
    return {
        name,
    }
})

// main.js
require(['mA'], function (a) {
    console.log(a.name === 'name1') // => true
})

CMD && sea.js

CMD规范,通用模块定义,可运行于浏览器和node,执行时才加载

UMD && webpack

解决CommonJSAMD不通用问题,同时支持老式的全局变量规范。

ES6 Module && ES6

  • 默认开启严格模式

  • 会生成顶级的词法作用域,顶层的thisundefined

用过import导入,通过export导出,导出的是值的引用

模块循环引用

  • CommonJS:只输出已经执行的部分,还未执行的部分不会输出

  • ES6:不关心是否发生"循环加载",只是生成一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值

webpack

从入口文件开始,识别模块依赖,分析、编译并输出代码。其编译结果为匿名函数,参数是一个对象,对象是包含页面名/eval(页面源码字符串)的键值对。总的来说,webpack利用node将源码转义当作字符串放入eval()中,然后自己创建一个浏览器对象,并对这个对象进行处理,使其符合commonjs规范,最后根据规范调用编译好的字符串。

构成

  • entry:入口,webpack构建的开始

  • module:模块

  • chunk:代码块

  • loader:模块转换器

  • plugin:插件

构建流程

  1. 初始化:从配置文件或shell读取或合并得到最终的配置参数,实例化插件new Plugin()

  2. 开始编译:初始化Compiler对象、加载插件,通过执行Compiler.cun开始编译

  3. 确定入口:根据entry找出所有入口文件

  4. 编译模块:从entry出发,调用loader对模块进行转换,同时找出模块依赖的模块,依次递归,知道所有依赖模块完成转换

  5. 生成资源:根据入口与模块之前的依赖关系,组装成chunk代码块,并生成文件输出列表

  6. 写入资源:根据配置的输出路径和文件名,将文件写入,完成构建

loader原理

  • loader的执行顺序与配置顺序相反;

  • 第一个执行的loader会接受源文件作为参数、,执行完毕返回的数据作为一下个loader的参数;

  • 执行流程为

    • 加载loader代码

    • 获取pitch方法(currentLoaderObject.pitch),向loader传入remainingRequestpreviousRequest等参数

    • 进入normal阶段,读取资源

    • 执行runSyncOrAsync进行loader转换

    • 把转换后的内容复制给模块的_source属性,然后调用模块源码的解析、分析资源依赖

loader与plugin区别

loader用来对模块的源代码进行转换;plugin可以在任何阶段调用,能够跨loader进一步加工loader的输出

ParallelUglifyPlugin

UglifyJsPlugin是单线程压缩代码,由于压缩耗时非常严重(先把代码解析成AST语法树,再用各种规则进行分析处理),因此ParallelUglifyPlugin开启多个子线程,把对多个文件的压缩任务分配给多个子线程完成,子线程依旧使用UglifyJsPlugin,进而提升压缩速度。

DllPlugin

DllPlugin抽离公共代码,后续打包不打包该代码。DllReferencePlugin通过manifest.json引用打包好代码

HappyPack

webpack loader虽然是异步执行,但内部执行任务还是单线程的,HappyPack开启子线程并发执行,等子线程处理完毕后再把结果发给主线程,加速打包速度。

热加载原理

提取公共文件

优化

  • 配置 include exclude 减少文件搜索范围

  • 配置编译缓存 babel-loader?cacheDirectory=ture

  • 使用 HappyPack 并行执行 loader

  • 代码可写成按序加载

babel

  • Parser解析代码转为AST树。此处词法分析阶段把字符串形式的代码转换为令牌(tokens)流;语法分析阶段把令牌流转换成AST形式

  • Transformer利用配置好的plugins/presets把AST树转化为新的AST树

  • Generator识别AST生成新代码。深度遍历AST,构建代码转换后的字符串

git

jenkins + git 持续集成环境

Last updated