模块化开发 webpack

模块化开发 & webpack

  • 1、模块化开发 & webpack
    • 1.1 webpack 执行过程
      • 1.1.1 初始化
      • 1.1.2 编译
      • 1.1.3 输出
    • 2.1 webpack 基础配置
      • 2.1.1 Entry
        • 2.1.1.1 context
        • 2.1.1.2 Entry类型
      • 2.1.2 output
        • 2.1.2.1 filename
        • 2.1.2.2 publicPath
        • 2.1.2.3 path
        • 2.1.2.4 libraryTarget 和 library
      • 2.1.3 module
        • 2.1.3.1 loader
        • 2.1.4 Resolve
        • 2.1.5 总结
    • 2.2 编写loader
      • 2.2.1 loader基础
      • 2.2.2 loader进阶
      • 2.2.3 加载本地Loader
      • 2.2.4 实战
    • 2.3 编写plugin
      • 2.3.1 Compiler 和 Compilation
      • 2.3.2 事件流

为什么要将文件进行打包?
1、转换文件 兼容性
2、对众多资源处理 css font image
3、产物优化 代码压缩 代码丑化 源码安全性 减少文件体积

1、模块化开发 & webpack

问题:
1、从0-1使用 webpack 进行搭建 vue react
2、对 webpack 执行过程
3、常用的 plugins 自定义自己的插件 事件机制 tapable 发布订阅模式 事件注册 触发等
4、常用的 loaders 自定义的loader 内容 原理 babel-loader es6+es5 ast
5、优化:
-体积:采取xxx、xxx
-构建速度:采取

1.1 webpack 执行过程

在这里插入图片描述

1.1.1 初始化

初始化参数,后续参数合并options
1、配置项

  • entry 入口 第一步从entry 开始
  • module 不同文件解析内容
  • loader 模块转换器 babel-loader ts-loader等
  • plugin 扩展插件 构建过程 广播事件 插件监听这些事件 在特定时机做对应事情

2、实例化 compiler new Compiler(options)
-负责文件监听和启动编译 全局唯一

3、加载插件 插件的apply 对事件进行监听 compiler

1.1.2 编译

run 启动一次新的编译

compilation 模块的资源 编译生成的资源 变化的文件

1.1.3 输出

输出打包后的文件

emit

done

2.1 webpack 基础配置

2.1.1 Entry

entry是配置模块的入口,可抽象成输入,Webpack 执行构建的第一步将从入口开始搜寻及递归解析出所有入口依赖的模块。

2.1.1.1 context

Webpack 在寻找相对路径的文件时会以 context 为根目录,context 默认为执行启动 Webpack 时所在的当前工作目录。 如果想改变 context 的默认配置,则可以在配置文件里这样设置它:

module.exports = {context: path.resolve(__dirname, 'app')
}
2.1.1.2 Entry类型
  • string ‘./app/entry’ 入口模块的文件路径,可以是相对路径。
  • array [‘./app/entry1’, ‘./app/entry2’] 入口模块的文件路径,可以是相对路径。
  • object { a: ‘./app/entry-a’, b: [‘./app/entry-b1’, ‘./app/entry-b2’]} 配置多个入口,每个入口生成一个 Chunk

如果是 array 类型,则搭配 output.library 配置项使用时,只有数组里的最后一个入口文件的模块会被导出。

2.1.2 output

output 配置如何输出最终想要的代码。output 是一个 object,里面包含一系列配置项:

2.1.2.1 filename

配置输出文件的名称,为string 类型。如果只有一个输出文件,则可以把它写成静态不变的:

 filename: 'bundle.js'

但是在有多个 Chunk 要输出时,就需要借助模版和变量了。前面说到 Webpack 会为每个 Chunk取一个名称,可以根据 Chunk 的名称来区分输出的文件名:

filename: '[name].js'

代码里的[name] 代表用内置的 name 变量去替换[name],这时你可以把它看作一个字符串模块函数, 每个要输出的 Chunk 都会通过这个函数去拼接出输出的文件名称。

内置变量除了 name 还可以包括:

  • id chunk 唯一id
  • name: chunk 名称
  • hash Chunk 的唯一标识的 Hash 值
  • chunkhash Chunk 内容的 Hash 值

输出 => filename:‘[name][hash].js’

2.1.2.2 publicPath

静态资源URL前缀 形成完整 url

filename:'[name]_[chunkhash:8].js'
publicPath: 'https://cdn.example.com/assets/'
2.1.2.3 path

