Webpack中手动实现Loader与Plugin

webpack,手动,实现,loader,plugin · 浏览次数 : 31

小编点评

**Loaderloader** 是一个 webpack 模块的转换器,用于对源代码进行转换。 **工作流程**: 1. **加载模块**:当遇到相关模块文件时,webpack触发模块的 loader。 2. **加载源代码**:loader 接收源代码的源文件内容。 3. **转换代码**:loader 使用 webapck 提供的一系列 api 对源代码进行转换,例如替换或添加代码。 4. **返回结果**:loader 返回一个结果,或将其传递给下一个 Loader。 **示例**: ```js // loader.js function (source) { return source.replace('小明', '老王')} // webpack.config.js module.exports = { // ...其他配置 ... module: { rules: [ { test: /\\.js$/, use: [ { loader: path.resolve('./src/loader.js'), // 自定义 loader }, ] } ] } } ``` 当 webpack 加载 `main.js` 时,loader 会被触发并对 `index.js` 的代码进行转换。最终,编译后的输出为 `bundle.js`,其中 `index.js` 中的 `小明` 被替换为 `老王`。 **其他信息**: * loader 只能对源文件代码进行转换,不能处理外部资源或网络请求。 * loader 可以使用 `async` 和 `await` 语句进行异步操作。 * loader 在整个编译周期中会被调用多次,因为每个模块可能需要执行不同的 loader。

正文

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

Plugin

webpack 在整个编译周期中会触发很多不同的事件,plugin 可以监听这些事件,并且可以调用 webpack 的 API 对输出资源进行处理。这是它和 loader 的不同之处,loader 一般只能对源文件代码进行转换,而 plugin 可以做得更多。plugin 在整个编译周期中都可以被调用,只要监听事件。

名词解释

对于 webpack 编译,有两个重要的对象需要了解一下:

Compiler 和 Compilation
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

组成部分:

  1. 一个 JavaScript 命名函数。
  2. 在插件函数的 prototype 上定义一个 apply 方法。
  3. 指定一个绑定到 webpack 自身的事件钩子。
  4. 处理 webpack 内部实例的特定数据。
  5. 功能完成后调用 webpack 提供的回调

举个例子

plugin.js

  function Plugin(options) { }

Plugin.prototype.apply = function (compiler) {
    // 所有文件资源都被 loader 处理后触发这个事件
    compiler.plugin('emit', function (compilation, callback) {
        // 功能完成后调用 webpack 提供的回调
        console.log('Hello World')
        callback()
    })
}

module.exports = Plugin

使用:

const Plugin = require('./src/plugin')

module.exports = {
	...
    plugins: [
        new Plugin()
    ]
}

更复杂的例子:
经过 loader 处理后的打包文件 bundle.js 引入到 index.html 中:

function Plugin(options) { }

Plugin.prototype.apply = function (compiler) {
    // 所有文件资源经过不同的 loader 处理后触发这个事件
    compiler.plugin('emit', function (compilation, callback) {
        // 获取打包后的 js 文件名
        const filename = compiler.options.output.filename
        // 生成一个 index.html 并引入打包后的 js 文件
        const html = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="${filename}"></script>
</head>
<body>
    
</body>
</html>`
        // 所有处理后的资源都放在 compilation.assets 中
        // 添加一个 index.html 文件
        compilation.assets['index.html'] = {
            source: function () {
                return html
            },
            size: function () {
                return html.length
            }
        }

        // 功能完成后调用 webpack 提供的回调
        callback()
    })
}

module.exports = Plugin

使用方式如上
结果:会生成一个html并且自动引入了bound.js

与Webpack中手动实现Loader与Plugin相似的内容:

Webpack中手动实现Loader与Plugin

Loader loader 是一个转换器,用于对源代码进行转换。 工作流程 webpack.config.js 里配置了一个 模块 的 Loader; 2.遇到 相应模块 文件时,触发了 该模块的 loader; 3.loader 接受了一个表示该 模块 文件内容的 source; 4.loader

浅析Vite本地构建原理

前言 随着Vue3的逐渐普及以及Vite的逐渐成熟,我们有必要来了解一下关于vite的本地构建原理。 对于webpack打包的核心流程是通过分析JS文件中引用关系,通过递归得到整个项目的依赖关系,并且对于非JS类型的资源,通过调用对应的loader将其打包编译生成JS 代码,最后再启动开发服务器。

公共模块之模块联邦

目录 前言 模块联邦概念 使用配置 模块联邦优点 模块联邦缺点 动态远程模块 前言 工作中公共模块通过子仓库在多个项目中使用,其中公共头部,登录,反馈、举报等模块业务与技术栈都和项目耦合很深,在每个项目都会将这些公共模块打包进去,为了减少流量成本,考虑将这些模块打包后放到cdn,对比了webpack

Webpack5构建性能优化:构建耗时从150s到60s再到10s

近期对Webpack5构建性能进行了优化,构建耗时从150s到60s再到10s,下面详细讲解下优化过程。

webpack与其常见loader加载器使用方式

webpack是什么 webpack是前端项目工程化的具体解决方案。 主要功能:提供了友好的前端模块化开发支持,已经代码压缩混淆(去除空格和注释,让文件体积更小),处理浏览器端JS的兼容性(将箭头函数转成低级实现,let->var实现,兼容版本低的浏览器),性能优化等。 让程序员把重心放到具体的功能

安装node.js与webpack创建vue2项目

转载请注明出处: 1.安装node.js 下载地址:http://nodejs.cn/download/ (可查看历史版本) node.js 中文网:http://nodejs.cn/api-v16/ 建议下载稳定版本的msi 格式的进行安装;msi 为windows 直接安装包,一直next即可;

浅析 SplitChunksPlugin 及代码分割的意义

起因 有同事分享webpack的代码分割,其中提到了SplitChunksPlugin,对于文档上的描述大家有着不一样的理解,所以打算探究一下。 Q:什么是 SplitChunksPlugin?SplitChunksPlugin 是用来干嘛的? A: 最初,chunks(以及内部导入的模块)是通过内

模块化打包工具-初识Webpack

打包工具解决的是前端整体的模块化,不只是局限于js的模块化,打包工具需要完成的功能有:1.模块打包:完成多个模块的打包,将多个模块的js文件打包到一个js里面。2.loader转换: 以webpack为例,可以使用loader完成格式的转换,改善兼容性问题。 3.代码拆分:可以拆分不同模块的代码,没...

Django 静态文件管理与部署指南

title: Django 静态文件管理与部署指南 date: 2024/5/10 17:38:36 updated: 2024/5/10 17:38:36 categories: 后端开发 tags: WebOpt CDN加速 DjangoCompress Webpack StaticDeploy

Vue CLI 4与项目构建实战指南

这篇文章介绍了如何使用Vue CLI优化项目构建配置,提高开发效率,涉及配置管理、项目部署策略、插件系统定制以及Webpack和TypeScript的深度集成技巧。