当前位置: 首页 > news >正文

webpack+vite前端构建工具 -6从loader本质看各种语言处理 7webpack处理html

6 从loader本质看各种语言处理

语法糖?

6.1 loader的本质

  • loader本质是一个方法,接收要处理的资源的内容,处理完毕后给出内容,作为打包结果。

    所有的loader(例如babel-loader, url-loader等)export出一个方法。注册loader去处理某种类型文件。

6.1.1 手搓一个loader

1 定义loader
// mycss-loader\index.js
module.exports = function (cssContent) {console.log("🚀 ~ cssContent:", cssContent);// 将0变为0pxcssContent = cssContent.replace("0", "0px");return cssContent;
}
2 注册loader
// webpack.config.js
module.exports = {mode: "production", //webpack4以后要指定mode// loadermodule: {rules: [{test: /\.css/,use: [minicss.loader, "css-loader", "./mycss-loader"]},]}
}

最先调用mycss-loader.
注意路径,mycss-loader在当前目录下。

3 打包

打包出来的css文件里的padding,变为0px。
在这里插入图片描述

6.1.2 loader本质

  • 从手搓的mycss-loader可以推测babe-loader

    • 【babel-loader编译】通过babel-loader编译js,即babel-loader函数接收js文件内容,对es6字符串编译为es5字符串等等。
  • 同理,编译ts, jsx都是这样,目标都是转换为js.

  • 基本上各种语言处理可以看做

    1. 为改语言编写loader
    2. 编写loader配置

6.2 ts编译打包

6.2.1 安装ts的编译loader和编译库

命令:npm install typescript ts-loader --save-dev

6.2.2 定义编译规则

ts规则较多,可以集成到单独的文件tsconfig.json里。

// webpack.config.js
module.exports = {mode: "development", //webpack4以后要指定mode// loadermodule: {rules: [{test: /\.tsx?$/,//匹配ts,tsx文件use: {loader: 'ts-loader'}}]}
}
// tsconfig.json
// 暂时为空

定义ts文件

// ts1.ts
let a: number = 123;
console.log("🚀 ~ a:", a);

在app.js里引入ts1.ts

// app.js
import b from './a.js'
import "./test.css"
import img1 from "./img/两狗对视.jpg"
import './ts1.ts';
new Image().src = img1;
(() => {let a = 23;console.log(b);console.log(a);
})()

6.2.3 打包

ts语言在打包文件里编译为js语言
在这里插入图片描述

6.3 规律总结

项目里所有的loader都是如此。面对新的loader,要学会如何使用,只需要查一下相关配置即可。
记义不记形。

7 webpack处理html

前面介绍了webpack处理js、css等,还剩下html。
一个项目在浏览器展示,先拿到html文件。

  • 项目的3要素
    • html
    • js
    • css
浏览器htmljs执行js,创建内容
css执行css渲染样式

解读:先拿到项目的html,然后html加载js和css。加载js后执行js,创建内容。加载css后执行css,渲染页面样式。
html是起点。

  • 需要html做什么
    • 提供html模版,复用固定内容
    • 打包时生成一个html
    • 打包的html自动引入打包后的js, css

7.1 示例

7.1.0 html文件

<!-- index.html -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>webpackhtml</title>
</head><body><div id="app"></div>
</body></html>

快捷键: !

7.1.1 安装plugin

  • 使用插件处理html而非loader
  • 为什么不用loader
    • loader本质:webpack只能识别js,让webpack识别引入的其他文件需要用loader
    • 但html不需要webpack识别,而是作为载体去承载打包后的js文件
    • 因此webpack不需要识别html,只是用html承接weboack处理的结果(几乎不可能需要在js文件里import html文件)
    • 因此不使用loader处理html
  • 需要做什么
    • 拿到html模板,将打包后的内容加入到html文件中

    因此不是处理html,而是使用html去处理打包结果

安装命令:npm install html-webpack-plugin --save-dev

7.1.2 引入plugin

// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');

7.1.3 注册plugin

// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html"})]
}

7.1.4 打包

打包结果
在这里插入图片描述
打包后的html
可以看到引入了打包后的js和css文件

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>webpackhtml</title>
<script defer src="app1.34fb.bundle.js"></script><link href="test.bundle.css" rel="stylesheet"></head><body><div id="app"></div>
</body></html>

如果mode为production,打包后的index.html会压缩为一行代码

7.2 多入口情况

  • 传统vue项目是单入口(单页面项目)。
    • vue项目中页面的切换,本质还是同一个页面,只是执行不同的js创建不同的内容
  • 多入口,即多个页面,用于多个html的情况。切换页面时是切到另外一个html文件。
    • 多入口,表示多个js文件。

下面给出多入口处理的示例

7.2.0 多入口html文件

在原来基础上加入一个app2.js.

// app2.js
console.log("app2.js")

7.2.1 多入口文件打包配置

webpack.config.js的entry添加app2.js.

// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {// entry: "./app.js",//单入口写法,入口指定为app.jsentry: {  // 多入口写法:入口名称+入口文件app1: ["./app.js"],app2: './app2.js'},// entry: ["./app.js", './app2.js'] // 两个文件同时作为一个入口output: {path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径filename: "[name].[hash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位},mode: "production", //webpack4以后要指定mode// loadermodule: {rules: []},plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html"})]
}

7.2.2 打包

1 打包结果

打包结果包含两个js文件。
在这里插入图片描述
两个js文件在html如何加载呢
——都加到index.html里。

在这里插入图片描述

2 问题
  • 多入口意味着多个html,每个入口js应该有自己的html。
  • 正确逻辑:每个打包的js文件都应该有专属的html,html只引入一个js文件,而不是一个html文件引入2个js文件。
  • 正确做法:再new一个html-webpack-plugin插件

