乐趣区

关于javascript:编写-loader-和-plugin

原文地址

编写 loader 和 plugins

github

一、loader

1.loader 介绍

loader 是什么

loader 其实是一个函数,对匹配到的内容进行转换,将转换后的后果返回。

loader 作用

webpackloader 就像是一位翻译官。webpack 只意识 JavaScript 这们语言,对于其余的资源通过 loader 后能够转化做预处理

  • loader 的执行是有程序的,反对链式的调用 。loader 的执行程序是从下到上,从右到左。比方解决款式类的文件,use:['style-loader', 'css-loader']css-loader 解决后的文件返回给 style-loader
  • 一个 Loader 的职责是繁多的,只须要实现一种转换。
  • Webpack 会默认缓存所有 Loader 的处理结果,对没有批改的 loader 不会从新加载,敞开 webpack 的默认缓存后果须要增加this.cacheable(false);

常见的 loader

  • 款式类的 loader:css-loader, style-loader, less-loader, postcss-loader(增加 -webkit)
  • 文件类的 loader:url-loader, file-loader, raw-loader等。
  • 编译类的 loader:babel-loader, ts-loader
  • 校验测试类 loader:eslint-loader, jslint-loader

4. loader 的三种应用形式

    1. webpack.config.js 中配置

      module.exports = {
        module:{
         rules:[{
                 test:/\.css$/,
                 use:['css-loader'],
                 // use:{loader:'css-loader',options:{}}
             }
         ]
        }
      }
    1. 通过命令行的参数形式

      webpack --module-bind 'css=css-loader'
    1. 通过内联应用

      import txt from 'css-loader!./file.css';

2. 编写一个 loader

思路:后面咱们说过 1.loader 是一个函数;2. 对匹配到的内容进行转换;3. 再将转换内容返回,依照这个思路咱们能够编写一个最简略的loader

// 在 ./loader/replaceLoader.js 创立一个替换字符串的 loader
module.exports = function(source) {return source.replace('a', 'b')
}

// 在 webpack.config.js 应用 本人写的 loader
module.exports = {
    module:{
        rules:[{
            test:"/\.js$/",
            use:[{loader: path.resolve(__dirname, './loader/replaceLoader.js')
                    options:{name: '林一一'}
                }
            ]
        }]
    }
}

// 或者应用 replaceLoader
module.exports={resolveLoader:['node_modules', './loader']
    module:{
        rules:[{
            test:"/\.js$/",
            use:['resolveLoader']
        }]
    }
}

下面就是一个最简略的编写 loader 的案例

  • loader 还能够接管 options 传入的参数,详情查看 loader API,也能够应用官网提供的 loader-util 接管参数

    const loaderUtil = require('loader-utils')
    module.exports = function(source) {console.log(this.query.name) // 林一一
      const options = loaderUtil.getOptions(this)
      return source.replace('a', 'b')
    }
  • 异步:loader 是一个函数天然有同步和异步的辨别。应用异步的 loader 须要增加 this.async() 申明异步操作

    const loaderUtils = require('loader-utils')
    module.exports = function(source) {const options = loaderUtils.getOptions(this)
      const callback = this.async()
      setTimeout(()=>{console.log(options.name)
          let res = source.replace('a', options.name)
          callback(null, res, sourceMaps, ast)
      }, 4000)
    }

    下面的代码会在 4 秒后打包胜利,如果没有 this.async() 异步操作就会失败,callback() 回调函数将后果放回。

  • 默认状况下 webpack 给 loader 传递的字符串编码是 utf-8,如果须要解决二进制的文件须要增加exports.raw = true
  • 下面提到过 webpack 会默认将 loader 的加载后果缓存如果须要敞开 webpack 的缓存后果须要增加this.cacheable(false);
  • Npm link 专门用于开发和调试本地 Npm 模块,在没有公布到 npm 下面也能够在调式本地的 loader。具体须要在package.json 中配置 本地 loader,在根目录下执行 npm link loader-name 就能够在node_modules 中应用本地的 loader 了。同时也能够采纳下面的resolveLoader 实现导入 loader 的形式

总结编写 loader 的思路

  1. loader 是一个导出函数,有返回值,能够借助第三方模块和 Node api 实现。
  2. loader 能够应用 loader-utils 接管到options 中传递过去的参数
  3. loader 的异步编写须要显示的申明 const callback = this.async() 表明异步。
  4. loader 如果须要解决二进制文件也须要申明exports.raw = true
  5. loader 的容许后果会被 webpack 缓存,如果须要敞开 webpack 的缓存后果须要申明this.cacheable(false)
  6. 编写后的本地loader 能够借助 Npm linkresolveLoader 导入。

二、webpack 的构建流程

