webpack学习之——模块(Modules)

本文介绍了Webpack在模块化编程中的角色,详细解释了Webpack如何处理不同类型的依赖关系,包括ES2015 import语句、CommonJS require()语句等。此外,还探讨了Webpack如何解析模块路径、支持多种语言及预处理器,并介绍了其强大的API和模块解析机制。

    在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块

    每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易举。 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。

  什么是 webpack 模块

   对比 Node.js 模块,webpack 模块能够以各种方式表达它们的依赖关系,几个例子如下:

  • ES2015 import 语句;
  • CommonJSrequire() 语句;
  • AMDdefine 和 require 语句;
  • css/sass/less 文件中的 @import 语句;
  • 样式(url(...))或 HTML 文件(<img src=...>)中的图片链接(image url)

   支持的模块类型

     webpack 通过 loader 可以支持各种语言和预处理器编写模块。loader 描述了 webpack 如何处理 非 JavaScript(non-JavaScript) 模块,并且在bundle中引入这些依赖。 webpack 社区已经为各种流行语言和语言处理器构建了 loader,包括:

总的来说,webpack 提供了可定制的、强大和丰富的 API,允许任何技术栈使用 webpack,保持了在你的开发、测试和生成流程中无侵入性(non-opinionated)。

   模块解析(Module Resolution)

     resolver 是一个库(library),用于帮助找到模块的绝对路径。一个模块可以作为另一个模块的依赖模块,然后被后者引用,如下:

      

     所依赖的模块可以是来自应用程序代码或第三方的库(a third party library)。resolver 帮助 webpack 找到 bundle 中需要引入的模块代码,这些代码在包含在每个 require/import 语句中。 当打包模块时,webpack 使用 enhanced-resolve 来解析文件路径

   webpack 中的解析规则

   使用 enhanced-resolve,webpack 能够解析三种文件路径:

  绝对路径

     

     由于我们已经取得文件的绝对路径,因此不需要进一步再做解析。

  相对路径

    

    在这种情况下,使用 import 或 require 的资源文件(resource file)所在的目录被认为是上下文目录(context directory)。在 import/require 中给定的相对路径,会添加此上下文路径(context path),以产生模块的绝对路径(absolute path)。 

  模块路径

   

   模块将在 resolve.modules 中指定的所有目录内搜索。 你可以替换初始模块路径,此替换路径通过使用 resolve.alias 配置选项来创建一个别名。

   一旦根据上述规则解析路径后,解析器(resolver)将检查路径是否指向文件或目录。如果路径指向一个文件:

  • 如果路径具有文件扩展名,则被直接将文件打包。
  • 否则,将使用 [resolve.extensions] 选项作为文件扩展名来解析,此选项告诉解析器在解析中能够接受哪些扩展名(例如 .js.jsx)。

  如果路径指向一个文件夹,则采取以下步骤找到具有正确扩展名的正确文件:

  • 如果文件夹中包含 package.json 文件,则按照顺序查找 resolve.mainFields 配置选项中指定的字段。并且 package.json 中的第一个这样的字段确定文件路径。
  • 如果 package.json 文件不存在或者 package.json 文件中的 main 字段没有返回一个有效路径,则按照顺序查找 resolve.mainFiles 配置选项中指定的文件名,看是否能在 import/require 目录下匹配到一个存在的文件名。
  • 文件扩展名通过 resolve.extensions 选项采用类似的方法进行解析。

  webpack 根据构建目标(build target)为这些选项提供了合理的默认配置。

  缓存

   每个文件系统访问都被缓存,以便更快触发对同一文件的多个并行或串行请求。在观察模式下,只有修改过的文件会从缓存中摘出。如果关闭观察模式,在每次编译前清理缓存。

 

 

转载于:https://www.cnblogs.com/xuzhudong/p/8072142.html

