最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从无到有,实现一个webpack插件

    正文概述 掘金(晓黑板前端技术)   2020-12-02   448

    webpack已经成为开发web应用不可或缺的工程化工具,而作为webpack支柱功能的插件系统,是我们深入学习webpack绕不过的一道坎。站在插件开发的视角,你可以更细粒度地控制webpack的工作,实现那些通过修改配置文件做不到的事情。

    小程序 & webpack

    最近公司团队使用webpack来给微信小程序项目做工程化,每个页面的js文件作为webpack的一个独立entry,经过编译打包后,每个entry都对应生成一个output js文件,引用了node_modules文件夹下面的模块也会被打包进来,因此不需要执行小程序构建npm这一过程。但是造成了模块重复打包的问题: 从无到有,实现一个webpack插件

    如上图,A模块被1、2两个页面引用,最终A模块被重复打包进了两个页面的输出文件里,造成小程序打包体积过大。

    经过修改webpack配置、提取公共模块之后解决了该问题。但毕竟是跳过了“构建npm”这一过程,因此我决定开发一款webpack插件,模拟小程序的这一过程。

    What to do?

    先看一下小程序在“构建npm”这一步骤做了什么:

    构建后的目录结构大致如下:

    |--node_modules
    |--miniprogram_npm
    |    |--testComp // 小程序 npm 包
    |    |    |-index.js
    |    |    |-index.json
    |    |    |-index.wxss
    |    |    |-index.wxml
    |    |--testa // 其他 npm 包
    |         |--index.js // 打包后的文件
    |         |--miniprogram_npm
    |              |--testb
    |                   |--index.js // 打包后的文件
    |                   |--index.js.map
    |--pages
    |--app.js
    |--app.wxss
    |--app.json
    |--project.config.js
    

    简单来说:先将node_modules目录下的模块,拷贝到同级的miniprogram_npm目录;然后将所有对node_modules模块的引用,修改到miniprogram_npm,例如require('node_modules/abc')改为require('miniprogram_npm/abc')

    我们要做的就是用webpack插件复刻上面的步骤:

    1. 遍历所有webpack解析出的模块,找出所有公共Modules(node_modules目录、以及作为参数传给插件的目录)
    2. 公共Modules与其被引用的所有Chunks解绑
    3. 给每个公共Module创建新Chunk,一个Chunk关联一个Module,并插入Chunks列表
    4. 生成Assets阶段,修改文件源代码,根据本模块的dependencies和目标模块的reasons,插入require语句

    How to do?

    1. 对官方文档有个大概的了解

    只是大概,着手开发之前不需要看的特别细,因为大部分知识都没有通过文档整理出来。可以看下这篇:webpack.js.org/contribute/…,作为入门。

    tapable,懂得用哪种类型的挂钩即可,原理暂不必深究。

    (一定要看webpack英文官网,中文官网内容更新较晚!)

    2. 善用断点调试

    因为是在node端编程,我们在webstorm、vscode这样的编辑器里面就可以打断点,然后启动debug模式 从无到有,实现一个webpack插件

    从无到有,实现一个webpack插件

    各变量的数据结构一目了然。

    3. 了解webpack常用变量的结构

    例如Compiler、Compilation、Module、Chunk等,官方文档对这部分并没有说明,因此还是要通过断点+源码的方式。

    • 盯断点:可能需要在断点模式下,盯着数据结构看很久、很多次
    • 看源码:看类的常用方法,ts文件(有些ts类型相对于源码少了东西,应该是官方没来得及更新)

    4. 增删改内部变量时,优先调用封装好的函数

    例如解除module和chunk的绑定,如果执行module._chunk.delete(chunk),仅仅是解除了module对chunk的依赖,而两者是双向依赖,就意味着还需要反向解除chunk对module的依赖。

    但不需要这么麻烦,通过源码我们发现,可以直接调用Module类提供的一个方法:

    removeChunk(chunk) {
        if (this._chunks.delete(chunk)) {
            chunk.removeModule(this);
            return true;
        }
        return false;
    }
    

    解除了module和chunk的双向依赖。

    5. 选对时机:hooks

    Compiler和Compilation都提供各种钩子函数,可以参考这篇文档:webpack.js.org/api/compile…。列表里的函数是按照执行顺序来排列的,注意区分回调函数传入参数的不同。

    Compiler:我理解为webpack的实例,全局唯一 Compilation:一次编译,run模式下只执行一次,watch模式下每次文件变化执行一次

    各个钩子函数的解释文档里面都有,但我还是不知道从何入手,怎么办? 这时可以找一个比较成熟的插件,参考它的源码

    比如我要做的功能,和SplitChunkPlugin的功能非常相似,于是我去github搜索,没有找到...然后发现它已经被webpack内置了,在webpack的源代码中找到了它。然后就是参考它的hooks切入点,模仿它。这是对新手最友好的方式,特别是看hooks文档看的一头雾水的时候。

    6. 修改webpack config

    当插件要实现的功能,需要修改webpack的配置文件怎么办?其实可以在插件内部修改:

    compiler.hooks.environment.tap('HelloWorldPlugin', () => {
        // 修改webpack config,必须抽出runtime.js
        compiler.options.optimization.runtimeChunk = {
          	name: 'runtime'
        }
    });
    

    在适当的hooks里面,通过compiler.options对象访问、修改。

    或者不这样实现,而是手动修改配置文件,两种方式,自由选择,这里只是说明插件拥有这个功能。

    成果

    插件引用方式:

    new HelloWorldPlugin({
        libPaths: ['src/utils']
    }),
    

    引入了插件之后的打包结果:

    |--mp_node_modules	// 类似小程序的miniprogram_npm目录
    |--pages
    |--utils
    |--components
    |--app.js
    |--app.wxss
    |--app.json
    |--runtime.js
    |--sitemap.json
    

    根据依赖关系,在文件头部插入require语句: 从无到有,实现一个webpack插件

    小程序打包缺陷

    因为该原则的原因,所有node_modules模块,都会被打包到主包,因此对于稍大型的应用来说,随着工程规模扩大,主包随时可能超过2M上限,需要将业务拆分至多个小程序才能解决。

    不过换个角度一想,可能小程序的初衷就是“小”,有可能是微信官方故意而为之。


    起源地下载网 » 从无到有,实现一个webpack插件

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元