Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >教你手写webpack常用loader

教你手写webpack常用loader

原创
作者头像
gogo2027
发布于 2022-10-18 11:55:07
发布于 2022-10-18 11:55:07
38500
代码可运行
举报
运行总次数:0
代码可运行

前言

webpack 作为目前主流的前端构建工具,我们几乎每天都需要与它打交道。个人认为一个好的开源产品壮大的原因应该包括核心开发者的稳定输出以及对应生态的繁荣。对于生态来说, webpack 是一个足够开放的类库,提供了可插拔的方式去自定义一些配置,包括配置 loaderplugin ,本篇我们主要讨论loader。

loader 本质上是一个函数,webpack在打包过程中会按照规则顺序调用处理某种文件的 loader ,然后将上一个 loader 产生的结果或者资源文件传入进去,当前 loader 处理完成后再交给下一个 loader

loader的类型

开始之前,还是要先大概提一下 loader 的类型以及一些常用的 api ,不感兴趣的同学可以直接跳过这一小节,更详细的指引请参阅官方文档。

loader 主要有以下几种类型:

  • 同步 loaderreturn 或调用 this.callback 都是同步返回值
  • 异步 loader :是用 this.async() 获取异步函数,是用 this.callback() 返回值
  • raw loader :默认情况下接受 utf-8 类型的字符串作为入参,若标记 raw 属性为 true ,则入参的类型为二进制数据
  • pitch loaderloader 总是从右到左被调用。有些情况下,loader 只关心 request 后面的 元数据(metadata),并且忽略前一个 loader 的结果。在实际(从右到左)执行 loader 之前,会先从左到右调用 loader 上的 pitch 方法。

开发 loader 时常用的 API 如下:

  • this.async :获取一个 callback 函数,处理异步
  • this.callback :同步 loader 中,返回的方法
  • this.emitFile :产生一个文件
  • this.getOptions :根据传入的 schema 获取对应参数
  • this.importModule :用于子编译器在构建时编译和执行请求
  • this.resourcePath :当前资源文件的路径

Hello Loader

现在假设我们有这么一个需求:在每个文件的头部打上开发者的相关信息。比如打包之前的文件内容是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const name = 'jay'

