皮皮网

【tp分发平台源码】【c 源码文件编译】【个人售卡源码】webpackplugin源码

2024-11-18 22:29:57 来源:volcano源码

1.详解webpackplugin的原理及编写一个plugin
2.手摸手写个webpack plugin
3.uglifyjs-webpack-plugin 中文文档
4.webpack之plugin详解
5.源码细读-深入了解terser-webpack-plugin的实现

webpackplugin源码

详解webpackplugin的原理及编写一个plugin

       plugin解决了什么问题?

       plugin解决了Webpack构建生命周期过程中的功能定制问题,可以利用plugin参与到webpack构建流程中的各个阶段并劫持做一些代码处理。

       æ¯”如,打包后需要生成一个html文件,那么就可以使用html-webpack-plugin。还有,在打包之前把dist文件删除,就可以使用clean-webpack-plugin。

       webpack本身就是一个构建过程的状态机,其自身的核心功能也是构建在loader和plugin的机制上的。

compiler和compilation具体是干什么的?

       é¦–先我们来看一个webpack自带的插件BannerPlugin代码,其实webpack的很多核心公司就是利用插件来实现的。

       æ’件的格式

       ä¸€ä¸ªJavaScript函数或JavaScriptç±»;

       åœ¨å®ƒåŽŸåž‹ä¸Šå®šä¹‰çš„apply方法,会在安装插件时被调用,并被webpackcompiler调用一次;

       æŒ‡å®šä¸€ä¸ªè§¦åŠåˆ°webpack本身的事件钩子,即hooks,用于特定时机处理额外的逻辑;