再讲 plugins 之前须要先分明 webpack 的构建流程是怎么的

  1. 初始化参数。从配置文件和 shell 语句中合并的参数
  2. 开始编译。将上一步失去的参数初始化成 complier 对象,加载所有的导入插件,执行对象的 run 办法开始执行编译;
  3. 确定入口。从配置的 entry 入口找出所有的入口文件。
  4. 编译模块 。依据入口文件的依赖,调用所有配置的loader 进行转换。
  5. 实现模块编译并输入。依据入口文件之间的依赖关系,造成一个个代码块 chunk
  6. 输入实现。将造成的代码块 chunk 输入到文件系统。

下面初始化造成的 complier对象 会被注入到插件的 apply(complier)内。complier对象对象蕴含了 Webpack 环境所有的的配置信息比方 options, loaders, plugins等等属性,能够简略的认为 complier 是 webpack 的实例,通过 compler.plugin() 能够监听到 webpack 播送进去的事件。

三、plugin

1 plugin 介绍

plugin 是什么

plugin 是一个插件,这个插件也就是一个类,基于事件流框架 Tapable 实现。在 webpack 的构建流程中在初始化参数后,就会加载所有的 plugin 插件,创立插件的实例。

plugin 作用

plugin 通过钩子能够波及到 webpack 的整一个事件流程。也就是说 plugin 能够通过监听这些生命周期的钩子在适合的机会应用 webpack 提供的 API 做一些事件。

常见的 plugin

  • html-webpack-plugin 会在打包后主动生成一个 html 文件,并且会将打包后的 js 文件引入到html 文件内。
  • optimize-css-assets-webpack-plugin 对 CSS 代码进行压缩。
  • mini-css-extract-plugin。将写入 style 标签内的 css 抽离成一个 用 link 导入 生成的 CSS 文件
  • webpack-parallel-uglify-plugin。开启多过程执行代码压缩,进步打包的速度。
  • clean-webpack-plugin。每次打包前都将旧生成的文件删除。
  • serviceworker-webpack-plugin。为网页利用减少离线缓存性能。

plugin 的应用形式

plugins 中应用

const ServiceworkerWebpackPlugin = require('serviceworker-webpack-plugin')
module.exports = {
    plugins:[new ServiceworkerWebpackPlugin(),
    ]
}

2 编写一个 plugin

思路:plugins 是一个类,webpack 为 plugin 提供了很多内置的 api,须要在原型上定义 apply(compliers) 函数。同时指定要挂载的 webpack 钩子。

class MyPlugin {constructor(params){console.log(params)
    }
    // webpack 初始化参数后会调用这个援用函数,闯入初始化的 complier 对象。apply(complier){
         // 绑定钩子事件
        // complier.hooks.emit.tapAsync()
        compiler.plugin('emit', compilation => {console.log('MyPlugin')
        ))
    }
}
module.export = MyPlugin

compilation 对象 蕴含以后的模块资源、编译生成资源、和能监听变动的文件。每一个文件发生变化后,都会生成一个 compilation 对象,通过 compilation 也能读取到 compiler 对象。
调式plugin 能够应用 node 的调式工具在 package.json 中增加 "debug":"node --inspect --inspect brk node_modules/webpack/bin/webpack.js"

总结编写 plugin 的思路

  1. 编写一个 class 类。
  2. 在类中定义一个 apply 办法。
  3. 在利用办法 apply() 中指定挂载的 webpack 事件钩子complier.hooks.
  4. 解决 webpack 外部实例的特定数据。
  5. 性能实现后调用 webpack 提供的回调。

四、面试题

1. loader 和 plugin 的区别

  1. loader 是一个函数,用来匹配解决某一个特定的模块,将接管到的内容进行转换后返回。在webpack 中操作文件,充当文件转换器的角色。在 modules.rules 中配置。
  2. plugin 是一个插件,不间接操作文件,基于事件流框架 Tapable 实现,plugin 通过钩子能够波及到 webpack 的整一个事件流程。也就是说 plugin 能够通过监听这些生命周期的钩子在适合的机会应用 webpack 提供的 API 做一些事件。在plugins 中配置插件

2. loader 的编写思路

参上

3. plugin 的编写思路

参上

4. complier 和 compilation 区别

  1. complier 对象裸露了 webpack 整一个生命周期相干的钩子,是 webpack 初始化的参数的产物,蕴含 options, entry, plugins 等属性能够简略的了解为 webpack 的一个实例。
  2. compilation 对象是 complier 的实例,是每一次 webpack 构建过程中的生命周期对象。每一个文件发生变化后都能生成一个 complition 对象。
    总结:两个对象都有本人的生命周期钩子,compilation 对象 负责的是粒度更小的生命周期钩子。compiler 对象 是 webpack 整一个整个生命周期钩子的对象。

参考

webpack 之 loader 和 plugin 简介

webpack 构建流程

webpack loader 和 plugin 编写

深刻 Webpack- 编写 Loader

退出移动版