webpack------>webpack 的本质

1.概念

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

2.作用

webpack 通过 loader 可以支持各种语言和预处理器编写模块(通过loader处理非JavaScript模块,并在bundle中引入依赖),模块可以通过以下方式来表达它们的依赖关系:

1. ES2015 import 语句
2. CommonJS require() 语句
3. AMD define 和 require 语句
4. css/sass/less 文件中的@import语句
5. 样式(url(...))HTML文件(<img src=...>)中的图片链接

3.本质

webpack可以理解为一种基于事件流的编程范例,一系列的插件运行,而实现这个插件机制的是Tapable。

1. Tapable是什么?

Tapable公开了许多Hook类,可用于为插件创建钩子。
Tapable是一个类似于Node.js的EventEmitter的库,主要是控制钩子函数的发布与订阅,控制着Webpack的插件系统。

npm install --save tapable

Node.js事件机制简单例子:

// nodejs中的事件机制
const EventEmitter = require('events');
const emitter = new EventEmitter();
// 监听事件
emitter.on('start',()=>{
    
    
    console.log('start')
})
// 触发事件
emitter.emit('start')
2.Tapable Hooks类型

Tapable暴露的为插件提供挂载的Hook类,如下:

const {
    
        
  SyncHook,                // 同步钩子
  SyncBailHook,            // 同步熔断钩子
  SyncWaterfallHook,       // 同步流水钩子
  SyncLoopHook,            // 同步循环钩子
  AsyncParallelHook,       // 异步并发钩子 
  AsyncParallelBailHook,   // 异步并发熔断钩子   
  AsyncSeriesHook,         // 异步串行钩子
  AsyncSeriesBailHook,     // 串行串行熔断钩子
  AsyncSeriesWaterfallHook // 异步串行流水钩子
} = require("tapable");

这些Hook可以按以下进行分类:

Hook:所有钩子的后缀
Waterfall:同步方法,但是它会传值给下一个函数
Bail:熔断:当函数有任何返回值,就会在当前执行函数停止
Loop:监听函数返回true表示继续循环,返回undefined表示循环结束
Sync:同步方法
AsyncSeries:异步串行钩子
AsyncParallel:异步并行执行钩子
3.构建流程
  • 初始化参数,从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
  • 开始编译,用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。
  • 确定入口,根据配置中的 entry 找出所有的入口文件。
  • 编译模块,从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  • 完成模块编译,在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。
  • 输出资源,根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
  • 输出完成,在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
    在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

4. 实现简易webpack

模拟webpack的Compiler与plugin

//tapable使用:模拟webpack的Compiler.js
const {
    
    SyncHook} = require("tapable");

module.exports = class Compiler{
    
    
    constructor(){
    
    
        this.hooks = {
    
    
            // 1. 注册同步钩子
           init:new SyncHook(['start']),  
        }
    }
    run(){
    
    
        // 3. 触发钩子函数
        this.hooks.init.call()
    }
} 

//模拟 plugin.js
class Plugin{
    
    
	constructor(){
    
    }
  apply(compiler){
    
    
    // 2. 插件内监听钩子函数
  	compiler.hooks.init.tap('start',()=>{
    
    
    	console.log('compiler start')
    })
  }
}


// 模拟webpack.js
const options = {
    
    
	plugins:[new Plugin()]
}

const compiler = new Compiler()
for(const plugin of options.plugins){
    
    
	if(typeof plugin==='function'){
    
    
  	plugin.call(compiler,compiler)
  }else{
    
    
  	plugin.apply(compiler)
  }
}

compiler.run()

猜你喜欢

转载自blog.csdn.net/qq_44880095/article/details/113500262
今日推荐