classBannerPlugin{ constructor(options){ this.options=options;}apply(compiler){ constoptions=this.options;constbanner=this.banner;compiler.hooks.compilation.tap("BannerPlugin",compilation=>{ compilation.hooks.processAssets.tap({ name:"BannerPlugin"},()=>{ for(constchunkofcompilation.chunks){ for(constfileofchunk.files){ constdata={ chunk,filename:file};//生成注释constcomment=compilation.getPath(banner,data);//把注释加入到文件中compilation.updateAsset(file,old=>{ constsource=options.footer?newConcatSource(old,"\n",comment):newConcatSource(comment,"\n",old);returnsource;}});}}}}}}

       ä»Žä»£ç ä¸­å‡ºçŽ°äº†compiler和compilation,那它们到底是什么呢?

compiler

       compiler模块是Webpack最核心的模块。每次执行Webpack构建的时候,在Webpack内部,会首先实例化一个Compiler对象,然后调用它的run方法来开始一次完整的编译过程。compiler对象代表了完整的webpack环境配置,插件可以通过它获取到webpack的配置信息,如entry、output、module等配置。

       compiler钩子compiler有很多钩子,下面只介绍常用的几个:钩子名?|Tapable类型|触发时机?|传入callback的参数?||--------------------|-----------------|------------------------------------------|---------------------------------||entryOption?|SyncBailHook?|在webpack中的entry配置处理过之后|context,entry||afterPlugins|SyncHook?|初始化完内置插件之后|compiler||environment?|SyncHook?|准备编译环境,webpackplugins配置初始化完成之后|compiler||beforeRun|AsyncSeriesHook?|开始正式编译之前?|compiler||run?|AsyncSeriesHook?|开始编译之后,读取records之前;|compiler||compile?|SyncHook?|一次compilation编译创建之前?|compilationParams?||compilation?|SyncHook?|compilation创建成功之后?|compilation,compilationParams||emit|AsyncSeriesHook?|生成资源到output目录之前?|compilation||done|AsyncSeriesHook?|compilation完成之后|stats?||failed?|SyncHook?|compilation失败|

       æ•´ä¸ªCompiler完整地展现了Webpack的构建流程:

       å‡†å¤‡é˜¶æ®µï¼šmake之前做的事情都属于准备阶段,这阶段的calback入参以compiler为主;

       ç¼–译阶段:这阶段以compilation的钩子为主,calback入参以compilation为主;

       äº§å‡ºé˜¶æ®µï¼šè¿™é˜¶æ®µä»Žcompilation开始,最后回到Compiler钩子上,calback传入参数是跟结果相关的数据,包括stats、error。

compilation

       åœ¨compilation阶段,模块会被加载(loaded)、封存(sealed)、优化(optimized)、分块(chunked)、哈希(hashed)和重新创建(restored),Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。Compilation对象也提供了很多事件回调供插件做扩展,通过Compilation也能读取到Compiler对象。

       Compilation钩子

       åœ¨Compilation中处理的对象分别是module、chunk、assets,由modules组成chunks,由chunks生成assets,处理顺序是:module→modules→chunks→assets,先从单个module开始处理,查找依赖关系,最后完成单个module处理,完成全部modules之后,开始chunks阶段处理,最后在根据优化配置,按需生成assets。

       æ‰€ä»¥æ•´ä¸ªCompilation的生命周期钩子虽然比较多,但是大规律上是围绕这个顺序进行的,具体的钩子可以查看webpack官网。

       Stats对象在Webpack的回调函数中会得到stats对象。这个对象实际来自于Compilation.getStats(),返回的是主要含有modules、chunks和assets三个属性值的对象。

       modules:记录了所有解析后的模块;

       chunks:记录了所有chunk;

       assets:记录了所有要生成的文件。

       æœ‰äº†å¯¹compilercompilation的理解,那现在来看看BannerPlugin的实现,这个插件的功能是在最后生成的文件的头部加上一段我们自定义的注释,那么它的执行时机肯定是在编译完成之后,生成打包文件之间,也就是在compiler.hooks.compilation这个大钩子下面的processAssets钩子里面执行我们的逻辑。

编写pluginplugin:在文件尾部插入一段注释

       é¦–先创建一个plugins/FootPlugin.js,代码如下:

const{ ConcatSource}=require('webpack-sources')classFootPlugin{ constructor(options){ this.options=options}apply(compiler){ compiler.hooks.compilation.tap('FootPlugin',compilation=>{ compilation.hooks.processAssets.tap('FootPlugin',()=>{ for(constchunkofcompilation.chunks){ for(constfileofchunk.files){ console.log('file--',file)//bundle.js//定义注释的内容constcomment=`/*${ this.options.banner}*/`compilation.updateAsset(file,old=>{ //把注释和旧代码进行拼接returnnewConcatSource(old,'\n',comment)})}}})})}}module.exports=FootPlugin

       webpack.config.js

constFootPlugin=require('./plugins/FootPlugin')module.exports={ plugins:[newwebpack.BannerPlugin({ banner:'欢迎学习'}),newFootPlugin({ banner:'结束学习'})]}

       å¯ä»¥çœ‹åˆ°åœ¨bundle.js的开头和结尾都有对应的注释。

plugin:文件超过一定大小时给出警告const{ resolve}=require('path')constfs=require('fs')classBundleSizeWebpackPlugin{ constructor(options){ this.options=options}apply(compiler){ const{ sizeLimit}=this.optionsconsole.log('bundlesizeplugin')//在编译完成后,执行回调,拿到打包后文件路径,然后读取文件信息获取文件大小,然后定义一些逻辑compiler.hooks.done.tap('BundleSizePlugin',stats=>{ const{ path,filename}=stats.compilation.outputOptionsconstbundlePath=resolve(path,filename)const{ size}=fs.statSync(bundlePath)constbundleSize=size/if(bundleSize<sizeLimit){ console.log('safe:bundle-size',bundleSize,'\nsizelimit:',sizeLimit)}else{ console.warn('unsafe:bundle-size',bundleSize,'\nsizelimit:',sizeLimit)}})}}module.exports=BundleSizeWebpackPlugin

       æœ¬ç« åˆ°è¿™é‡Œå°±ç»“束了,我们开始介绍了webpack的核心概念,有了对webpack的基本配置的了解;接着利用css-loader和style-loader对webpack的loader机制进行了详细分析;最后,对webpackplugin的工作机制和流程进行了梳理,并手写了两个plugin,让你对plugin不再觉得遥不可及。有了这些前置知识,就可以对我们原生项目进行工程化的改造了。期待你的学习。

原文:/post/

手摸手写个webpack plugin

       本周的任务是深入了解和编写webpack插件。插件是什么?它实际上是一个具有 apply 方法的JavaScript对象,更准确地说,就是一种函数。它可以是普通的函数,也可以是tp分发平台源码特殊的函数,用于实现特定功能。

       相比loader,插件可以解决一些loader无法处理的场景,比如在打包开始前进行环境配置、打包结束后发送通知邮件等。例如,HtmlWebpackPlugin插件可以帮助我们在dist文件夹下自动生成index.html文件,并在其中自动引入打包后的css和js脚本文件。安装并配置插件后,运行打包指令,可以看到生成的index.html文件自动引入了生成的main.js脚本文件。

       接下来,c 源码文件编译我们深入探讨HtmlWebpackPlugin的源码,了解如何编写插件。通过观察源码,我们可以发现插件是通过apply方法在特定生命周期内执行操作。以HtmlWebpackPlugin为例,其在初始化阶段会利用Compiler提供的hook函数,实现生成html文件并引入资源的功能。

       为了更深入理解插件的工作原理,我们可以执行yarn run webpack命令,跟踪webpack的运行过程,了解不同hook函数的调用时机和作用。例如,afterDone钩子函数会在打包完成后触发,用于执行发送通知邮件等操作。通过观察Compiler类的实现,我们可以理解如何在插件中访问和利用Compiler实例对象,以及如何在特定钩子函数的个人售卡源码回调中实现自定义逻辑。

       接下来,我们以一句话需求为例,实现一个在webpack打包后发送通知邮件的插件。首先,我们需要安装nodemailer库以实现邮件发送功能。然后,根据需求编写插件代码,利用Compiler提供的hook函数,如afterDone,实现邮件发送逻辑。运行webpack后,我们可以看到通知邮件被成功发送。为了方便他人使用,我们还可以将自定义插件发布到npm仓库。

       在插件开发中,还有一些重要的概念,如SyncHook和AsyncHook,投诉信箱 源码它们分别用于同步和异步操作。另外,了解如何在插件中正确使用这些概念,对于提高插件的可复用性和功能性至关重要。官方文档提供了关于编写插件的详细指导,建议开发者深入学习。

       总之,通过本篇文章的学习,我们不仅掌握了webpack插件的基本概念和使用方法,还深入探讨了其原理和实战应用。希望这些知识能帮助开发者在实际项目中灵活运用插件,提升开发效率。

uglifyjs-webpack-plugin 中文文档

       uglifyjs-webpack-plugin 的核心功能与配置

       uglifyjs-webpack-plugin 是一个用于webpack项目的插件,它利用uglify-js进行JavaScript文件的压缩,以减小文件大小并提升网站性能。

       要开始使用,首先确保你的java源码的游戏项目环境满足要求:Node.js版本需在6.9.0及以上,Webpack版本需为4.0.0及以上。

       安装与配置

       在项目中安装插件:

       javascript

       npm install uglifyjs-webpack-plugin

       接着,在webpack配置文件(webpack.config.js)中添加插件配置,如示例所示:

       javascript

       // webpack.config.js

       module.exports = {

        // ...

        module: {

        rules: [

        {

        test: /\.js(?.*)?$/i,

        use: {

        // ...

        plugins: [

        new UglifyJsPlugin({

        // 插件配置项

        }),

        ],

        },

        },

        ],

        },

        // ...

       };

       配置选项包括:

test:匹配需要压缩的JavaScript文件。

include:指定要包含在压缩过程中的文件。

exclude:指定要排除在压缩过程中的文件。

cache:选择启用或自定义缓存机制。

parallel:启用多进程并行压缩,提高构建速度。

sourceMap:选择是否启用源码映射,注意这会增加编译时间。

minify:自定义压缩函数,允许使用其他压缩工具。

extractComments:控制如何处理和提取注释。

condition:用于设置特定注释的提取条件。

filename:定义提取注释的文件名。

warningsFilter:过滤uglify-js产生的警告。

       根据具体需求调整这些选项,例如,要启用缓存和多进程并行运行,可以这样配置:

       javascript

       new UglifyJsPlugin({

        cache: true,

        parallel: true,

        // 其他配置项...

       }),

webpack之plugin详解

       plugin在webpack中扮演着核心角色,它们是构建工具的扩展点,用于解决loader无法实现的其他功能。要使用plugin,通常先通过npm安装到本地,然后在配置文件(webpack.config.js)的头部引入,紧接着在plugins那一栏使用new关键字生成插件的实例并注入到webpack中。在webpack构建过程中,plugin会在特定的生命周期函数触发时执行定义的功能。这些生命周期函数可以类比为打包流程中的工序,当执行到特定工序时,plugin绑定的事件就会被触发。

       例如,clean-webpack-plugin插件会在webpack重新打包前自动清空输出文件夹,而HtmlWebpackPlugin插件则会在打包结束后根据配置的模板路径自动生成一个html文件,并把打包生成的js路径自动引入到这个html文件中,大大提高了开发效率。

       webpack程序架构中包含compiler和compilation两个核心概念。compiler是webpack的支柱引擎,负责控制程序的执行,其生命周期函数用于定义在不同阶段执行的事件。compiler会从左到右执行每一个生命周期函数定义的事件队列。compilation实例主要负责代码的编译和构建,每次代码编译(例如日常开发时按ctrl + s保存修改后的代码)都会生成一个新的compilation实例来执行构建任务。

       在compilation的生命周期中,compiler进入make阶段后,compilation实例被创建,它依次执行一系列定义的钩子函数,包括加载相应的loader对代码进行编译、解析生成AST语法树、进行依赖分析、优化和封装等步骤。这些步骤构成了webpack完整的打包构建流程。

       Tapable是一个用于事件发布订阅的第三方库,webpack中使用Tapable实现了事件的绑定和触发机制。通过使用Tapable提供的SyncHook和AsyncSeriesHook,可以定义同步和异步事件,这些事件会在特定的生命周期阶段被触发。

       为了开发自定义插件,可以创建一个js文件并实现一个class,其中包含一个固定方法apply。apply函数的第一个参数是compiler,可以在apply函数内部编写插件逻辑。为了在特定生命周期阶段绑定事件,可以使用Tapable提供的hook,例如在emit阶段绑定事件。通过这样的方式,插件可以在webpack执行到特定时刻时执行特定功能。

       使用自定义插件时,首先在webpack配置文件中引入插件,然后在plugins数组中使用new关键字注入插件实例。这样,当webpack执行到相应的事件节点时,插件定义的监听函数就会被触发。

源码细读-深入了解terser-webpack-plugin的实现

       terser-webpack-plugin 是一个基于 webpack 的插件,它利用 terser 库对 JavaScript 代码进行压缩和混淆。其核心功能在于通过在 webpack 的运行时钩子 optimizeChunkAssets 中注册,实现了代码优化过程。在 apply 函数中,它获取 compilation 实例,并通过 tapPromise 注册一个异步任务,当 webpack 执行优化阶段时,每个 chunk 会触发这个任务,执行 minify 函数进行压缩处理。

       optimise 函数是实际的任务处理入口,它负责具体的优化流程。函数内部,scheduleTask 负责并行处理,如果开启 parallel 模式,会利用jest-worker提供的线程池进行并发工作,线程池管理复杂,根据 node 版本不同采用 worker_threads 或 child_process。minify 函数则是压缩和混淆代码的核心操作,它直接使用 terser 库完成任务。

       总的来说,terser-webpack-plugin 的优化流程包括在 webpack 的优化阶段对代码进行压缩,使用 Jest 的 worker 线程池进行并行处理,以及通过 terser 库的实际压缩操作。理解这些核心环节,可以帮助开发者更深入地掌握该插件的使用和工作原理。