首页 » SEO优化 » webpcak添加phploader技巧_手把手教你在Webpack写一个Loader

webpcak添加phploader技巧_手把手教你在Webpack写一个Loader

访客 2024-12-06 0

扫一扫用手机浏览

文章目录 [+]

下面小浪为你大略先容下webpack中的loader

常见的loader

我们先来回顾下常见的 Loader 根本的配置和利用吧(仅仅只是常见的,npm上面开拓者大佬们发布的太多了)

webpcak添加phploader技巧_手把手教你在Webpack写一个Loader

那么开始吧,首先先先容 处理 CSS 干系的 Loader

webpcak添加phploader技巧_手把手教你在Webpack写一个Loader
(图片来自网络侵删)
css-loader 和 style-loader

安装依赖

npm install css-loader style-loader复制代码

利用加载器

module.exports = { // ... module: { rules: [{ test: /.css$/, use: ['style-loader', 'css-loader'], }], },};复制代码

个中module.rules代表模块的处理规则。
每个规则可以包含很多配置项

test 可以吸收正则表达式或元素为正则表达式的数组。
只有与正则表达式匹配的模块才会利用此规则。
在此示例中,/.css$/ 匹配所有以 .css 结尾的文件。

use 可以吸收一个包含规则利用的加载器的数组。
如果只配置了一个css-loader,当只有一个loader时也可以为字符串

css-loader 的浸染只是处理 CSS 的各种加载语法(@import 和 url() 函数等),如果样式要事情,则须要 style-loader 将样式插入页面

style-loader加到了css-loader前面,这是由于在Webpack打包时是按照数组从后往前的顺序将资源交给loader处理的,因此要把末了生效的放在前面

还可以这样写成工具的形式,里面options传入配置

module.exports = { // ... module: { rules: [{ test: /.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { // css-loader 配置项 }, } ], }], },};复制代码

exclude与include

include代表该规则只对正则匹配到的模块生效

exclude的含义是,所有被正则匹配到的模块都打消在该规则之外

rules: [ { test: /.css$/, use: ['style-loader', 'css-loader'], exclude: /node_modules/, include: /src/, }],复制代码

是否都还记得呢,现在有现成的脚手架,很多人都很少自己去配置这些了,欸~当然还有干系的 sass/less等等预处理器loader这里就不一一先容了。

babel-loader

babel-loader 这个loader十分的主要,把高等语法转为ES5,常用于处理 ES6+ 并将其编译为 ES5。
它许可我们在项目中利用最新的措辞特性(乃至在提案中),而无需特殊把稳这些特性在不同平台上的兼容性。

先容下紧张的三个模块

babel-loader:使 Babel 与 Webpack 一起事情的模块@babel/core:Babel核心模块。
@babel/preset-env:是Babel官方推举的preseter,可以根据用户设置的目标环境,自动添加编译ES6+代码所需的插件和补丁

安装

npm install babel-loader @babel/core @babel/preset-env复制代码

配置

rules: [ { test: /.js$/, exclude: /node_modules/, //打消掉,不用除拖慢打包的速率 use: { loader: 'babel-loader', options: { cacheDirectory: true, // 启用缓存机制以防止在重新打包未变动的模块时进行二次编译 presets: [[ 'env', { modules: false, // 将ES6 Module的语法交给Webpack本身处理 } ]], }, }, }],复制代码html-loader

Webpack 可不认识 html,直接报错,须要loader转化

html-loader 用于将 HTML 文件转换为字符串并进行格式化,它许可我们通过 JS 加载一个 HTML 片段。

安装

npm install html-loader复制代码

配置

rules: [ { test: /.html$/, use: 'html-loader', }],复制代码

// index.jsimport otherHtml from './other.html';document.write(otherHtml);复制代码

这样你可以在js中加载另一个页面,写刀当前index.html里面

file-loader

用于打包文件类型的资源,比如对png、jpg、gif等图片资源利用file-loader,然后就可以在JS中加载图片了

安装

npm install file-loader复制代码

配置

const path = require('path');module.exports = { entry: './index.js', output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js', }, module: { rules: [ { test: /.(png|jpg|gif)$/, use: 'file-loader', } ], },};复制代码url-loader

既然先容了 file-loader 就不得不先容 url-loader,它们很相似,但是唯一的差异是用户可以设置文件大小阈值。
大于阈值时返回与file-loader相同的publicPath,小于阈值时返回文件base64编码。

安装

npm install url-loader复制代码

配置

rules: [ { test: /.(png|jpg|gif)$/, use: { loader: 'url-loader', options: { limit: 1024, name: '[name].[ext]', publicPath: './assets/', }, }, }],复制代码ts-loader

TypeScript利用得越来越多,对付我们平时写代码有了更好的规范,项目更加利于掩护...等等好处,我们也在Webpack中来配置loader,实质上类似于 babel-loader,是一个连接 Webpack 和 Typescript 的模块

安装

npm install ts-loader typescript复制代码

loader配置,紧张的配置还是在 tsconfig.json 中

rules: [ { test: /.ts$/, use: 'ts-loader', }],复制代码vue-loader

用来处理vue组件,还要安装vue-template-compiler来编译Vue模板,估计大家大部分都用脚手架了

安装

npm install vue-loader vue-template-compiler 复制代码

rules: [ { test: /.vue$/, use: 'vue-loader', }],复制代码写一个大略的Loader

先容了几个常见的loader的安装配置,我们在详细的业务的实现的时候,可能碰着各种需求,上面先容的或者npm上都没有的加载器都不适宜当前的业务场景,那我们可以自己去实现一个自己的loader来知足自己的需求,小浪下面先容一下如何自定义一个loader

1.初始化项目

初始化项目

先创建一个项目文件夹(名字可以随意,当然肯定是英文名)后进行初始化

npm init -y复制代码

安装依赖

安装依赖:Webpack 和 Webpack脚手架 和 热更新做事器

不同的版本 Webpack 可能有些差异,如果你随着我的这个例子写的话,小浪建媾和我装一样的版本

npm install webpack@4.39.2 webpack-cli@3.3.6 webpack-dev-server@3.11.0 -D复制代码

新建一个index.html文件

dist/index.html

<!DOCTYPE html><html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title></title> </head> <body> <script src="./bundle.js"></script> </body></html>复制代码

新建一个入口文件 index.js 文件

src/index.js

document.write('hello world')复制代码

创建 webpack.config.js 配置文件

配置出口和入口文件

配置devServer做事

const path = require('path')module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, devServer: { contentBase: './dist', overlay: { warnings: true, errors: true, }, open: true, },}复制代码

在 package.json 中配置启动命令

"scripts": { "dev": "Webpack-dev-server" },复制代码

启动 npm run dev

devServer帮我们启动一个做事器,每次修正index.js不须要自己在去打包,而是自动帮我们完成这项任务

页面内容便是我们index.js编写的内容被打包成在dist/bundle.js引入到index.html了

image.png

当前的文件目录

Webpack-demo ├── dist │ └── index.html ├── package-lock.json ├── package.json ├── src │ └── index.js └── Webpack.config.js复制代码2.实现一个大略的 loader

在 src/MyLoader/my-loader.js

module.exports = function (source) { // 在这里按照你的需求处理 source return source.replace('word', ', I am Xiaolang')}复制代码

返回其它结果 this.callback

this.callback( // 当无法转换原内容时,给 Webpack 返回一个 Error err: Error | null, // 原内容转换后的内容 content: string | Buffer, // 用于把转换后的内容得出原内容的 Source Map,方便调试 sourceMap?: SourceMap, // 如果本次转换为原内容天生了 AST 语法树,可以把这个 AST 返回,以方便之后须要 AST 的 Loader 复用该 AST,以避免重复天生 AST,提升性能 abstractSyntaxTree?: AST);复制代码

打开代码对应的source-map,方便调试源代码。
source-map 可以方便实际开拓者在浏览器掌握台查看源代码。
如果不处理source-map,终极将无法天生精确的map文件,在浏览器的开拓工具中可能会看到混乱的源代码。

为了在利用 this.callback 返回内容时将 source-map 返回给 Webpack

loader 必须返回 undefined 让 Webpack 知道 loader 返回的结果在 this.callback 中,而不是在 return

module.exports = function(source) { // 通过 this.callback 见告 Webpack 返回的结果 this.callback(null, source.replace('word', ', I am Xiaolang'), sourceMaps); return;};复制代码

常用加载本地 loader 两种办法

1.path.resolve

利用 path.resolve 指向这个本地文件

const path = require('path')module.exports = { module: { rules: [ { test: /.js$/, use: path.resolve('./src/myLoader/my-loader.js'), }, ], },}复制代码

2.ResolveLoader

先去 node_modules 项眼前探求 my-loader,如果找不到,会再去 ./src/myLoader/ 目录下探求。

module.exports = { //... module: { rules: [ { test: /.js$/, use: ['my-loader'], }, ], }, resolveLoader: { modules: ['node_modules', './src/myLoader'], },}复制代码

一个 loader的职责是单一的,使每个loader易掩护。

如果源文件须要分多步转换才能正常利用,通过多个Loader进行转换。
当调用多个loader进行文件转换时,每个loader都会链式实行。

第一个loader会得到要处理的原始内容,将前一个loader处理的结果通报给下一个。
处理完毕,终极的Loader会将处理后的终极结果返回给 Webpack

以是,当你写loader记得保持它的职责单一,你只关心输入和输出。

image-20220522142823507

3.option参数

module: { rules: [ { test: /.js$/, use: [ { loader: 'my-loader', options: { flag: true, }, }, ], }, ],},复制代码

那么我们如何在loader中获取这个写入配置信息呢?

Webpack 供应了loader-utils工具

在之前写的loader修正

const loaderUtils = require('loader-utils')module.exports = function (source) { // 获取到用户给当前 Loader 传入的 options const options = loaderUtils.getOptions(this) console.log('options-->', options) // 在这里按照你的需求处理 source return source.replace('word', ', I am Xiaolang')}复制代码

掌握台也打印了出来

image-20220522143828316

4.缓存

如果为每个构建重新实行重复的转换操作,这样Webpack构建可能会变得非常慢。

Webpack 默认会缓存所有loader的处理结果,也便是说,当待处理的文件或者依赖的文件没有变革时,不会再次调用对应的loader进行转换操作

module.exports = function (source) { // 开始缓存 this.cacheable && this.cacheable(); // 在这里按照你的需求处理 source return source.replace('word', ', I am Xiaolang')}复制代码

一样平常默认开启缓存,如果不想Webpack这个loader进行缓存,也可以关闭缓存

module.exports = function (source) { // 关闭缓存 this.cacheable(false); // 在这里按照你的需求处理 source return source.replace('word', ', I am Xiaolang')}复制代码5.同步与异步

在某些情形下,转换步骤只能异步完成。

例如,您须要发出网络要求以获取结果。
如果利用同步办法,网络要求会壅塞全体构建,导致构建非常缓慢。

module.exports = function(source) { // 见告 Webpack 本次转换是异步的,Loader 会在 callback 中回调结果 var callback = this.async() // someAsyncOperation 代表一些异步的方法 someAsyncOperation(source, function (err, result, sourceMaps, ast) { // 通过 callback 返回异步实行后的结果 callback(err, result, sourceMaps, ast) })};复制代码6.处理二进制数据

默认情形下,Webpack 通报给 Loader 的原始内容是一个 UTF-8 格式编码的字符串。
但是在某些场景下,加载器处理的不是文本文件,而是二进制文件

官网例子 通过 exports.raw 属性见告 Webpack 该 Loader 是否须要二进制数据

module.exports = function(source) { // 在 exports.raw === true 时,Webpack 传给 Loader 的 source 是 Buffer 类型的 source instanceof Buffer === true; // Loader 返回的类型也可以是 Buffer 类型的 // 在 exports.raw !== true 时,Loader 也可以返回 Buffer 类型的结果 return source;};// 通过 exports.raw 属性见告 Webpack 该 Loader 是否须要二进制数据 module.exports.raw = true;复制代码7.实现一个渲染markdown文档loader

安装依赖 md 转 html 的依赖,当然可以选择其余一个模块 marked

我这里利用的 markdown-it

npm install markdown-it@12.0.6 -D 复制代码

赞助工具 用来添加 div 和 class

module.exports = function ModifyStructure(html) { // 把h3和h2开头的切成数组 const htmlList = html.replace(/<h3/g, '$(<h3').replace(/<h2/g, '$(<h2').split('$(') // 给他们套上 .card 类名的 div return htmlList .map(item => { if (item.indexOf('<h3') !== -1) { return `<div class="card card-3">${item}</div>` } else if (item.indexOf('<h2') !== -1) { return `<div class="card card-2">${item}</div>` } return item }) .join('')}复制代码

新建一个loader

/src/myLoader/md-loader.js

const { getOptions } = require('loader-utils')const MarkdownIt = require('markdown-it')const beautify = require('./beautify')module.exports = function (source) { const options = getOptions(this) || {} const md = new MarkdownIt({ html: true, ...options, }) let html = beautify(md.render(source)) html = `module.exports = ${JSON.stringify(html)}` this.callback(null, html)}复制代码

这样loader也写完了,this.callback(null, html) 和 return 在这里差不多哈。

html = `module.exports = ${JSON.stringify(html)}`复制代码

这里解析的结果是一个 HTML 字符串。
如果直接返回,也会面临Webpack无法解析模块的问题。
精确的做法是把这个HTML字符串拼接成一段JS代码。

这时候我们要返回的代码便是通过module.exports导出这个HTML字符串,这样外界在导入模块的时候就可以吸收到这个HTML字符串。

然后在webpack.config.js利用这个加载器

const path = require('path')module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, module: { rules: [ { test: /.js$/, use: [ { loader: 'my-loader', options: { flag: true, }, }, ], }, { test: /.md$/, use: [ { loader: 'md-loader', }, ], }, ], }, resolveLoader: { modules: ['node_modules', './src/myLoader'], }, devServer: { contentBase: './dist', overlay: { warnings: true, errors: true, }, open: true, },}复制代码

利用

末了在index.js中加载一个md文件,我这里随便全体,新建github的readme.md

document.write('hello word')import mdHtml from './test.md'const content = document.createElement('div')content.className = 'content'content.innerHTML = mdHtmldocument.body.appendChild(content)复制代码

结果图

image-20220522165928553

目录构造

Webpack-demo ├── dist │ └── index.html ├── package-lock.json ├── package.json ├── src │ ├── index.js │ ├── myLoader │ │ ├── beautify.js │ │ ├── md-loader.js │ │ └── my-loader.js │ └── test.md └── webpack.config.js复制代码

github仓库地址[1]

结语

感谢大家能看到这里哈~ ,现在打包构建工具也逐步增多了vue-cli,vite等等,但是 webpack 仍旧有一席之地,很多值得学习的地方,连续努力学习~~

来源:小浪努力学前端,https://juejin.cn/post/7100534685134454815

同时收录于小程序-互联网小兵,涵盖前端、后端、移动端、算法、人工智能等领域的精良技能文章,技能人小程序,希望支持支持!

标签:

相关文章