output.path 配置输出文件存放在本地的目录,必须是 string 类型的绝对路径。

 path: path.resolve(__dirname, 'dist_[hash]')

output.path 和 output.publicPath 都支持字符串模版,内置变量只有一个:hash 代表一次编译操作的 Hash 值。

2.1.2.4 libraryTarget 和 library
  • libraryTarget 何种方式导出当前库
  • library 导出库的名称 antd

2.1.3 module

module 配置如何处理模块。

2.1.3.1 loader

loader 何种方式处理模块
文件类型 针对不同的文件类型 如何处理
比如js用babel-loader。ts、vue、md、css、less对应使用不同loader等等,也可以使用自定义loader

示例:

module: {rules: [{// 命中 JavaScript 文件test: /\.js$/,// 用 babel-loader 转换 JavaScript 文件// ?cacheDirectory 表示传给 babel-loader 的参数,用于缓存 babel 编译结果加快重新编译速度use: ['babel-loader?cacheDirectory'],// 只命中src目录里的js文件,加快 Webpack 搜索速度include: path.resolve(__dirname, 'src')},{// 命中 SCSS 文件test: /\.scss$/,// 使用一组 Loader 去处理 SCSS 文件。// 处理顺序为从后到前,即先交给 sass-loader 处理,再把结果交给 css-loader 最后再给 style-loader。use: ['style-loader', 'css-loader', 'sass-loader'],// 排除 node_modules 目录下的文件exclude: path.resolve(__dirname, 'node_modules'),},{// 对非文本文件采用 file-loader 加载test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,use: ['file-loader'],},]
}
2.1.4 Resolve

resolve 入口模块如何找出所有依赖的模块

  • alias 别名配置 :通过别名来把原导入路径映射成一个新的导入路径
  // Webpack alias 配置
resolve:{alias:{components: './src/components/'}
}

当你通过 import Button from 'components/button' 导入时,实际上被 alias 等价替换成了 import Button from './src/components/button'

以上 alias 配置的含义是把导入语句里的 components 关键字替换成 ./src/components/。

  • extensions 在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试访问文件是否存在。
 extensions: ['.js', '.json']

当遇到 require(‘./data’) ,data省略了后缀名,先查找有没有data.js,再找data.json,都没有就会报错

2.1.5 总结

Webpack 内置了很多功能。 你不必都记住它们,只需要大概明白 Webpack 原理和核心概念去判断选项大致属于哪个大模块下,再去查详细的使用文档。
通常你可用如下经验去判断如何配置 Webpack:

  • 想让源文件加入到构建流程中去被 Webpack 控制,配置 entry;
  • 想自定义输出文件的位置和名称,配置 output;
  • 想自定义寻找依赖模块时的策略,配置 resolve;
  • 想自定义解析和转换文件的策略,配置 module,通常是配置 module.rules 里的 Loader;
  • 其它的大部分需求可能要通过 Plugin 去实现,配置 plugin;

2.2 编写loader

Loader 就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多个翻译员翻译。

以处理 SCSS 文件为例:

  1. SCSS 源代码会先交给 sass-loaderSCSS 转换成 CSS
  2. sass-loader 输出的 CSS 交给 css-loader处理,找出 CSS 中依赖的资源、压缩 CSS 等;
  3. css-loader 输出的 CSS 交给 style-loader 处理,转换成通过脚本加载的 JavaScript 代码;

可以看出以上的处理过程需要有顺序的链式执行,先 sass-loadercss-loaderstyle-loader。 以上处理的 Webpack 相关配置如下:

module.exports = {module: {rules: [{// 增加对 SCSS 文件的支持test: /\.scss$/,// SCSS 文件的处理顺序为先 sass-loader 再 css-loader 再 style-loaderuse: ['style-loader',{loader:'css-loader',// 给 css-loader 传入配置项options:{minimize:true, }},'sass-loader'],},]},
};

一个 Loader 的职责是单一的,只需要完成一种转换。 如果一个源文件需要经历多步转换才能正常使用,就通过多个 Loader 去转换。

2.2.1 loader基础

一个 Loader 其实就是一个 Node.js 模块,这个模块需要导出一个函数。
这个导出的函数的工作就是获得处理前的原内容,对原内容执行处理后,返回处理后的内容

一个最简单的 Loader 的源码如下:

module.exports = function(source) {// source 为 compiler 传递给 Loader 的一个文件的原内容// 该函数需要返回处理后的内容,这里简单起见,直接把原内容返回了,相当于该 Loader 没有做任何转换return source;
};

由于 Loader 运行在 Node.js 中,你可以调用任何 Node.js 自带的 API,或者安装第三方模块进行调用:

const sass = require('node-sass');
module.exports = function(source) {return sass(source);
};

2.2.2 loader进阶

以上只是个最简单的 Loader,Webpack 还提供一些 API 供 Loader 调用
1、获得 Loader 的 options
在最上面处理 SCSS 文件的 Webpack 配置中,给 css-loader 传了 options 参数,以控制 css-loader。 如何在自己编写的 Loader 中获取到用户传入的 options 呢?需要这样做:

const loaderUtils = require('loader-utils');
module.exports = function(source) {// 获取到用户给当前 Loader 传入的 optionsconst options = loaderUtils.getOptions(this);return source;
};

2、返回其他结果
上面的 Loader 都只是返回了原内容转换后的内容,但有些场景下还需要返回除了内容之外的东西。
例如以用 babel-loader 转换 ES6 代码为例,它还需要输出转换后的 ES5 代码对应的 Source Map,以方便调试源码。 为了把 Source Map 也一起随着 ES5 代码返回给 Webpack,可以这样写:

module.exports = function(source) {// 通过 this.callback 告诉 Webpack 返回的结果this.callback(null, source, sourceMaps);// 当你使用 this.callback 返回内容时,该 Loader 必须返回 undefined,// 以让 Webpack 知道该 Loader 返回的结果在 this.callback 中,而不是 return 中 return;
};

3、同步与异步
有些场景下转换的步骤只能是异步完成
在转换步骤是异步时,你可以这样:

module.exports = function(source) {// 告诉 Webpack 本次转换是异步的,Loader 会在 callback 中回调结果var callback = this.async();someAsyncOperation(source, function(err, result, sourceMaps, ast) {// 通过 callback 返回异步执行后的结果callback(err, result, sourceMaps, ast);});
};

4、处理二进制数据

module.exports = function(source) {// 在 exports.raw === true 时,Webpack 传给 Loader 的 source 是 Buffer 类型的source instanceof Buffer === true;// Loader 返回的类型也可以是 Buffer 类型的// 在 exports.raw !== true 时,Loader 也可以返回 Buffer 类型的结果return source;
};
// 通过 exports.raw 属性告诉 Webpack 该 Loader 是否需要二进制数据 
module.exports.raw = true;

5、缓存加速
如果你想让 Webpack 不缓存该 Loader 的处理结果,可以这样:

module.exports = function(source) {// 关闭该 Loader 的缓存功能this.cacheable(false);return source;
};

6、其他Loader API
Webpack 官网

2.2.3 加载本地Loader

两种方式:
1、 npm link:把Loader链接到node_moduels 下
2、配置ResolveLoader // 去哪些目录下寻找 Loader,有先后顺序之分

module.exports = {resolveLoader:{// 去哪些目录下寻找 Loader,有先后顺序之分modules: ['node_modules','./loaders/'],}
}

2.2.4 实战

创建名为comment-require-loader
自定义Loader作用是把 @require '../style/index.css'转为require('../style/index.css');

该 Loader 的使用方法如下:

module.exports = {module: {rules: [{test: /\.js$/,use: ['comment-require-loader'],// 针对采用了 fis3 CSS 导入语法的 JavaScript 文件通过 comment-require-loader 去转换 include: [path.resolve(__dirname, 'node_modules/imui')]}]}
};

具体实现时:

function replace(source) {// 使用正则把 // @require '../style/index.css' 转换成 require('../style/index.css');  return source.replace(/(\/\/ *@require) +(('|").+('|")).*/, 'require($2);');
}module.exports = function (content) {return replace(content);
};

2.3 编写plugin

一个最基础的 Plugin 的代码是这样的:

class BasicPlugin{// 在构造函数中获取用户给该插件传入的配置constructor(options){}// Webpack 会调用 BasicPlugin 实例的 apply 方法给插件实例传入 compiler 对象apply(compiler){compiler.plugin('compilation',function(compilation) {})}
}// 导出 Plugin
module.exports = BasicPlugin;

在使用这个 Plugin 时,相关配置代码如下:

const BasicPlugin = require('./BasicPlugin.js');
module.export = {plugins:[new BasicPlugin(options),]
}

2.3.1 Compiler 和 Compilation

在开发 Plugin 时最常用的两个对象就是 CompilerCompilation,它们是 PluginWebpack 之间的桥梁。 CompilerCompilation 的含义如下:

  • Compiler 对象包含了 Webpack 环境所有的的配置信息,包含 optionsloadersplugins 这些信息,这个对象在 Webpack 启动时候被实例化,它是全局唯一的,可以简单地把它理解为 Webpack 实例;
  • Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当 Webpack 以开发模式运行时,每当检测到一个文件变化,一次新的 Compilation 将被创建。Compilation 对象也提供了很多事件回调供插件做扩展。通过 Compilation 也能读取到 Compiler 对象;
    Compiler 和 Compilation 的区别在于:Compiler 代表了整个 Webpack 从启动到关闭的生命周期,而 Compilation 只是代表了一次新的编译

2.3.2 事件流

Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。
Webpack 通过 Tapable 来组织这条复杂的生产线。 Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 Webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。

在开发插件时,还需要注意以下几点:

  • 只要能拿到 Compiler 或 Compilation 对象,就能广播出新的事件,所以在新开发的插件中也能广播出事件,给其它插件监听使用。
  • 传给每个插件的 Compiler 和 Compilation 对象都是同一个引用。也就是说在一个插件中修改了 Compiler 或 Compilation 对象上的属性,会影响到后面的插件。
  • 有些事件是异步的,这些异步的事件会附带两个参数,第二个参数为回调函数,在插件处理完任务时需要调用回调函数通知 Webpack,才会进入下一处理流程。例如:
 compiler.plugin('emit',function(compilation, callback) {// 支持处理逻辑// 处理完毕后执行 callback 以通知 Webpack // 如果不执行 callback,运行流程将会一直卡在这不往下执行 callback();});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/5877.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

OpenEuler 使用ffmpeg x11grab捕获屏幕流,rtsp推流,并用vlc播放

环境准备 安装x11grab(用于捕获屏幕流)和libx264(用于编码) # 基础开发环境&x11grab sudo dnf install -y \autoconf \automake \bzip2 \bzip2-devel \cmake \freetype-devel \gcc \gcc-c \git \libtool \make \mercurial \pkgconfig \zlib-devel \libX11-devel \libXext…

uni-app 图标库整合最佳实践:使用 iconfont 构建属于自己的图标库

一. 前言 在前端开发中,图标已经成为页面设计中不可或缺的一部分。图标可以使界面更加美观、清晰,并且能够提升用户体验。而使用图标库来管理和引用图标资源,可以带来更多的便利和效率。 而在众多的图标库中,iconfont 独树一帜。…

刷题强训 (day1) -- 数字统计

1、数字统计 1.1题目 1.2 思路 根据题目得知我们要统计2出现的次数,那么这就是一个枚举 数字拆分的过程,先设一个变量count统计2出现的次数,那么count怎么变化呢? 当然了出现一个2,count就1,重点在于如何…

AI-基本概念-向量、矩阵、张量

1 需求 需求:Tensor、NumPy 区别 需求:向量、矩阵、张量 区别 2 接口 3 示例 4 参考资料 【PyTorch】PyTorch基础知识——张量_pytorch张量-CSDN博客

Halcon区域分割之分水岭分割法

现实中我们见到过有山有湖的景象,那么一定是水绕山、山围水的情形。当然可在需要的时候人工构筑分水岭,以防集水盆之间的互相穿透。而区分高山与水的界线以及湖与湖之间的间隔,就是分水岭。 分水岭分割法是一种基于拓扑理论的数学形态…

数据结构与算法——图

图 1.图的定义和表示 图的定义 图G由集合V和集合E组成,记作G(V,E),其中: 1、V是顶点元素的有限集合; 2、E是顶点间关系——边的有限集合。 3、边是顶点的无序对或有序对。 无向图和有向图: 无向图 由没有方向的边构成的图…

FebHost:法国.FR域名的市场前景和挑战

.FR域名的未来前景如何? .fr域名在2023年经历了显著增长,新注册量大幅增加。这一积极趋势凸显了法国 VSE(极小型企业)和 SME(中小型企业)数字化转型的持久影响,这一转变早在 2022 年就已开始。…

SQL进阶技巧:如何计算复合增长率?

目录 0 场景描述 1 数据准备 2 问题分析 3 小结 0 场景描述 复合增长率是第N期的数据除以第一期的基准数据,然后开N-1次方再减去1得到的结果。假如2018年的产品销售额为10000,2019年的产品销售额为12500,2020年的产品销售额为15000&…

开源的 API 学习平台「GitHub 热点速览」

前有 5 万颗星标的开源项目 HTTPie 因误操作导致 Star 清零(2022 年),上周知名开源项目 Elasticsearch 也经历了 Star 一夜清零的事件。这些事故的原因均是管理员误将开源项目从公开状态转为私有状态所导致。为避免类似事件再次发生&#xff…

华为HD集群重启NAMENODE实例操作步骤

华为HD集群重启NAMENODE实例操作步骤 管理员账号进入FI——服务——HDFS,选择角色:namenode重启namenode(备) 如下图:点击【实例】–角色选择【Namenode】–选择备节点(自己记录一下当前备节点的IP&…

LoRA:大型语言模型(LLMs)的低秩适应;低秩调整、矩阵的低秩与高秩

目录 LoRA:大型语言模型(LLMs)的低秩适应 一、LoRA的基本原理 二、LoRA的举例说明 三、LoRA的优势 低秩调整、矩阵的低秩与高秩 一、低秩调整(LoRA) 二、矩阵的低秩 三、矩阵的高秩 LoRA:大型语言模型(LLMs)的低秩适应 LoRA(Low-Rank Adaptation of LLMs),…

CST参数扫描设置细节

cst参数扫描的细节 点开参数扫描对话框,新建扫描参数, 例如参数a进行扫描1-2,0.5的步长,这样最后会出现3个参数的仿真结果。 这时如果增加参数b的扫描,在同一sequence下,同样1-2,0.5的步长&…

最高降本90%!它究竟是如何实现的?

第一、云在未来“优先”,病毒攻击和人为错误将成主要威胁 根据Gartner预测,到2025年,超过95%的新数字工作负载将被部署在云原生平台上,超过85%的企业机构将接受云优先原则。 在这一背景下,勒索病毒攻击和人为错误成为…

OpenCV—calcHist()函数

void calcHist( const Mat* images, int nimages,const int* channels, InputArray mask,SparseMat& hist, int dims,const int* histSize, const float** ranges,bool uniform true, bool accumulate false ); images 输入的数据指针,要具备相同的尺寸和数…

用例怎么链接到其他地方的序列图

龙勤思(2018年1月22日): 潘老师,你在PPT里说分析序列图的位置在用例下面。但是你上课时给的EA模板里需求和分析是分成两个包的,所以分析序列图没办法直接加为系统用例的下级元素 潘加宇: 这页幻灯片有点老了,回头我更新。严格来…

Java | Leetcode Java题解之第540题有序数组中的单一元素

题目&#xff1a; 题解&#xff1a; class Solution {public int singleNonDuplicate(int[] nums) {int low 0, high nums.length - 1;while (low < high) {int mid (high - low) / 2 low;mid - mid & 1;if (nums[mid] nums[mid 1]) {low mid 2;} else {high …

利用游戏引擎的优势

大家好&#xff0c;我是小蜗牛。 在当今快速发展的游戏产业中&#xff0c;选择合适的游戏引擎对开发者来说至关重要。Cocos Creator作为一款功能强大且灵活的游戏引擎&#xff0c;为开发者提供了丰富的工具和资源&#xff0c;使他们能够高效地开发出优秀的游戏。本文将探讨如何…

python怎样嵌入c

用c语言编写一个动态库&#xff0c;提供两个函数&#xff0c;两个数的整形求和&#xff0c;两个浮点数的求和。取名为mylib.c。 将c函数文件编译成so动态库。运行gcc mylib.c -fPIC -shared -o libtest.so命令&#xff0c;在目录下可以看到生成的库文件libtest.so。 Python调用…

ML 系列:机器学习和深度学习的深层次总结( 19)— PMF、PDF、平均值、方差、标准差

一、说明 在概率和统计学中&#xff0c;了解结果是如何量化的至关重要。概率质量函数 &#xff08;PMF&#xff09; 和概率密度函数 &#xff08;PDF&#xff09; 是实现此目的的基本工具&#xff0c;每个函数都提供不同类型的数据&#xff1a;离散和连续数据。 二、PMF 的定义…

一键AI换衣-可图AI试衣

我们的真的实现了穿衣自由了吗&#xff1f;上传一张人物图片和衣服的图片&#xff0c;就能实现一键换衣。 这就是可图AI试衣项目 魔塔地址&#xff1a;https://www.modelscope.cn/studio ... lors-Virtual-Try-On 参考&#xff1a; 一键AI换衣-可图AI试衣 https://www.jinsh…