webpack
webpack是一个打包模块化javascript的工具,它将一切文件都看作是模块。通过loader编译转换文件,通过plugin注入钩子,最后输出的资源模块组合成文件。它的主要配置有entry,output,modules,plugins,loader。
webpack打包输出后的文件其实就是一个闭包,传入的参数是一个对象,键值为所有输出文件的路径,内容为eval包裹的文件内容。必报内重写了模块的加载方式,自己定义了__webpack_require__方法,来实现commonjs规范模块的加载机制。
webpack实际上是基于时间流,通过一系列的插件来运行,webpack利用taptable库提供的各种钩子来实现对于整个构建流程各个步骤的控制。
一些基本概念
- compiler:webpack的运行入口,实例化时定义webpack构建主要流程,同时创建时使用的核心对象compilation;
- compilation:由compiler实例化,存储构建过程中使用的数据,用户监控这些数据的变化,每次构建创建一个compilation实例;
- chunk:一般一个入口对应一个chunk;
- Module:用于标示代码模块的类型,有很多子类用于处理不同情况的模块,模块相关信息都可以从Module实例中获取,例如dependiencies记录模块的依赖信息;
- Parser:基于acorn来分析AST语法树,解析出代码模块的依赖;
- Dependency:解析用于保存代码块对应的依赖使用对象
- template:生成最终代码要用到的代码模块
webpack构建的基本流程
- 创建complier实例,用于控制构建流程,complier实例包含了webpack基本环境信息
- 根据配置项转换成对应的内部插件,并初始化options配置项
- 执行compiler.run
- 创建complitation实例,每次构建都会创建一个compilation实例,包含了这次构建的基本信息
- 从entery开始递归分析依赖,对每个模块进行buildmodule,通过loader将不同的类型的模块转化成webpack模块
- 调用parser.parse将上面的结构转化成AST树
- 遍历整个AST树,搜集依赖dependency,并保存在compilation的实例中
- 生成chunks,不同的entry,生成不同的chunks,动态导入也会生成自己的chunks,待到生成chunks后再继续优化
- 使用template基于compilation的数据生成结果代码
编译过程
- 第一步先初始化参数,通过args将webpack.config.js和shell脚本的配置信息合并,并且初始化。
- 第二步利用初始化的参数创建complier对象,complier可以视作为一个webpack的实例。存在于webpack从启动到结束的整个过程,它包含了webpack的module,plugin等参数信息,然后调用complier.run方法开始编译。
- 第三步根据entry配置信息找到入口文件,创建compilation对象,可以理解为webpac的一次构建编译过程。包含了当前编译环境的所有资源。包括编译后的资源。
- 第四步通过配置信息,调用loader进行模块编译,使用acorn将模块转化为AST树,当遇到require模块依赖时,创建依赖并加入到依赖数组,再找出依赖的依赖,递归异步的处理所有的依赖项。
- 第五步得到所有模块的依赖关系和模块翻译之后的文件后,然后调用compilation.seal方法,对这些模块和根据模块依赖关系创建chunks进行整理,将所有资源进行合并拆分等操作,最后一次性修改输出内容的地方。
- 第六步根据配置信息中的output配置进行最后模块文件的输出,指定输出文件名和文件路径。