本文主要的内容是通过之前使用的prerender-spa-plugin插件的源码阅读,来看下我们应该如何编写一个webpack的插件,同时了解下预渲染插件到底是如何实现的。
这个内容其实已经在使用prerender-spa-plugin里面有所涉及了,这一章的内容算是对之前一篇文章的补充和拓展,详细介绍下Webpack的插件机制到底是如何运行的,之前写的简单的替换的插件生效的原理到底是什么。
如果大家还没有看之前的如何使用prerender-spa-plugin插件对页面进行预渲染这篇文章,可以先去看看,了解下这个插件到底是做什么的,我们的插件大概是什么样的。
prerender-spa-plugin是开源的,源码在GitHub上面可以看到,大家如果有兴趣的话,可以自己点击看下。
首先,我们让我们来简单回顾下这个插件是如何使用的,这个对于我们了解其内部构造,有一定的帮助。我们就直接使用它官方文档上提供的一个例子。
从上面这个例子来看,我们可以知道这个插件需要初始化一个实例,然后传入对应的参数如输出的路径staticDir
、需要渲染的路由routes
等。
接下来,让我们来简单介绍下他的源码结构。代码具体分块如下:
整个prerender-spa-plugin的插件是由2大部分构成:
下面,我们就基于prerender-spa-plugin插件,来一个一个部分的看下。
首先让我们来看下初始化的function函数。这个函数主要做的是一些初始化参数获取后的处理。具体代码如下:
因为我们的插件使用的方式是实例化后添加(即new操作符实例化后使用),所以function函数的入参主要是将一些需要的参数绑定到this对象上,这样实例化后,就可以获取相关的参数。
很多的SDK或者说插件相关的工具,因为能够接受多种类型、不同长度的入参,因此会在一开始对参数类型进行判断,确定传入的参数类型到底是哪一种。
从代码中看,目前记录的参数有输出的参数staticDir
、需要渲染的路由routes
。如果自己定义了renderer
函数,那么也绑定存储下来。同时,这个V3版本的代码还对V2版本进行了向前兼容。
说完了初始化的function,我们来看下最重要的apply函数。具体代码如下:
在说apply函数之前,我们先看下apply函数接收的参数compiler
对象和mkdirp
这个方法,以及生命周期绑定的代码。
整个apply方法,接收的参数只有一个complier
对象,详细的内容我们可以看webpack中关于complier对象的描述,具体的源码可以见此处。我下面简单介绍下:
complier
对象是webpack提供的一个全局的对象,这个对象上面挂载了一些在插件生命周期中会使用到的功能和属性,比如options、loader、plugin等。我们可以通过这个对象,在构建中获取webpack相关的数据。
这个方法就是将执行mkdir -p
方法的函数转化成一个Promise对象。具体可以看代码上面的原文注释。因为比较简单,这里我就不过多介绍了。
在最后,钩子函数生命完成后,需要将其关联到最近的生命周期上。这个插件关联的是afterEmit这个节点,大家如果想看下整个webpack相关构建流程的生命周期,可以参考这个文档。
看完了简单的部分,下面我们来看下最重点的钩子函数。
接下来,让我们来看下这个插件中最核心的钩子函数。这个插件的关联的声明周期是afterEmit这个节点,接下来我们来看下具体的代码。
在这个方法中,又出现了一个新的compilation
对象。这个方法详细的介绍可以看Webpack compilation对象,具体的源码可以见此处。下面我简单介绍下:这个对象代表的是一次文件资源的构建。每次有文件变化时,就会创建一个新的对象。这个文件主要包含了当前资源构建和变化过程中的一些属性和信息。
另一个done
参数,代表着当前插件执行完后执行下一步的一个触发器,和我们常见的Node框架中的next()
一样。
接下来,我们来简单说下这个函数执行的逻辑:
Prerenderer
的实例。这个实例是用于对页面进行预渲染的一个工具,具体的代码可以见GitHub。
Prerenderer
实例。
这个就是一个插件执行的完整流程。
通过prerender-spa-plugin这个插件,大家应该能够了解到我们现行的一个插件到底是如何运转的,我们编写一个插件需要的核心部件:
有了这些东西,我们的一个Webpack的插件就完成了。
希望通过一个插件源码的示例,能够让大家了解下我们日常使用的看似很复杂的Webpack插件,到底是怎么实现的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。