app2.js的html模板可以是之前的index.html,也可以指定新的,例如index2.html.

3 正确配置并打包

index2.html就不赘述了,与index.html一样的。

  • webpack.config.js的plugin再加一个plugin,用于给app2.js指定html模板,即index2.html.
  • 注意还加了chunks属性,注意chunks的值要与entry的key对应。
// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {// entry: "./app.js",//单入口写法,入口指定为app.jsentry: {  // 多入口写法:入口名称+入口文件app1: ["./app.js"],app2: './app2.js'},// entry: ["./app.js", './app2.js'] // 两个文件同时作为一个入口output: {path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径filename: "[name].[hash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位},mode: "production", //webpack4以后要指定mode// loadermodule: {rules: []},plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html",chunks: ["app1"]}),new htmlwebpack({template: './index2.html',filename: "index2.html",chunks: ["app2"]})]
}

打包完成,可以看到有2个html,每个html各引入对应的js.
在这里插入图片描述

7.3 其他配置项

7.3.1 代码不处理压缩

打出来的代码是压缩后的,不便于阅读,可以稍加配置(minify属性)。
在这里插入图片描述

// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {// entry: "./app.js",//单入口写法,入口指定为app.jsentry: {  // 多入口写法:入口名称+入口文件app1: ["./app.js"],app2: './app2.js'},// entry: ["./app.js", './app2.js'] // 两个文件同时作为一个入口output: {path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径filename: "[name].[hash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位},mode: "production", //webpack4以后要指定mode// loadermodule: {rules: []},plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html",chunks: ["app1"],            minify: {collapseInlineTagWhitespace: false, // 是否一行展示removeComments: false, //是否移除注释removeAttributeQuotes: false, //是否移除属性之间的多余空格}}),new htmlwebpack({template: './index2.html',filename: "index2.html",chunks: ["app2"]})]
}

配置后打包出来的index.html

// dist\index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>webpackhtml</title>
<script defer="defer" src="app1.506b.bundle.js"></script><link href="test.bundle.css" rel="stylesheet"></head><body><div id="app"></div>
</body></html>

7.3.2 js加载位置

  • 可以看到目前script标签是加载在head标签里的。是否可以指定js文件的加载位置(默认加载到head标签)?
    • 加入inject属性,值为body.
// webpack.config.js
const htmlwebpack = require('html-webpack-plugin');
module.exports = {// entry: "./app.js",//单入口写法,入口指定为app.jsentry: {  // 多入口写法:入口名称+入口文件app1: ["./app.js"],app2: './app2.js'},// entry: ["./app.js", './app2.js'] // 两个文件同时作为一个入口output: {path: __dirname + '/dist', // 绝对路径,__dirname是node的全局变量,表示当前目录的绝对路径filename: "[name].[hash:4].bundle.js", //将name加到filename里,打包结果文件是app.bundle.js和app2.bundle.js,hash是对文件是否有改变的标志,:4表示截取前4位},mode: "production", //webpack4以后要指定mode// loadermodule: {rules: []},plugins: [new htmlwebpack({template: './index.html',// 写法1,指定html模板// templateContent: function () {  // 写法2,自定义模板,使用频率较低//     return '<div>123</div>'// }filename: "index.html",chunks: ["app1"],            minify: {collapseInlineTagWhitespace: false, // 是否一行展示removeComments: false, //是否移除注释removeAttributeQuotes: false, //是否移除属性之间的多余空格},inject: "body" // 指定js加载位置: body|true(加载到body中), head, false(不加载)}),new htmlwebpack({template: './index2.html',filename: "index2.html",chunks: ["app2"]})]
}

在这里插入图片描述

7.3.3 其他配置

html的标题title标签支持可配置,也可在webpack.config.js设置。

vue项目可以实现处理,这部分就不看了。

http://www.lqws.cn/news/475075.html

相关文章:

  • 案例:塔能科技以“数字光网”重塑某市照明绿色生态
  • Docker 运行RAGFlow 搭建RAG知识库
  • LeapMotion-PhysicalHandsManager 类详解
  • 7.5.1散列表的基本概念
  • 测试工程师实战:用 LangChain+deepseek构建多轮对话测试辅助聊天机器人
  • 深入解析Flink Local模式启动流程源码:揭开作业初始化的神秘面纱
  • vue3 el-table 行颜色根据 字段改变
  • 企业级安全实践:SSL 加密与权限管理(二)
  • python 常见数学公式函数使用详解
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(三十六) -> 配置构建(三)
  • swift-17-字面量协议、模式匹配、条件编译
  • Java 21 的虚拟线程与桥接模式:构建高性能并发系统
  • Kafka Streams入门与实战:从概念解析到程序开发
  • 架构总结记录
  • VSCode性能调优:从卡顿到丝滑的终极方案
  • C++法则11:没有“顶层 const 引用“
  • 16_设备树中的remote-endpoint演示基于视频字符设备Linux内核模块
  • 深度实战|星环OS三大创新场景解密:如何用确定性技术重构智能汽车安全与体验?
  • Unity高性能无GC图表
  • RSA加密原理及推导
  • 跨个体预训练与轻量化Transformer在手势识别中的应用:Bioformer
  • 深入解析ID3算法:信息熵驱动的决策树构建基石
  • 为车辆提供路径规划解决方案:技术演进、挑战与未来蓝图
  • 微处理器原理与应用篇---CISCRISC指令集架构
  • 2025最新Python 100个常用函数在线体验项目
  • 索引——高效查询的关键
  • python中学物理实验模拟:凸透镜成像和凹透镜成像
  • Python 的内置函数 hash
  • `shallowReactive` 与 `shallowRef`:浅层响应式 API
  • 从零开发ComfyUI插件:打造你的AI绘画专属工具