当前位置: 首页 > 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.lryc.cn/news/573653.html

相关文章:

  • Linux内核中安全创建套接字:为何inet_create未导出及正确替代方案
  • SAP金属行业解决方案:无锡哲讯科技助力企业数字化转型与高效运营
  • Kafka Streams架构深度解析:从并行处理到容错机制的全链路实践
  • 针对数据仓库方向的大数据算法工程师面试经验总结
  • netcore url编码/解码
  • [计算机网络] 局域网内的网络传输
  • SpringBoot+Vue服装商城系统 附带详细运行指导视频
  • 3dgs涉及的基本概念:球谐系数(SH 系数)等
  • Python之数据容器
  • 【JavaScript】代码整理
  • vim学习流程,以及快捷键总结
  • Python 深度学习基础:TensorFlow 入门——从张量到神经网络的实战指南
  • 【2025年软考中级】第三章数据结构3.4 数组与矩阵
  • Flink作业三种部署模式:架构、配置与实战应用
  • rknn优化教程(三)
  • Bytemd@Bytemd/react详解(编辑器实现基础AST、插件、跨框架)
  • 【云原生】Docker 部署 Elasticsearch 9 操作详解
  • Git Worktree:高效开发的秘密武器
  • C# 数组(数组协变和数组继承的有用成员)
  • webpack+vite前端构建工具 - 8 代码分割
  • 【数据结构试题】
  • C#Halcon从零开发_Day13_几种阈值分割方法
  • 《高等数学》(同济大学·第7版)第五章 定积分 第四节反常积分
  • 目标检测neck算法之MPCA和FSA的源码实现
  • python实战项目77:足球运动员数据分析
  • React 18.2.0 源码打包
  • C++智能指针的知识!
  • 无人机表演越来越火,C端市场大爆发
  • Java基础八股文 - 面试者心理历程与标准答案
  • 微处理器原理与应用篇---常见基础知识(7)