打包之后文件内容可能是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/** * @Author:jay * @Email:email@qq.com * /const name = 'jay'

那废话不多说,直接开整。首先把相关依赖安装一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//package.json
"webpack": "^5.0.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.0"

再简单的配置一下webpack:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { resolve } = require('path')
module.exports = {
    mode: 'none',
    entry: './src/main.js',
    output: {
        path: resolve(__dirname, './dist'),
        filename: 'js/[name].js',
        clean: true
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: './loaders/hello-loader',
            },
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ]
}

接下来就可以开始实现这个 loader 了,首先每一个 loader 都是一个函数,这个函数的返回结果要么是二进制数据要么是字符串,字符串就是文件的具体内容,二进制数据就是资源文件比如图片的内容。在上面这个需求中,显然我们只需要拿到文件的内容,做一些修改替换即可。所以可以比较容易的写出下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module.exports = function (content) {
    const newContent = `        /**         * @Author:jay         * @Email:email@qq.com         * */                ${content}
    `

    return newContent;
}

这样就会将对应的内容添加到打包结果中,如下图所示:

在这里插入图片描述
在这里插入图片描述

获取参数

上面对于文件的一些描述我们是已经写死了,但这样不太灵活,大多数时候是希望能通过 loader 对应的配置去获取对应的参数,我们可以在引入 loader 的时候这样改造一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    test: /\.js$/,
    loader: './loaders/hello-loader',
    options: {
        author: 'hello loader',
        email: 'helloloader@qq.com'
    }
}

那么在具体的loader中,可以使用 this.getOptions(schema) 去获取传入的配置。这个 schema 是对 option 的格式校验,代码改造如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const schema = {
    type: 'object', //options是一个对象
    properties: {
        //author是一个字符串
        author: {
            type: 'string'
        },
        //email是一个字符串
        email: {
            type: 'string'
        }
    }
}
const options = this.getOptions(schema) || {}
const { author = 'null', email = 'null' } = options
const newContent = `    /**     * @Author:"${author}"     * @Email:"${email}"     * */    ${content}
`

这样就可以将用户自定义的参数传给处理的 loader ,对于一些需要提供可拓展能力的 loader 来说,获取参数这一步是必不可少的。webpack配置如下,即可使用loader获取参数的能力。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

异步回调

这时候有了一个新需求,希望我们把当前处理的文件内容信息与文件名通过网络传输,以便后续做一些分析。那为了方便我们还是在上面的 loader 进行拓展,实际开发中最好不要这样做,要保证 loader 的单一职责。这时候就不能直接返回结果,而是要获取一个异步 callback 函数,使用这个函数把结果输出。代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const callback = this.async()
// 模拟网络请求
setTimeout(() => {
    callback(null, JSON.stringify(newContent), null, {})
    console.log('net done');
}, 1000)

这里留意一下 callback 函数的用法:callback(error,content,map,meta) ,其中有四个参数,分别的作用是:

  • error :错误信息,如果存在的话则会抛出异常,构建终止
  • content :处理后的内容
  • mapsourceMap 相关信息
  • meta :要传给下一个 loader 的额外信息参数
  • 参考webpack视频讲解:进入学习

JS处理

上面大致举例说明了同步l loader 、异步 loader 以及如何获取 loader 的参数。在这一小结,主要实现开发过程中经常用到的三个 JS 处理相关的 loader

  • eslint-loader :使用 eslint 做代码检测
  • babel-loader :将 ES6+ 语法转换为 ES5 语法
  • uglify-loader :对代码进行压缩混淆

eslint-loader

首先先来实现 eslint-loader ,实现思路是对当前处理的文件调用 eslint 去扫描,如果无错误则继续正常调用下一个 loader 去处理。具体代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const childProcess = require('child_process')
const exec = (command, cb) => {
    childProcess.exec(command, (error, stdout) => {
        cb && cb(error, stdout)
    })
}
const schema = {
    type: 'object',
    properties: {
        fix: 'boolean'
    }
}

module.exports = function (content) {
    const resourcePath = this.resourcePath
    const callback = this.async()
    const command = `npx eslint ${resourcePath}`
    exec(command, (error, stdout) => {
        if (error) {
            console.log(stdout)
        }
        callback(null, content)
    })
}

这里需要理清的是, loader 只是调用了具体工程中的 eslint ,也就是说用到的 eslint 相关的插件以及配置文件都是具体工程提供的,与这个 loader 无关。简单在项目内的 .eslintrc.js 文件下配置了一下引号类型为单引号

在这里插入图片描述
在这里插入图片描述

打包过程如下:

在这里插入图片描述
在这里插入图片描述

配置fix

由上图可以看出, eslint 其实还支持一键修复的能力,由 fix 参数控制。实现 fix 的思路如下:

  • 将文件内容写入到新文件中,对新文件进行 eslint 检测并 fix
  • 读取新文件的内容,返回

代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let id = 0
const schema = {
    type: 'object',
    properties: {
        fix: {
            type: 'boolean'
        }
    }
}
const fs = require('fs')
const path = require('path')
module.exports = function (content) {
    const resourcePath = this.resourcePath
    const callback = this.async()
    const { fix } = this.getOptions(schema) || { fix: false }
    if (fix) {
        const tempName = `./${id++}.js`
        const fullPath = path.resolve(__dirname, tempName)
        // 写入新文件
        fs.writeFileSync(fullPath, content, { encoding: 'utf8' })
        // 带fix检测新文件
        const command = `npx eslint ${fullPath} --fix`
        exec(command, (error, stdout) => {
            if (error) {
                console.log(stdout)
            }
            // 读取新文件
            const newContent = fs.readFileSync(fullPath, { encoding: 'utf8' })
            fs.unlinkSync(fullPath)
            callback(null, newContent)
        })
    } else {
        // 没有选择fix则还是走旧逻辑,没必要读写文件
        const command = `npx eslint ${resourcePath}`
        exec(command, (error, stdout) => {
            if (error) {
                console.log(stdout)
            }
            callback(null, content)
        })
    }
}

这是打包前的文件,可以看到eslint也对它错误标红提示了

在这里插入图片描述
在这里插入图片描述

这是打包后的文件,可以看到配置的检测规则 eslint 已经帮我们修复

在这里插入图片描述
在这里插入图片描述

babel-loader

babel-loader 应该是绝大部份前端项目都会用到的 loader 之一了吧, ES6+ 语法转 ES5 在打包这一步是必不可少的。这里也是依赖 babel 的提供的能力, loader 充当的角色只是一个 API 调用工程师罢了~。稍微灵活一点的是,调用 babel 相关的参数可以从 loader 配置中传进来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    test: /\.js$/,
    loader: './loaders/babel-loader',
    options: {
        presets: ['@babel/preset-env']
    }
}

loader的具体代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const schema = {
    "type": "object",
    "properties": {
        "presets": {
            "type": "array"
        }
    }
}
const babel = require('@babel/core')
module.exports = function (content) {
    const options = this.getOptions(schema);
    const callback = this.async();
    babel.transform(content, options, function (err, result) {
        if (err) {
            callback(err)
        } else {
            callback(null, result.code)
        }
    })
}

可以分别看一下打包前后的效果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

uglify-loader

最后要实现的一个是对代码进行压缩混淆的 loader ,主要是用到的是uglify-js这个十分强大的库,感兴趣的同学可以自行去了解下。我们这里的实现十分简单,只是调用了一下这个库而已。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const uglifyJS = require('uglify-js');
module.exports = function (content) {
    const result = uglifyJS.minify(content)
    const { error, code } = result
    if (error) {
        this.callback(error)
    } else {
        this.callback(null, code)
    }
}

可以稍微看一下打包后的代码:

在这里插入图片描述
在这里插入图片描述

小结

上面我们大概了解与实现了 JS 相关的三个 loader ,这三个 loader 配合起来使用的顺序如下,默认情况下, loader 的执行顺序都是从下往上,从右往左的,注意实际情况下,一般会加一个 exclude 属性,让 loader 不去检测一些文件(比如 node_modules 目录下的文件)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    test: /\.js$/,
    exclude:/node_modules/,
    loader: './loaders/uglify-loader',
},
{
    test: /\.js$/,
    loader: './loaders/babel-loader',
    exclude:/node_modules/,
    options: {
        presets: ['@babel/preset-env']
    }
},
{
    test: /\.js$/,
    loader: './loaders/eslint-loader',
    exclude:/node_modules/,
    options: {
        fix: true
    }
}

CSS处理

处理完 JS 文件之后,我们开始处理 CSS 文件。这里会实现两个常用的 loadercss-loaderstyle-loader 。先分别介绍一下它们的作用:

  • css-loader:处理 CSS 文件的依赖以及资源的加载(因为 webpack 默认只支持 JS 的导入以及一些资源文件的导入,所以我们需要实现对 CSS 文件的导入)
  • style-loader:将 css-loader 处理后的结果输出到文档中

在源码的实现中,使用了 postcss 去分析 CSS 文件,对 CSS 文件中的资源进行了分类处理加载。我们实现没有源码实现那么全,这里实现主要实现两个功能:

  • @import 的实现
  • 图片资源的导入

其中图片资源的导入会放到下小节图片处理中介绍,所以本小结主要实现 @importCSS 文件的输出以及 style-loader

@import与CSS代码输出

先写下一些测试的导入代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//main.js
import './style/index.css'


//index.css
@import './color.css';
.container {
    width: 100px;
    height: 100px;
}

//color.css
@import './bg.css';
.container {
    color: red;
}

//bg.css
.container {
    background: url('../assets/img-168kb.jpeg');
    border: 1px solid red;
}

在这里主要需要处理的应该是 @import 这个关键字,其他的内容就当字符串正常输出即可。由上图可以看出, @import 可以无限嵌套使用,实际上我们要做的就是一棵树的深度优先遍历,递归是比较浅显易懂的处理方式,可以配合注释大概看下下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//css-loader.js

module.exports = async function (content) {
    const callback = this.async()
    let newContent = content
    try {
        newContent = await getImport(this, this.resourcePath, content)
        //这里注意需要这样导出,后续webpack的打包处理会默认当成一个JS文件来处理
        callback(null, `module.exports = ${JSON.stringify(newContent)}`)
    } catch (error) {
        callback(error, '')
    }
}
// 匹配图片
const urlReg = /url\(['|"](.*)['|"]\)/g
// 匹配@import关键字
const importReg = /(@import ['"](.*)['"];?)/
const fs = require('fs')
const path = require('path')
async function getImport(context, originPath, content) {
    let newContent = content
    let regRes, imgRes
    // 获取当前处理文件的父目录
    let absolutePath = originPath.slice(0, originPath.lastIndexOf('/'))
    // 如果当前文件中存在@import关键字,不断匹配处理
    while (regRes = importReg.exec(newContent)) {
        const importExp = regRes[1]
        const url = regRes[2]
        // 获取@import导入的css文件的绝对路径
        const fileAbsoluteUrl = url.startsWith('.') ? path.resolve(absolutePath, url) : url
        // 读取目标文件的内容
        const transformResult = fs.readFileSync(fileAbsoluteUrl, { encoding: 'utf8' })
        // 将@import关键字替换成读取的文件内容
        newContent = newContent.replaceAll(importExp, transformResult)
        // 继续递归处理
        newContent = await getImport(context, fileAbsoluteUrl, newContent)

        // 处理图片
        while (imgRes = urlReg.exec(newContent)) {
            const url = imgRes[1]
            // 获取url方式引入图片的父目录
            let absolutePath = fileAbsoluteUrl.slice(0, fileAbsoluteUrl.lastIndexOf('/'))
            // 获取引入图片的绝对路径
            const imgAbsoluteUrl = url.startsWith('.') ? path.resolve(absolutePath, url) : url
            if (fs.existsSync(imgAbsoluteUrl)) {
                // 调用图片相关loader处理(下一小节实现)
                const transformResult = await context.importModule(imgAbsoluteUrl, {})
                // 将图片loader处理完成的内容替换url
                newContent = newContent.replaceAll(url, transformResult)
            }
        }
    }
    return newContent
}

总结来说,上面代码干了如下几点:

  • 匹配 @import ,获取绝对路径
  • 读取目标文件,将读取到的文件内容替换 @import
  • 如果有图片,则调用相关 loader 处理
  • 当前文件循环处理,引用的文件递归处理,直至 CSS 依赖树构建完成

可以大致看一下打包后的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/***/ ((module) => {

module.exports = '.container {\n    border: 1px solid red;\n    background: url(\'../assets/img-168kb.jpeg\'); \n}\n.container {\n    color: red;\n}\n.container {\n    width: 100px;\n    height: 100px;\n}\n\n'

/***/ })

style-loader

有了上面的打包结果之后,我们只需要把打包结果插入到 DOM 中,就可以实现引入样式文件的功能。大致实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let id = 0
const fs = require('fs')
const path = require('path')
module.exports = function (content) {
    const temp = path.resolve(__dirname,`./${id++}.js`)
    // 将css-loader生成的字符串写入文件
    fs.writeFileSync(temp,content)
    // 读出module.exports
    const res = require(temp)
    fs.unlinkSync(temp)
    // 插入样式
    const insertStyle = `        const style = document.createElement('style');        style.innerHTML = ${JSON.stringify(res)};        document.head.appendChild(style);    `
    return insertStyle
}

这里 style-loader 的实现相对简单,做了如下几件事情:

  • 提取 css-loader 的处理结果(这里取巧使用了读写文件的方式)
  • 插入样式

一起来看看样式生效了没有吧~

在这里插入图片描述
在这里插入图片描述

图片处理

上面我们还没有实现图片的相关 loader

在这里插入图片描述
在这里插入图片描述

毫无疑问的这篇图片引入失败了,因为图片的路径不对。我们接下来会实现三个 loader 去处理图片,分别是:

  • file-loader 处理图片的路径
  • url-loader 将图片转成base64
  • image-loader 压缩图片

file-loader

file-loader 是一个 raw loader ,也就是它接受的内容应该是二进制的图片数据,它要做的有两件事:

  • 将图片输出到打包结果中
  • 将打包结果的图片路径替换代码的路径

代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const loaderUtils = require('loader-utils')
module.exports = function (content, map = null, meta = {}) {
    // 是否被url-loader处理过,处理过的话返回base74,url-loader在下面小结具体实现
    const { url,base64 } = meta
    if (url) {
        return `module.exports = "${base64}"`
    } else {
        // 根据当前的上下文,生成一个文件路径,基于dist打包目录,这里生成的文件地址就是:dist/assets/img.jpg
        const interpolateName = loaderUtils.interpolateName(
            this,
            'assets/[name].[contenthash].[ext][query]',
            { content }
        }
        // webpack特有方法,生成一个文件
        this.emitFile(interpolateName, content);
        return `module.exports = "${interpolateName}"`
    }
}
// 添加标记,表示这是一个raw loader
module.exports.raw = true

有了 file-loader 之后,我们来看看打包结果是怎样的:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以看到文件已经输出到 dist 目录,打包后的文件中引入文件也是正确的,可以正常显示文件了。到这里我们才算把上面说的 CSS 文件导入致实现完毕:

  • 处理 @import
  • 处理图片

image-loader

接下来就是一些锦上添花的内容了,这里做的事情是压缩图片,用到的是images这个开源的图片处理库。可以大概看一下代码,这里没有什么特别的处理,都是上面已经提到过的内容,就不过多赘述。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const images = require('images')
const fs = require('fs')
// 根据全路径取文件后缀
const { getExtByPath } = require('../utils')

const schema = {
    type: 'object',
    properties: {
        quality: {
            type: 'number'
        }
    }
}
module.exports = function (content) {
    const options = this.getOptions(schema) || { quality: 50 }
    const { quality } = options
    const ext = getExtByPath(this)
    const tempname = `./temp.${ext}`
    // 根据传入的压缩程度,生成一张新图片
    images(content).save(tempname, { quality })
    // 读取新图片的内容
    const newContent = fs.readFileSync(tempname)
    fs.unlinkSync(tempname)
    // 返回新图片的内容
    return newContent
}
module.exports.raw = true

url-loader

对于一些小图片,我们可以将它转成 base64 嵌入代码中,这样可以省去一些网络请求的时间,但是转成 base64 之后文件的大小会增大,所以要根据自身的实际情况把控好这里的阈值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const { getExtByPath } = require('../utils')
const schema = {
    type: 'object',
    properties: {
        limit: {
            type: 'number'
        }
    }
}
module.exports = function (content) {
    // 默认值500K
    const options = this.getOptions(schema) || { limit: 1000 * 500 }
    const { limit } = options
    // 超过阈值则返回原内容
    const size = Buffer.byteLength(content)
    if (size > limit) {
        return content
    }
    // 读取buffer
    const buffer = Buffer.from(content)
    const ext = getExtByPath(this)
    // 将buffer转为base64字符串
    const base64 = 'data: image/' + ext + ';base64,' + buffer.toString('base64');
    // 这里返回了第四个参数——meta,表示这张图片已经被url-loader处理过,上层的file-loader应该使用base64变量
    this.callback(null, content, null, { url: true, base64 })
}

module.exports.raw = true

来看看打包后的结果:

在这里插入图片描述
在这里插入图片描述

小结

这三个 loader 的使用顺序一般如下:

  • 先压缩图片
  • 再判断是否可以转成 base64
  • 最后使用 file-loader 输出
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    test: /\.(png|jpe?g|gif)$/,
    loader: './loaders/file-loader',
    type: 'javascript/auto' //让webpack把这些资源当成js处理,不要使用内部的资源处理程序去处理
},
{
    test: /\.(png|jpe?g|gif)$/,
    loader: './loaders/url-loader',
    type: 'javascript/auto', 
    options: {
        limit: 1000 * 500
    }
},
{
    test: /\.(png|jpe?g|gif)$/,
    loader: './loaders/image-loader',
    type: 'javascript/auto', 
    options: {
        quality: 50
    }
}

最后

在本文中主要实现了8个平时会经常接触到的 loader ,包括 JS 的处理、 CSS 的处理、图片的处理。希望能够加深你我对 loader 的理解,在脑海中大概知道它可以做什么,或许有一天遇到问题的时候,你我可以通过这种开发 loader 的方式去解决。

最近在工作中多多少少接触到了一点开发工具的需求——类似于 babel 分析文件、 eslint 插件、 stylelint 插件编写,觉得还是挺有意思的。还有 postcss ,他可以生成 CSSAST ,之后也想去了解一下。当然, loader 都写了, plugin 肯定也得整一篇。接下来应该会对这些相关的工具写一些分享的文章,感兴趣的同学可以留意一下下~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
编写一个 Webpack 的 loader
使用Webpack往往离不开loader的安装配置,手写一个loader其实非常简单,类似手写一个功能函数,下面我们来实现一个替换字符串的loader
EchoROne
2022/08/15
3040
[ webpack ] webpack 的 loader 和 plugin 开发的方法
loader 主要的是处理静态资源,而 plugins 是可以贯穿在整个 webpack 构建的周期中,他能做到 loader 做不到的事情。但是,loader 他可以用独立的运行环境,可以在本地使用一些库进行本地发发调制,而 plugins 不行,他必须编写好这个 plugin 之后在 webpack 构建中将 plugin 放在 plugins 的数组中执行。
GavinUI
2021/06/12
8530
[ webpack ] webpack 的 loader 和 plugin 开发的方法
6-1~2 如何编写一个 loader
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
love丁酥酥
2020/06/02
6110
6-1~2 如何编写一个 loader
手把手教你撸一个 Webpack Loader
文:小 boy(沪江网校Web前端工程师) 本文原创,转载请注明作者及出处 经常逛 webpack 官网的同学应该会很眼熟上面的图。正如它宣传的一样,webpack 能把左侧各种类型的文件(webp
iKcamp
2018/03/30
1.1K0
手把手教你撸一个 Webpack Loader
Webpack编写自己的Loader和Plugin
Loader就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多个翻译员翻译。 以处理SCSS文件为例:
javascript.shop
2019/09/04
7630
如何实现一个Webpack Loader
Loader 是支持链式执行的,如处理 sass 文件的 loader,可以由 sass-loader、css-loader、style-loader 组成,由 compiler 对其由右向左执行,第一个 Loader 将会拿到需处理的原内容,上一个 Loader 处理后的结果回传给下一个接着处理,最后的 Loader 将处理后的结果以 String 或 Buffer 的形式返回给 compiler。 这种链式的处理方式倒是和 gulp 有点儿类似,固然也是希望每个 loader 只做该做的事,纯粹的事,而不希望一箩筐的功能都集成到一个 Loader 中。
前端迷
2019/06/05
1.1K0
webpack 基础知识整理
webpack是一个 模块打包工具,支持所有的打包语法,比如 ES Module、CommonJS、CMD、AMD。初期的webpack是用来模块打包js的,发展到现在,已经可以打包很多种文件类型,比如 css、img 。
神葳
2021/01/22
1.4K0
前端Webpack Loader API 知多少
上篇文章简单介绍了一下如何简单实现一个loader,今天聊一聊Loader API相关的内容。
terrence386
2022/07/14
5100
前端Webpack Loader API 知多少
详解Webpack的loader和plugin编写
loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中。
张张
2019/12/24
2.1K0
多图详解,一次性搞懂Webpack Loader
Webpack 是一个模块化打包工具,它被广泛地应用在前端领域的大多数项目中。利用 Webpack 我们不仅可以打包 JS 文件,还可以打包图片、CSS、字体等其他类型的资源文件。而支持打包非 JS 文件的特性是基于 Loader 机制来实现的。因此要学好 Webpack,我们就需要掌握 Loader 机制。本文阿宝哥将带大家一起深入学习 Webpack 的 Loader 机制,阅读完本文你将了解以下内容:
童欧巴
2021/08/20
1.1K0
多图详解,一次性搞懂Webpack Loader
Webpack - 手把手教你写一个 loader / plugin
也就是说,webpack 把任何文件都看做模块,loader 能 import 任何类型的模块,但是 webpack 原生不支持譬如 css 文件等的解析,这时候就需要用到我们的 loader 机制了。 我们的 loader 主要通过两个属性来让我们的 webpack 进行联动识别:
用户4456933
2021/07/12
5770
Webpack - 手把手教你写一个 loader / plugin
《webpack5 实战四》之loader
webpack 的loader 基础作用相当于一个项目插件,能够将指定文件统一的处理,是一个函数,相当于源码经过这个函数,出去变成了想要的目标。
星宇大前端
2022/03/09
8640
《webpack5 实战四》之loader
看完这篇webpack-loader,不再怕面试官问了
下面会从基本使用开始出发,探究一个loader怎么写,并实现raw-loader、json-loader、url-loader、bundle-loader
lhyt
2020/02/17
1.7K0
webpack实战,手写loader和plugin
对于 webpack 来说, loader 和 plugin 可以算是需求程度最为广泛的配置项了。但是呢,单单止步于配置可能还不够。如果我们自己有时候想要 diy 一个需求,但是 webpack 又没有相关的 loader 和 plugin 。那这个时候我们可能就得开始造点轮子来供给自己使用了。
gogo2027
2022/09/28
5140
实现一个 webpack loader 和 webpack plugin
例如 babel-loader 可以将 ES6 代码转换为 ES5 代码;sass-loader 将 sass 代码转换为 css 代码。
谭光志
2020/09/28
6840
webpack 入门教程
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
老马
2018/08/20
4.3K0
webpack 入门教程
Webpack4 性能优化实践
在使用 Webpack 时,如果不注意性能优化,可能会产生性能问题,会导致在开发体验上不是非常丝滑,性能问题主要是编译速度慢,打包体积过大,因此性能优化也主要从这些方面来分析。本文主要是自己平时的工作积累和参考别人的文章,而进行总结,基于 Webpack4 版本。
发声的沉默者
2021/06/14
1.3K0
Webpack4 性能优化实践
webpack4.x常用配置
yarn init -y yarn add webpack webpack-cli -D
FinGet
2020/01/13
2K0
webpack4.x常用配置
webpack入门指南
1. 导语 github仓库 https://github.com/Rynxiao/webpack-test 1.1 什么叫做webpack webpack is a module bundler. webpack takes modules with dependencies and generates static assets representing those modules. 简单的概括就是:webpack是一个模块打包工具,处理模块之间的依赖同时生成对应模块的静态资源。 1.2 web
糊糊糊糊糊了
2018/05/09
2.4K0
webpack入门指南
Webpack Loader知识分享
原创不易,未经作者允许禁止转载!! 认识Loader Loader可以用于对模块的源代码进行转换; 在加载这个模块时,webpack其实并不知道如何对其进行加载,我们必须定制对应的loader来完成这个功能。 loader配置方式 内联方式:import "css-loader!../css/index.css"; loader和文件路径用!分隔 配置方式:webpack.config.js 配置方式表示的意思是在我们的webpack.config.js文件中写明配置信息 module.rules中允许我
前端LeBron
2021/12/08
5680
Webpack Loader知识分享
相关推荐
编写一个 Webpack 的 loader
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档