大家好,今天我想给大家分享如何去写一个插件,相信大家都是用webpack来做前端的打包和构建,其中插件是为webpack非常重要的一个部分,webpack附带了很多内置插件,并且我们还可以自定义插件做很多事情。在说如何写插件之前我们必须要了解的是webpack的打包流程。
那么它的打包流程是什么样的呢?当我们输入打包命令之后发生了什么?运行命令之后,它拿到我们命令行的参数,然后结合这个webpack.config.js中的内容,去初始化参数合并参数,然后去准备编译。
准备编译的过程中,他又干了什么呢?他创建了一个compiler对象,然后把所有的插件都注册好,找到我们整个打包的入口,也就是这个entry,这就是它的准备工作。于是就开始编译了。
他首先是用loader去转换所有的模块,比如说ts,还有tsx啊,这些文件去转换成js文件。从入口开始转换所有模块。转换的同时,他还会去分析每个模块的依赖关系。编译完成之后他也就得到了所有模块之间的相互依赖关系,最后输出打包好的所有文件。
plugin的功能之所以强大,就是因为webpack在这打包的过程中,暴露了一个完整生命周期。这就意味着我们开发者可以在这个生命周期里面去执行任何的操作,影响他任意的打包步骤,来得到我们想要的结果。它可以做任何loader无法实现的事情。
接下来我给大家介绍一下如何写一个插件。这是每个插件都遵循的规范。首先你要有一个class函数,这个class函数里面要有一个Apply方法,这个方法会被webpack执行,我们的主要功能都写在这个apply方法里。然后调用一个webpack的钩子,webpack会在特定的时间去执行你想要的操作。我们可以在官网这里查看compiler所有的钩子函数,然后选择合适的钩子去做我们想做的事情。如果调用的是异步钩子,我们还需要去调用webpack提供的回调函数来告诉webpack我们功能完成了。
接下来我给大家介绍一下我们项目里面已经用到的自定义插件,这是一个简单的生成html并且把打包出来的文件都注入到html里的插件。当打包出来的文件包含哈希值时,这个插件就特别有用,不用我们自己去更改标签,容易出错。
由于我们的插件需要在打包完成之后再执行,因此我们是要找从里面找到这个emit钩子是符合我们的要求的,他是在输出所有的打包好的文件之前去执行的,那我们就可以利用这个钩子。
现在一起来看看我们的plugin具体实现的代码。我们用了一个类来定义插件,用apply方法来编写我们的主要功能。在这里我们调用了webpack的emit钩子,在输出所有的打包好的文件之前执行。compliation这个对象里面有所有这次打包的资源的信息,我们通过它拿到我们所有的打包好的入口文件路径,写成标签,然后用我们存在项目里的这个html文件作为模版,把写好的标签注入到这个html里面,然后把新生成的文件放到我们的compliation的assets对象里。这样就完成了。
这是我们的最后输出的html文件。这是我们webpack打包好的资源。这是通过我们自己定义的插件处理完的。除此以外我们项目还有其他的一些自定义插件,比如这个简易的将public文件夹下的assets copy到build文件的copy plugin。
我们需要用很多时间来学习和调试如何自定义插件,但是我们可以更加了解webpack在做什么,用插件去定义任何我们想要的功能。
最后,这是我参考的文档。谢谢!
【打开PPT】Hello everyone, today I want to share with you how to write a plug-in, I believe that everyone is using webpack to do front-end packaging, and plugin is a very important part. webpack comes with a lot of built-in plugins, and we can also customize plugins to do a lot of things. Before we talk about how to write a plugin, we must understand the webpack packaging process.【下一页PPT】
So what's the packaging process like? 【打开Powershell】What happens when we enter the pack command? After running the command, it takes the parameters of our command line, and then, 【打开VS code】combined with the parameters of this config file to get the final parameters, and then prepares to compile.
Before it compiles, It creates a compiler object, registers all the plugins, finds the entry where it need to start with. After this it began to compile.
It uses loader to convert all the modules from the entry. At the same time, It also analyzes the dependencies of each module.
【回到PPT】After the compilation is complete, wepack also gets the interdependencies between all the modules, and finally outputs all bundles.
The plugin is powerful because webpack exposes a full life cycle during this packaging process. This means that we developers can do whatever we want in this life cycle, influencing any of its packaging steps, to get the result we want. Plugin can do anything that loader can't do.
Next I'll show you how to write a plugin. 【下一页PPT】This is the specification that every plugin follows. First we must have a class function, and inside that class function must have an Apply method, which is executed by webpack, and our main functions are written in that apply method. Then we need to call a webpack compiler hook, and webpack will perform the desired action at a specific time. 【打开官网】We can check all the hooks of the compiler in the official website here, and then choose the appropriate hook to do what we want. 【回到PPT】If we are calling an asynchronous hook, we also need to call the callback function provided by webpack to tell webpack that our execution is complete.
【下一页PPT】Next, I'll introduce you to the custom plug-in we've used in our CCP project, which is a simple plug-in that generates html and injects the packaged files into the html. This plugin is especially useful when the packaged file contains a hash value, we dont need to change the tag ourselves.
【打开官网】Since our plugin needs to be executed after the packaging is completed, we find out that the emit hook is in line with our requirements, and it is executed before all the packaged files are output, so we can use this hook.
【打开VS code】Now let's take a look at the code of our plugin implementation. We used a class to define the plug-in and the apply method to write our main functionality. From here we call webpack's emit hook and execute it before exporting all the bundles. The compliation object contains all the information of the packaged resources. We obtain the path of all bundle entry files through it, write them into tags, and then use this html file in our project as a template to inject the written tags into the html. Then put the newly generated file into our compliation assets object. And that's it.
This is our final output html file. This is the resource we inject. This is done through our own plugins. In addition, our project also has some other custom plug-ins, such as this simple copy plugin to copy assets from the public folder to the build folder.
Webpack provides the appropriate hooks for each step, we just need to find the right moment to do the right thing.
Finally, this is the document I refer to. Thank you!