### Webpack 5 Module Federation 实现微前端的最佳实践 #### 微前端架构概述 微前端是一种将大型单体应用程序拆分为更小、独立部署单元的设计模式。它允许多个团队并行工作,各自负责不同的子应用或功能模块Webpack 5 的 Module Federation 功能为此提供了强大的支持,使得不同前端应用之间可以无缝共享组件和状态[^2]。 --- ### 最佳实践总结 1. **清晰划分职责** - 将整个系统划分为多个独立的应用(Host 应用与 Remote 应用)。每个应用专注于自己的业务领域。 2. **统一构建工具链** - 确保所有参与联邦的项目均基于相同的 Webpack 版本,并保持一致的配置风格。 3. **合理设计公共依赖管理策略** - 使用 `shared` 属性定义跨应用间共享的基础库版本号,减少重复打包体积的同时提升性能表现[^4]。 4. **动态加载能力增强用户体验** - 借助懒加载特性按需引入外部资源而不是一次性全部加载进来从而优化启动速度。 5. **考虑兼容性和降级方案** - 针对老旧浏览器可能存在的不完全支持情况提前做好预案处理比如 polyfill 或者回退至传统 iframe 方式嵌套页面片段等替代手段。 --- ### 示例代码演示 假设我们要搭建两个简单的 React 应用来模拟真实场景下的微前段协作流程——其中一个是作为宿主容器存在而另一个则充当被集成的内容提供商角色。 #### Host Application (App1) ##### webpack.config.js ```javascript const { ModuleFederationPlugin } = require("webpack").container; const path = require("path"); module.exports = { entry: "./src/index", mode: "development", devServer: { port: 3000, }, output: { publicPath: "auto", }, resolve: { extensions: [".jsx", ".js"], }, module: { rules: [ { test: /\.(js|jsx)$/, loader: "babel-loader", exclude: /node_modules/, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "host_app", filename: "remoteEntry.js", remotes: { guest_app: "guest_app@http://localhost:3001/remoteEntry.js", }, shared: ["react", "react-dom"], // 明确指出哪些包应该在整个解决方案范围内共用一份副本 }), ], }; ``` ##### src/App.jsx ```javascript import React from "react"; import GuestComponent from "guest_app/GuestComponent"; function App() { return ( <div> <h1>Host Application</h1> {/* Dynamically load component from remote application */} <GuestComponent /> </div> ); } export default App; ``` #### Remote Application (App2) ##### webpack.config.js ```javascript const { ModuleFederationPlugin } = require("webpack").container; const path = require("path"); module.exports = { entry: "./src/index", mode: "development", devServer: { port: 3001, }, output: { publicPath: "auto", }, resolve: { extensions: [".jsx", ".js"], }, module: { rules: [ { test: /\.(js|jsx)$/, loader: "babel-loader", exclude: /node_modules/, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "guest_app", filename: "remoteEntry.js", exposes: { /// Expose this specific file so that other apps can consume it. "./GuestComponent": "./src/components/GuestComponent", }, shared: ["react", "react-dom"], }), ], }; ``` ##### src/components/GuestComponent.jsx ```javascript import React from "react"; const GuestComponent = () => { return <p>This is a paragraph coming from the guest application!</p>; }; export default GuestComponent; ``` --- ### 技术细节解析 - **暴露与消费模块** 在上面的例子中,Remote 应用通过 `exposes` 字段指定了可供外界访问的具体路径;与此同时,Host 应用借助 `remotes` 参数声明了希望连接上的远端服务位置信息[^3]。 - **动态注入行为** 当我们在 Host 应用里写下了 `<GuestComponent />` 后,实际上背后发生了一系列复杂的操作:首先是向指定 URL 请求对应脚本文件(remoteEntry.js),接着按照既定规则完成初始化动作最后才真正意义上渲染出了最终界面效果[^1]。 - **资源共享机制** 凭借着 `shared` 键值设定,我们可以有效避免同一份第三方类库多次被打包进各个单独的小型工程之中进而造成不必要的浪费现象出现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值