Webpack源码浅析

webpack编译的起点

一切从const compiler = webpack(config)开始。

webpack函数源码(./lib/webpack.js):

const webpack = (options, callback) => { let compiler = createCompiler(options) // 如果传入callback函数,则自启动 if(callback){ compiler.run((err, states) => { compiler.close((err2)=>{ callbacl(err || err2, states) }) }) } return compiler }

webpack函数执行后返回compiler对象,在webpack中存在两个非常重要的核心对象,分别为compiler和compilation,它们在整个编译过程中被广泛使用。

   · Compiler类(./lib/Compiler.js):webpack的主要引擎,在compiler对象记录了完整的webpack环境信息,在webpack从启动到结束,compiler只会生成一次。你可以在compiler对象上读取到webpack config信息,outputPath等;

   · Compilation类(./lib/Compilation.js):代表了一次单一的版本构建和生成资源。compilation编译作业可以多次执行,比如webpack工作在watch模式下,每次监测到源文件发生变化时,都会重新实例化一个compilation对象。一个compilation对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。

Compiler类在函数createCompiler中实例化(./lib/index.js):

const createCompiler = options => { const compiler = new Compiler(options.context) // 注册所有的自定义插件 if(Array.isArray(options.plugins)){ for(const plugin of options.plugins){ if(typeof plugin === 'function'){ plugin.call(compiler, compiler) }else{ plugin.apply(compiler) } } } compiler.hooks.environment.call() compiler.hooks.afterEnvironment.call() compiler.options = new WebpackOptionsApply().process(options, compiler) // process中注册所有webpack内置的插件 return compiler }

Compiler类实例化后,如果webpack函数接收了回调callback,则直接执行compiler.run()方法,那么webpack自动开启编译之旅。如果未指定callback回调,需要用户自己调用run方法来启动编译。

从上面源码中,可以得出一些信息:

compiler由Compiler实例化,里面的属性和方法后面一节会提到,其中最重要的是compiler.run()方法;

遍历webpack config中的plugins数组,这里我加粗了plugins数组,所以配置plugins时不要配成对象了。(事实上,在webpack函数中会对options做object schema的校验)。

plugin:如果 plugin 是函数,直接调用它;如果 plugin 是其他类型(主要是object类型),执行plugin对象的apply方法。apply函数签名:(compiler) => {}。

webpack非常严格的要求我们plugins数组元素必须是函数,或者一个有apply字段的对象且apply是函数,原因就在于此。{ plugins: [ new HtmlWebpackPlugin() ] }

调用钩子:compiler.hooks.environment.call()以及compiler.hooks.afterEnvironment.call()是源码阅读至此我们最先遇到的钩子调用,在之后的阅读中,你会遇到更多的钩子注册与调用。要理解webpack钩子的应用,需要先了解Tapable,这是编写插件的基础。

调用钩子:compiler.hooks.environment.call()以及compiler.hooks.afterEnvironment.call()是源码阅读至此我们最先遇到的钩子调用,在之后的阅读中,你会遇到更多的钩子注册与调用。要理解webpack钩子的应用,需要先了解Tapable,这是编写插件的基础。

你可能感兴趣的:(Webpack源码浅析)