webpack笔记-webpack之模块module、路径解析、resolve 配置(三)
module
webpack 的初衷是让 js 支持模块化管理,并且将前端中的各种资源都纳入到对应的模块管理中来,所以在 webpack 的设计中,最重要的部分就是管理模块和模块之间的关系。
在 webpack 支持的前端代码模块化中,我们可以使用类似 import * as m from './index.js' 来引用代码模块 index.js。webpack 构建的时候,会解析依赖后,然后再去加载依赖的模块文件。所谓 webpack 构建的起点,本质上也是一个 module,而我们在设置好 webpack 后,开发的过程亦是在写一个个的业务 module。
在 JavaScript 中尽量使用 ES6 module 的语法来引用依赖。
路径解析
当我们写一个 import 语句来引用一个模块时,webpack 是如何获取到对应模块的文件路径的呢?这其中有十分复杂的实现逻辑和相对繁琐的配置选择。
webpack 中有一个很关键的模块 enhanced-resolve 就是处理依赖模块路径的解析的,这个模块可以说是 Node.js 那一套模块路径解析的增强版本,有很多可以自定义的解析配置。
不熟悉 Node.js 模块路径解析机制的同学可以参考这篇文章:深入 Node.js 的模块机制。
简单整理一下基本的模块解析规则,以便更好地理解后续 webpack 的一些配置会产生的影响。
- 解析相对路径
- 查找相对当前模块的路径下是否有对应文件或文件夹
- 是文件则直接加载
- 是文件夹则继续查找文件夹下的 package.json 文件
- 有 package.json 文件则按照文件中 main 字段的文件名来查找文件
- 无 package.json 或者无 main 字段则查找 index.js 文件
- 解析模块名
查找当前文件目录下,父级目录及以上目录下的 node_modules 文件夹,看是否有对应名称的模块
- 解析绝对路径(不建议使用)
直接查找对应路径的文件
在 webpack 配置中,和模块路径解析相关的配置都在 resolve 字段下:
module.exports = {
resolve: {
// ...
}
}
resolve 配置
resolve.alias
假设我们有个 utils 模块极其常用,经常编写相对路径很麻烦,希望可以直接 import 'utils' 来引用,那么我们可以配置某个模块的别名,如:
alias: {
utils: path.resolve(__dirname, 'src/utils') // 这里使用 path.resolve 和 __dirname 来获取绝对路径
}
上述的配置是模糊匹配,意味着只要模块路径中携带了 utils 就可以被替换掉,如:
import 'utils/query.js' // 等同于 import '[项目绝对路径]/src/utils/query.js'
如果需要进行精确匹配可以使用:
alias: {
utils$: path.resolve(__dirname, 'src/utils') // 只会匹配 import 'utils'
}
查看下vue-cli的别名配置代码如下:
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
// ...省略其它代码
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'#': resolve('config')
}
}
// ...省略其它代码
resolve.extensions
我们在页面中常常这样引用文件:
import * as common from './src/utils/common'
webpack 会自行补全文件后缀,而这个补全的行为,也是可以配置的。
extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx'],
// 这里的顺序代表匹配后缀的优先级,例如对于 index.js 和 index.jsx,会优先选择 index.js
webpack 会尝试给你依赖的路径添加上 extensions 字段所配置的后缀,然后进行依赖路径查找,所以可以命中 src/utils/common.js 文件。
vue脚手架的extensions的配置如下:
extensions: ['.js', '.vue', '.json']
resolve.modules
对于直接声明依赖名的模块,webpack 会类似 Node.js 一样进行路径搜索,搜索 node_modules 目录,这个目录就是使用resolve.modules 字段进行配置的,默认就是:
resolve: {
modules: ['node_modules'],
},
通常情况下,我们不会调整这个配置,但是如果可以确定项目内所有的第三方依赖模块都是在项目根目录下的 node_modules 中的话,那么可以在 node_modules 之前配置一个确定的绝对路径:
resolve: {
modules: [
path.resolve(__dirname, 'node_modules'), // 指定当前目录下的 node_modules 优先查找
'node_modules', // 如果有一些类库是放在一些奇怪的地方的,你可以添加自定义的路径或者目录
],
},
这样配置在某种程度上可以简化模块的查找,提升构建速度。
resolve.mainFields
有 package.json 文件则按照文件中 main 字段的文件名来查找文件
我们之前有提到这么一句话,其实确切的情况并不是这样的,webpack 的 resolve.mainFields 配置可以进行调整。当引用的是一个模块或者一个目录时,会使用 package.json 文件的哪一个字段下指定的文件,默认的配置是这样的:
resolve: {
// 配置 target === "web" 或者 target === "webworker" 时 mainFields 默认值是:
mainFields: ['browser', 'module', 'main'],
// target 的值为其他时,mainFields 默认值为:
mainFields: ["module", "main"],
},
因为通常情况下,模块的 package 都不会声明 browser 或 module 字段,所以便是使用 main 了。
在 NPM packages 中,会有些 package 提供了两个实现,分别给浏览器和 Node.js 两个不同的运行时使用,这个时候就需要区分不同的实现入口在哪里。如果你有留意一些社区开源模块的 package.json 的话,你也许会发现 browser 或者 module 等字段的声明。
resolve.mainFiles
当目录下没有 package.json 文件时,我们说会默认使用目录下的 index.js 这个文件,其实这个也是可以配置的,是的,使用 resolve.mainFiles 字段,默认配置是:
resolve: {
mainFiles: ['index'], // 你可以添加其他默认使用的文件名
},
通常情况下我们也无须修改这个配置,index.js 基本就是约定俗成的了。
resolve.resolveLoader
这个字段 resolve.resolveLoader 用于配置解析 loader 时的 resolve 配置,原本 resolve 的配置项在这个字段下基本都有。我们看下默认的配置:
resolve: {
resolveLoader: {
extensions: ['.js', '.json'],
mainFields: ['loader', 'main'],
},
},
这里提供的配置相对少用,我们一般遵从标准的使用方式,使用默认配置,然后把 loader 安装在项目根路径下的 node_modules 下就可以了。
webpack笔记-webpack之模块module、路径解析、resolve 配置(三)的更多相关文章
- python全栈开发中级班全程笔记(第二模块、第四章(三、re 正则表达式))
python全栈开发笔记第二模块 第四章 :常用模块(第三部分) 一.正则表达式的作用与方法 正则表达式是什么呢?一个问题带来正则表达式的重要性和作用 有一个需求 : 从文件中读取所有联 ...
- requirejs:让人迷惑的路径解析
接触过requirejs的童鞋可能都知道,无论是通过define来定义模块,还是通过require来加载模块,模块依赖声明都是很重要的一步.而其中涉及到的模块路径解析,对于新手来说,有的时候会让人觉得 ...
- 转:requirejs:让人迷惑的路径解析(~~不错)
接触过requirejs的童鞋可能都知道,无论是通过define来定义模块,还是通过require来加载模块,模块依赖声明都是很重要的一步.而其中涉及到的模块路径解析,对于新手来说,有的时候会让人觉得 ...
- Python 学习 第十五篇:模块搜索路径和包导入
在导入自定义的模块时,除了指定模块名之外,也需要指定目录,由于Python把目录称作包,因此,这类导入被称为包导入.包导入把计算机上的目录变成Python的命名空间,而目录中所包含的子目录和模块文件则 ...
- webpack新版本4.12应用九(配置文件之模块(module))
这些选项决定了如何处理项目中的不同类型的模块. module.noParse RegExp | [RegExp] RegExp | [RegExp] | function(从 webpack 3.0. ...
- webpack 导出、导入模块(及路径)
参考:https://blog.csdn.net/xyphf/article/details/83411552 (下面的代码亲测有效) 注:导入的模块的方法,只有两种方法 import 和 requ ...
- Webpack笔记(一)——从这里入门Webpack
准备了挺久,一直想要好好深入了解一下Webpack,之前一直嫌弃Webpack麻烦,偏向于Parcel这种零配置的模块打包工具一些,但是实际上还是Webpack比较靠谱,并且Webpack功能更加强大 ...
- 入门学习webpack笔记
注意事项: 1.预热知识:前端模块化.commonJS最好提前了解.commonJS语法最好熟悉. 2.commonJS中,module表示当前模块,module.exports(或者exports) ...
- 透过现象看webpack处理css文件中图片路径转换的具体过程
webpack是目前使用比较流行的一个前端模块打包器,前端的任何资源都被当成一个模块来处理,如图片.css文件等等.在基于webpack构建的前端项目中,一般都会配置有关css文件处理的规则,这其中也 ...
- Webpack 入门指南 - 2.模块
这一次我们谈谈模块问题. 通常我们希望这个项目可以分为多个独立的模块,比如,上一次提高的 hello 函数,如果我们定义为一个模块,其它模块引用之后,直接调用就好了.在前端怎么使用模块呢?这可说来话长 ...
随机推荐
- 效率工具RunFlow完全手册之进阶篇
欢迎来到RunFlow手册的进阶篇,如果您还不了解RunFlow,建议先阅读我们的基础篇. (Solo 社区投稿) 搜索文件 按文件大小过滤,添加 len 参数,比如:len:1kb-2kb,len: ...
- 学习笔记--Java中方法递归调用
Java中方法递归调用 public class RecursionTest01{ public static void main(String[] args){ System.out.println ...
- LLM-01 大模型 本地部署运行 ChatGLM2-6B-INT4(6GB) 简单上手 环境配置 单机单卡多卡 2070Super8GBx2 打怪升级!
搬迁说明 之前在 CSDN 上发文章,一直想着努力发一些好的文章出来!这篇文章在 2024-04-17 10:11:55 已在 CSDN 发布 写在前面 其他显卡环境也可以!但是最少要有8GB的显存, ...
- 题解:P10537 [APIO2024] 九月
题解:P10537 [APIO2024] 九月 题意 在一个树上,在 \(k\) 天内有 \(n-1\) 个节点掉落,会有 \(m\) 个记录者记录掉落的情况,每一天每一个人会以任意的顺序记录当天的掉 ...
- 如何用 WinDbg 调试Linux上的 .NET程序
一:背景 1. 讲故事 最新版本 1.2402.24001.0 的WinDbg真的让人很兴奋,可以将自己伪装成 GDB 来和远程的 GDBServer 打通来实现对 Linux 上 .NET程序进行调 ...
- openEuler 安装 DocekrCE
就个人而言,openEuler 算是不错的国产化操作系统."一脉传承"自redhat让实际的使用体验非常丝滑.软件源都是国内的,开箱即用,漏洞的补丁发的也挺及时.美中不足的是貌似 ...
- JVM系列(一) -浅谈虚拟机的成长史
一.摘要 众所周知,Java 经过多年的发展,已经从一门单纯的计算机编程语言,发展成了一套成熟的软件解决方案.从互联网到企业平台,Java 是目前使用最广泛的编程语言. 以下这段内容是来自 Java ...
- Django+Bootstrip 卡片模板设计 经典精品
下面是一个完整的卡片模板代码,包含所有元素,并使用Django的模板语言来处理状态字段的条件渲染.同时还包括示例视图和URL配置. 完整的卡片模板 <div class="card&q ...
- 【Kotlin】官网学习笔记
0.IDEA环境设置: 1.基础语法 BasicSyntax 地址:https://kotlinlang.org/docs/basic-syntax.html 一.方法与变量 可以直接编写main方法 ...
- 论文写作:“et al.”和“etc.”在英语中的区别
"et al."和"etc."在英语中有不同的用法和含义.以下是它们的区别和具体用法: et al. "et al."是拉丁短语" ...