• webpack5学习进阶:模块、依赖与扩展功能(PostCSS、Web Works、TypeScript)



    在开发过程中,我们会把程序分解为功能离散的文件,这些文件就是模块;

    一、webpack 模块

    1、webpack 支持的模块

    ES6 的 import/export/export default 语句
    commonJS 的 require/module.exports 语句
    AMD 的 define 和 require 语句
    CSS 等样式库的 @import 语句
    样式里面 url 引入的资源

    总体来说 webpack 天生就支持 ECMAScript、CommonJS、AMD、Assets 等模块;同时 webpack 的 loader 也可以使 webpack 可以支持多种语言和预处理语法来编写模块;

    2、webpack 模板解析的简易原理

    webpack 将 js、css、less、img、html 等文件通过 loader 以及 webpack 内置的一些模块方法解析成模块化文件;

    打包编译的解析过程:
    1、webpack 执行会返回一个描述 webpack 打包编译整个流程的对象:compiler ;
    2、compiler 对象内置了一个打包状态,随着打包的进行状态也会实时的发生变更,同时会触发相应状态的 webpack 钩子函数;
    3、每一个 webpack 打包都会创建一个 compiler 对象,它会走完整个生命周期的过程,webpack 所有模块的解析都是 compiler 对象内置模块的解析器(resolvers)去工作的;
    4、resolver 的主体功能就是解析模块,它是基于 enhanced-resolve 这个包来实现的,所以在 webpack 中无论使用什么样的模块引用语句,最终都是使用 enhanced-resolve 这个包的 API 来实现模块解析的;

    二、模块解析(resolve)

    webpack 通过 resolvers 实现模块之间的依赖和引用;resolver 帮助 webpack 从每一个 require/import 语句中找到需要引入的模块代码;当打包的时候 webpack 使用 enhanced-resolve 来解析文件路径;

    1、解析路径

    webpack 能解析三种文件路径:相对路径、绝对路径、模块路径;
    1、绝对路径:相对于项目的根目录作为参考的路径(‘/src/util/test.js’),第一个 / 就代表根目录;
    2、相对路径:相对于文件本身作为参考的路径(‘./util/test.js’),./ 表示进入文件;
    3、模块路径:引入第三方模块的时候,直接通过模块名(‘lodash’);

    2、目录(路径)配置别名

    如果我们的目录层级比较深,那么我们在内部的文件中引入外部的文件就会需要多次使用 ‘…/’ 来找到外部的文件;这也操作起来会比较麻烦;所以我们可以给特定文件夹下的目录起个别名:

    const path = require('path')
    module.exports={
    	resolve:{
    		alias:{
    			"@":path.resolve(__dirname,'./src')
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这样 @ 就可以直接访问到 src 这个目录下的文件了,此时 @ 指向就是 src;

    "../../../../../../../../util/tset"
    //替换为
    "@/util/test"
    
    • 1
    • 2
    • 3

    3、配置文件的扩展名

    在引入文件的时候,webpack 会默认帮我们查找一些具有某个文件名的文件,因此我们在引入文件时可以不用带上后缀名;但是如果我们有相同文件名后缀不一样的两个文件(test.js、test.json),在引入时不携带后缀名,webpack 会帮我们找到对应名称的 js 文件,而不是 json 文件;这是因为 webpack 默认的优先级配置;

    当然我们也可以修改 webpack 默认的配置:

    module.exports = {
    	extensions:[".json", ".js", ".vue"]
    }
    
    • 1
    • 2
    • 3

    这样上面的引入,webpack 会帮我们找到 json 文件;

    三、外部扩展(Externals)

    1、引入 cdn 文件

    有时候为了减小 bundle 文件的体积,我们需要把一些不变的第三方库用 cdn 的形式引入进来;

    //index.html
    
    
    • 1
    • 2

    这个时候我们想在代码中使用引入的 jquery ,但是三种模块引入方式都不行,webpack 给我们提供了 Externals 的配置属性,让我们配置外部扩展模块:

    module.exports = {
    	plugins:[
    		new HtmlPlugin({
    			template:'./index.html'
    		})
    	],
    	externals:{
    		jquery:'jQuery'
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后在页面中引入

    import $ from 'jquery'
    
    • 1

    这也就可以正常使用 JQuery 了;

    2、改造

    如果我们不想自己手动引入 cdn 在 html 文件中,想让 webpack 自动生成一个 html 并且帮我们自动引入 script 标签,并且引入 cdn;我们只需要下面的操作:首先删除 index.html;

    module.exports = {
    	plugins:[
    		new HtmlPlugin()
    	],
    	externalsType:'script',
    	externals:{
    		jquery:[
    			"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js",
    			"jQuery"
    		]
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    不需要手动 Html 引入,只需要上面的配置就可以自动生成的 HTML 文件中自动引入 jquery 的 cdn 文件;

    四、依赖图(dependency graph)

    每当一个文件依赖另一个文件时, webpack 就会认为这两个文件存在依赖关系;这也就让 webpack 可以获取非代码资源(图片,字体)等,并把它们作为依赖提供给应用程序;
    当 webpack 开始工作时,它会根据我们写的配置,从入口(entyr)开始,递归构建一个依赖关系图,这个依赖图包含应用程序所有的模块,然后将所有模块打包为 bundle(也就是出口(output)配置项);

    1、bundle 分析工具

    1、webpack-chart:生成一个可交互的饼图;
    2、webpack-visualizer:可视化,并分析你的 bundle ,检查那些模块占用空间,那些是可以重复使用的;
    3、webpack-bundle-analyzer:一个 plugin 和 cli 工具,将 bundle 内容展示成一个便捷的、交互式、可缩放的树状图;
    4、webpack bundle optimize helper:分析 bundle 并提供可操作的改进措施,以减少 bundle 的大小;
    5、bundle-stats:生成 bundle 报告(大小、资源、模块)并比较不同构建之间的结果;

    2、webpack-bundle-analyzer

    安装

    npm i webpack-bundle-analyzer -D
    
    • 1

    安装成功之后在 webpack.config.js 中引入使用

    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
    module.exports = {
    	plugins:[
    		new BundleAnalyzerPlugin()
    	]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后运行项目,就可以自动打开一个浏览器,里面可以看到下面这种关系图:
    在这里插入图片描述
    stat:统计信息,可以看到每个模块的互相依赖的图,以及每个模块的大小信息;
    parsed:解析以后的模块结果,以及模块大小信息;
    gzipped:压缩以后的模块,以及模块大小信息;

    五、扩展功能

    1、PostCSS 与 css 模块

    PostCSS :是一个用 JavaScript 工具和插件转换 CSS 代码的工具;比如可以使用 Autoprefixer 插件自动获取浏览器的流行度和能够支持的属性,并根据这些数据自动为 CSS 添加前缀,将最新的 CSS 语法转换成大多数浏览器能够理解的语法;
    CSS模块:就是所有的类名都只有局部作用域的 CSS 文件;CSS 模块不是浏览器中的官方标准,是改变类名和选择器的作用域到当前文件的构建过程;

    1.1、PostCSS 使用

    webpack 中使用 PoseCSS 需要安装 style-loader、css-loader、postcss-loader:
    安装:

    npm i style-loader css-loader postcss-loader -D
    
    • 1

    安装之后使用

    module.exports={
    	module:{
    		rules:[
    			{
    				test:/\.css$/,
    				use:['style-loader','css-loader','postcss-loader']
    			}
    		]
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个时候我们可以在浏览器上查看,并没有做浏览器的兼容设置;

    我们想要使用具体的功能还需要安装对应的插件:我们在安装一个插件 autoprefixer 来加载样式的前缀;

    npm i autoprefixer -D
    
    • 1

    新增文件 postcss.config.js 来配置 css 的插件;

    module.exports = {
    	plugins:[
    		require('autoprefixer')
    	]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在 package.json 中约定浏览器的版本:

    "browserslist": [
        "> 1%", //全球浏览器的使用率要大于1%
         "last 2 versions"//每个浏览器最新的两个版本
     ],
    
    • 1
    • 2
    • 3
    • 4

    这样浏览器的样式就会出现带有前缀的:
    在这里插入图片描述
    插件会自动帮助我们找到当前浏览器支持的样式,并添加前缀;

    如果想在样式里面写嵌套可以安装插件: postcss-nested(这种嵌套样式会被编译成浏览器可以识别的样式)

    1.2、CSS 模块给样式类添加唯一的名字

    开启 CSS 模块;

    module.exports={
    	module:{
    		rules:[
    			{
    				test:/\.css$/,
    				use:[
    					'style-loader',
    					{
    						loader:'css-loader',
    						options:{
    							modules:true
    						}
    					},
    					'postcss-loader'
    				]
    			}
    		]
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这个时候我们的类名就会变成一个 hash 字符串类型的唯一标识;
    在这里插入图片描述
    由于编译后的类名变了,我们在使用的时候也需要换一种方式来使用:在引入css的时候把 css 文件作为一个模块来引入

    import styles from ''./app.css"
    
    const div = document.createElement('div')
    div.textContent = 'hello webapck'
    div.classList.add(styles.box) //使用
    document.body.appendChild(div)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1.3、部分开启 CSS 模块

    css 文件名统一使用 module 关键字进行识别,在 module 里面增加一个规则来匹配这种类型的文件:xxx.module.css

    {
    	test:new PegExp(`^(.*\\.module).*\\.css`),
    	use:[
    		'style-loader',
    		{
    			loader:'css-loader',
    			options:{
    				modules:true
    			}
    		},
    		'postcss-loader'
    	]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、Web Works

    如果一个 js 运算量比较大,执行时间比较长,我们又不想让它阻塞 js 的循环以及 ui 的渲染,这时候我们考虑使用一下 Web Works ;

    Web Works 提供了 js 的后台处理线程的 API,允许我们将复杂的、耗时的 js 逻辑放在浏览器的后台线程里进行处理,让 js 线程不阻塞 ui 线程从渲染;
    定义works:

    new Worker(scriptURL:string | URL,options?:WorkerOptions)
    
    • 1

    新建 work.js 文件,放置线程运行的代码

    self.onmessage = (message) => {
    	self.postMessage({//发送
    		msg:123
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在入口文件中创建一个 web works 来引用刚才的 worker;

    const worker = new Worker(new URL('./work.js',import.meta,url))
    worker.postMessage({
    	question:"hello"
    })
    worker.onmessage = (message) =>{//接收消息
    	console.log(message)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这样,打包的时候 webpack 会帮 Web Works 做一个额外的打包;

    3、TypeScript

    安装 TS 及相应的 loader

    npm i typescript ts-loader -D
    
    • 1

    安装成功之后配置

    module:{
    	rules:[
    		{
    			test:/\.ts$/,
    			use:'ts-loader',
    			exclude:/node_modules/
    		}
    	]
    },
    resolve:{
    	extensions:['.ts', '.js']
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    配置好之后 ,执行命令 初始化 ts

    npx tsc --init
    
    • 1

    将 rootDir 指向当前文件夹 “./src”,outDir 指向 “./dist”;然后就可以正常编译打包 ts 文件了;

    注意:我们在使用 TS 加 webpack 的时候,如果引入其他第三方插件、库、工具,都需要引入一个类型文件;想要查询相关类型文件包可以访问:https://www.typescriptlang.org/dt/search?search=

  • 相关阅读:
    ChatGPT实战100例 - (18) 用事件风暴玩转DDD
    linux版:TensorRT安装教程
    SVA断言总结
    钢材行业供应链协同管理系统提升企业上下游密切度,精细化企业内部管理
    分享一个基于微信小程序的高校图书馆预约座位小程序 图书馆占座小程序源码 lw 调试
    「题解」相交链表
    【ArcGIS】NDVI估算植被覆盖度FVC
    如何实现chatGPT批量问答,不用token
    三更Blog项目总结(p1~p40)
    latex公式及表格识别
  • 原文地址:https://blog.csdn.net/weixin_43299180/article/details/125935800