Webpack中手动实现Loader与Plugin

发布时间 2023-04-10 16:09:26作者: 菜鸟小何

Loader

loader 是一个转换器,用于对源代码进行转换。

工作流程

  1. webpack.config.js 里配置了一个 模块 的 Loader;
    2.遇到 相应模块 文件时,触发了 该模块的 loader;
    3.loader 接受了一个表示该 模块 文件内容的 source;
    4.loader 使用 webapck 提供的一系列 api 对 source 进行转换,得到一个 result;
    5.将 result 返回或者传递给下一个 Loader,直到处理完毕。

举个例子。

loader.js (将所有含有“小明”字符串 全都改为“老王”)

  module.exports = function (source){
  return source.replace('小明','老王')
}

webpack.config.js

  const path = require('path')

module.exports = {
    mode: 'development',
    entry: {
        main: './src/index.js' //入口文件
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        loader: path.resolve('./src/loader.js'), //我们自己实现的loader
                    },
                ]
            }
        ]
    },
}

index.js(入口文件)

  function test() {
  console.log('你好我是小明')
}
test()

编译后等待输出结果:
bound.js

  /*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/***/ (() => {

eval("function test() {\n  console.log('你好我是老王')\n}\n\ntest()\n\n\n//# sourceURL=webpack:///./src/index.js?"); //小明变成老王了

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval devtool is used.
/******/ 	var __webpack_exports__ = {};
/******/ 	__webpack_modules__["./src/index.js"]();
/******/ 	
/******/ })()
;

上述打包耗时:77ms

异步Loader

loader.js如下

  module.exports = function (source) {
  const callback = this.async()

  // 由于有 3 秒延迟,所以打包时需要 3+ 秒的时间
  setTimeout(() => {
    callback(null, `${source.replace('小明', '老王')}`)
  }, 3000)
}

上述打包耗时:3083ms