2022-06-08 webpack plugin

webpack 核心概念和手写 plugin

webpack 常用概念

  • Entry :项目入口,指示 webpack 应该使用哪个模块,来作为构建气内部依赖图的头节点

  • Output :输出,告诉 webpack 在哪里输入它所创建的 bundle,以及如何命名这些输出文件

  • Module :一个模块对应于一个文件,模块之间由引用关系构成依赖树

  • Chunk :构建后的代码块,一个 chunk 是多个模块分割合并构建后的结果

  • Loader :模块转换器,webpack 之所以可以处理不同类型的文件,是因为有一个个处理这些文件的 loader,loader 中的代码可以拿到文件的内容和 webpack 的配置,以处理文件并用于后面构建流程的输出

  • Plugin :功能插件。在 webpack 构建管道中,会广播很多事件,在 plugin 中,可以监听这些事件用于处理不同时机的流程。
    比如打包压缩,资源管理,注入环境变量。

  • Mode:模式,告知 webpack 使用相应模式的内置优化

  • Browser Compatibility:浏览器兼容性,Webpack 支持所有符合 ES5 标准 的浏览器(IE8 以上版本)

webpack 的常用功能

  • 代码分割
  • 文件合并压缩
  • ES5 兼容
  • 按需加载
  • 代码校验
  • Tree Shaking
  • 模块热替换等

Plugin 概念

webpack 构建的过程类似一个管道,处理依赖树是要经过多个流程节点的,且下一个流程节点会受上一个节点的影响。
插件的功能就是向这些节点中插入一段流程,用来处理流程。

对于 loader,它就是一个转换器,将 A 文件进行编译形成 B 文件,这里操作的是文件,比如将 A.scss 或 A.less 转变为 B.css,单纯的文件转换过程
plugin 是一个扩展器,它丰富了 wepack 本身,针对是 loader 结束后,webpack 打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听 webpack 打包过程中的某些节点,执行广泛的任务。

常用 Plugin

1,copy-webpack-plugin
将已经存在的单个文件或整个目录复制到构建目录

const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: "./template/page.html",
                    to: `${__dirname}/output/cp/page.html`
                }
            ]
        })
    ]
};

2,html-webpack-plugin
基本作用是生成 html 文件
要生成多个 html 文件,可以配置多套

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: {
        news: [path.resolve(__dirname, "../src/news/index.js")],
        video: path.resolve(__dirname, "../src/video/index.js")
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "news page", // 生成的文件名称 相对于webpackConfig.output.path路径而言
            filename: "pages/news.html", // 生成filename的文件模板
            template: path.resolve(__dirname, "../template/news/index.html"),
            chunks: ["news"]
        }),
        new HtmlWebpackPlugin({
            title: "video page", // 生成的文件名称
            filename: "pages/video.html", // 生成filename的文件模板
            template: path.resolve(__dirname, "../template/video/index.html"),
            chunks: ["video"]
        })
    ]
};

3,SplitChunksPlugin
代码分割

4,HotModuleReplacementPlugin
模块热更新(用于开发模式)

实现一个 plugin

/plugins/myPlugin.js

class myPlugin {
  constructor(options) {
    console.log('my plugins', options)
  }

  apply (compiler) {
    compiler.plugin('compilation', compilation => {
      console.log('myPlus1')
    })
  }
}

module.exports = myPlugin

webpack.config.js

const myPlugin = require('./plugins/myPlugin')

module.exports = {
  entry: {
    index: './src/js/index.js'
  },
  plugins: [
    new myPlugin({ param: 'xxx' })
  ]
}

以上是一个最简单的plugin

  • webpack启动后,先实例化一个plugin对象,然后调用其中的代码
  • 调用到apply函数后,plugin会注册一个监听事件函数
  • 当webpack管线出发事件广播的时候,这个监听事件的回调函数会被调用
  • 回调函数里面可以拿到关于webpack管线上下文对象,从而可以操作webpack的行为

compiler对象

  • 包含了webpack管线环境的所有信息,可以看作是webpack对象的一个实例。比如会包含loader,plugin,options

compilation对象

  • webpack的对每个文件的编译,都会出发compilation事件,这个事件中的回调参数就是compilation对象,其中包含了所有本次文件编译的信息

事件流

  • webpack通过管线来组织编译过程
  • webpack的事件流机制保证了插件工作的有序性
  • webpack的事件流运用了发布订阅模式
compiler.plugin('event-name', params => {
  ...     
});

注意点

  • compiler对象和compilation对象本身也能发布事件,在其他插件中就能监听到这些事件。
  • 有些事件是异步的,异步事件会附带两个参数,第二个参数为回电函数
compiler.plugin('emit',function(compilation, callback) {
  ...
    
  // 处理完毕后执行 callback 以通知 Webpack 
  // 如果不执行 callback,运行流程将会一直卡在这不往下执行 
  callback();
});
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容