You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// A JavaScript class.classMyExampleWebpackPlugin{// Define `apply` as its prototype method which is supplied with compiler as its argumentapply(compiler){// Specify the event hook to attach tocompiler.hooks.emit.tapAsync('MyExampleWebpackPlugin',(compilation,callback)=>{console.log('This is an example plugin!');console.log('Here’s the `compilation` object which represents a single build of assets:',compilation);// Manipulate the build using the plugin API provided by webpackcompilation.addModule(/* ... */);callback();});}}
// upload-plugin.tsimport{Compiler,Stats}from'webpack';import{isObject,uploadDir,removeDir}from'./utils';import{Option}from'./typings';classUploadPlugin{publicstats: Stats;publicoption: Option&Record<string,any>;publicremoveDir: boolean;constructor(option: Option,remove=true){this.stats=nullasunknownasStats;this.option=option;this.removeDir=remove;this.init();}init(){this.checkOption();this.setOption();}// 检验参数checkOption(option=this.option){if(!isObject(option)){thrownewError('option Must be an object!');}constresult=['to','host'].filter((f)=>!option[f]);if(result.length){thrownewError(`The ${result.join(',')} parameter is required!`);}if(!option.password&&!option.privateKey){thrownewError('password and privateKey must have one entry!');}}// 初始化默认值setOption(){constoption={port: 22,username: 'root',};this.option={
...option,
...this.option,};}apply(compiler: Compiler){compiler.hooks.done.tap('upload-plugin',async(stats)=>{console.time('time');// 获取默认的信息,如果src不存在直接使用webpack的配置constsrc=stats.compilation.outputOptions.path;this.option.src=this.option.src??src;if(this.removeDir){awaitremoveDir(this.option);}awaituploadDir(this.option);console.timeEnd('time');});}}exportdefaultUploadPlugin;
webpack 插件入门
最近写了一个移动端项目,不过每次 build 的时候还需要手动上传服务器感觉很不方便,毕竟每次删除文件夹然后拖拽上传的过程太重复了,本着不重复造轮子的原则去 Github 翻了一下,发现
Upload
上传插件还是蛮多的,不过距离自己的要求还是有些差异,很多插件只是只是单一职责,只负责上传这件事情。而如果只负责上传文件不做删除会导致服务器文件越来越多,占用额外的储存成本,WebPack 在 build 过程中会检测相关依赖是否变更,如果变更相关文件的
hash
也是发生变更,这样就会导致新的文件上传到服务器,而旧资源却不会被覆盖替换掉。基本概念
WebPack 的插件是基于
Tapable
实现的,它是一种发布订阅的实现,作用就是将插件的各个生命周期钩子广播出去,然后在合适的时机执行。同时只让插件关注自身的订阅,保证插件组合起来有序进行。Tapable
暴露了三个方法:在编写插件时 WebPack 显示要求我们有
apply
方法,这样做的原因是 WebPack 执行期间会执行 apply 方法,并且注入compiler
,之后在compiler
上订阅钩子事件,在合适时间触发已订阅的 apply 方法再看一下官方给出的示例代码
上面插件在
compiler
中订阅了emit
的异步钩子,然后做了一些操作之后,执行callback()
回调了解了上面的信息,我们找一下 compiler 钩子 有没有我们需要的,文档中列举的钩子很多:
翻到最后会看到一个
done
的钩子,它在compilation
完成时执行。这里我们需要的前置基本准备齐全了,下面要做的就是在
done
触发时rm-rf xx
的操作插件开发准备
为了方便解耦和复用文件,我们创建了一个 utils.ts 文件
它暴露三个方法,删除文件夹和上传文件夹还有一个判断 object 的方法,上面的删除和上传文件夹基于 node-ssh 封装而来,如果你有兴趣了解可以去阅读一下文档
插件开发
剩下的插件开发,就是获取用户填写一些必要字段,例如密码、上传的服务器路径、host 等信息,结合上面的
utils
和钩子,完成这个上传过程整体代码还是很简洁的,去除参数校验部分还有赋值默认值参数,剩下的就是根据参数来是否删除远程文件夹,之后执行上传方法。
你可能很好奇
Option
的定义是啥,这个是结合node-ssh
的连接信息加上自定义扩展的一些字段而来的最后
完整代码已经上传了Github 仓库,如果你有兴趣可以具体看下更具体的一些信息,如果对你有帮助也欢迎
star
。The text was updated successfully, but these errors were encountered: