-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
1.webpack 构建离线应用
==优化==
2. 减少文件搜索范围
resolve.modules 的默认值是 ['node_modules'],含义是先去当前目录下的 ./node_modules 目录下去找想找的模块,如果没找到就去上一级目录 ../node_modules 中找,再没有就去 ../../node_modules 中找,以此类推,这和 Node.js 的模块寻找机制很相似。
resolve.alias 配置项通过别名来把原导入路径映射成一个新的导入路径。
resolve: {
// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
// 其中 __dirname 表示当前工作目录,也就是项目根目录
modules: [path.resolve(__dirname, 'node_modules')]
// 只采用 main 字段作为入口文件描述字段,以减少搜索步骤
mainFields: ['main'],
// 使用 alias 把导入 react 的语句换成直接使用单独完整的 react.min.js 文件,
// 减少耗时的递归解析操作
alias: {
'react': path.resolve(__dirname, './node_modules/react/dist/react.min.js'), // react15
// 'react': path.resolve(__dirname, './node_modules/react/umd/react.production.min.js'), // react16
}
// 尽可能的减少后缀尝试的可能性
//在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在
extensions: ['js'],
// 独完整的 `react.min.js` 文件就没有采用模块化,忽略对 `react.min.js` 文件的递归解析处理
//让 Webpack 忽略对部分没采用模块化的文件的递归解析处理,这样做的好处是能提高构建性能。
noParse: [/react\.min\.js$/],
},
3 动态链接库
在一个动态链接库中包含给其他模块调用的函数和数据
1.把网页依赖的基础模块抽离出来,打包进一个个动态链接库,一个动态链接库中包含多个模块
2.当需要导入的模块在动态链接中,这个模块不能在被重新打包 而是直接去动态链接库中
3.页面依赖的所有动态链接库需要被加载
原因在于包含大量复用模块的动态链接库只需要编译一次,在之后的构建过程中被动态链接库包含的模块将不会在重新编译,而是直接使用动态链接库中的代码。 由于动态链接库中大多数包含的是常用的第三方模块,例如 react、react-dom,只要不升级这些模块的版本,动态链接库就不用重新编译。
4 cdn 加速 内容分发网络
压缩代码减少网络传输大小
Webpack 接入cdn
1. 静态资源的导入 URL 需要变成指向 CDN 服务的绝对路径的 URL 而不是相对于 HTML 文件的 URL。
2.静态资源的文件名称需要带上有文件内容算出来的 Hash 值,以防止被缓存。
3.不同类型的资源放到不同域名的 CDN(同一时刻针对同一个域名的资源并行请求是有限制的话(具体数字大概4个左右,不同浏览器可能不同)) 服务上去,以防止资源的并行加载被阻塞。这样会增加域名解析的时间 可以通过 head 标签<link rel="dns-perfetch" href="//sxx.com"/>预解析域名 减少域名解析的时间
- 压缩代码
1. 混淆源码
2. 减少网络传输流量
3. 提升网页加速
5 背后的运行机制
1. plugin: 扩展插件,在webpack构建过程中的特定时机会广播事件,插件监听特定事件,在特定时机作一些操作
2. loader: 模块转换器,用于把模块原内容转换成新的内容
webpack 的构建过程是串行化的从启动到结束 经过这些过程
1. 确定配置参数: 配置文件中的参数和shell命令行中的参数合并成最终的参数
2. 初始化compiler对象: 使用得出最终的参数初始化compiler对象,加载所有插件配置,执行compiler对象的run方法开始构建
3.确定入口:根据entry参数确定入口文件
4. 编译模块:从入口文件开始调用配置的loader对文件进行转换,在找出入口文件依赖的模块,逐个对他们进行转换,入口文件依赖的模块都被转换过了
5. 完成编译: 在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
6. 输出资源:根据入口与模块之间的依赖关系,产出一个个包含多个模块的chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这里是改变输出内容的最后机会
7. 输出完成:在确定好输出资源后,根据配置的路径和文件名,把文件内容写进到文件系统
Compiler 全局只有一个,包含完整的webpack的配置, 负责文件监听和启动编译
当 Webpack 以开发模式运行时,每当监测到文件变化,就会生成一个新的Compilation对象,Compilation对象包含了当前模块的资源,编译生成资源,变化的文件等,Compilation对象也提供了很多事件回调供插件使用
。。。。。。。。。。。
初始化阶段:启动构建,读取与合并配置参数,加载 Plugin,实例化 Compiler。
1.初始化参数
2.实例化compiler
3.加载插件,依次调用插件的 apply 方法,让插件可以监听后续的所有事件节点。
4. environment: 应用node.js的文件系统到compiler对象
5. entry-option 根据配置的entry信息,给每个entry生成一个对应的entryPlugin,为入口的解析,递归解析依赖作准备
6. after-plugins:当所有插件apply方法调用完成
7 .after-resolvers
编译阶段:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理。
1. run 开始一次新的编译
2. complier: 通知插件将开始一次新的编译
3. complilation: 生成新的complilation对象
4. make 一个新的 Compilation 创建完毕,即将从 Entry 开始读取文件,根据文件类型和配置的 Loader 对文件进行编译,编译完后再找出该文件依赖的文件,递归的编译和解析。
5.after-compile 一次 Compilation 执行完成。
6.invalid 当遇到文件不存在、文件编译错误等异常时会触发该事件,该事件不会导致 Webpack 退出。
输出阶段:对编译后的 Module 组合成 Chunk,把 Chunk 转换成文件,输出到文件系统。
1.emit: 确定好要输出哪些文件后,执行文件输出,可以在这里获取和修改输出内容。
2.after-emit文件输出完毕
3.done:成功完成一次完成的编译和输出流程。
4.failed 如果在编译和输出流程中遇到异常导致 Webpack 退出时,就会直接跳转到本步骤,插件可以在本事件中获取到具体的错误原因。
在输出阶段已经得到了各个模块经过转换后的结果和其依赖关系,并且把相关模块组合在一起形成一个个 Chunk。
6.输出文件分析
原来一个个单独的模块文件被合并到一个文件中
bundle.js
为什么bunlde.js能直接在浏览器中运行呢
bundle.js中能直接运行在浏览器中原因是在输出文件中通过_webpack_require_函数定义了一个在浏览器中执行的加载函数来模拟node.js中的require语句
做不到和node一样在本地加载文件,当发现需要加载新的文件时需要通过网络,但是模块多了的化,时间就很长,所有就放在数组里,一次加载完
_webpack_require_函数还有缓存处理,已经加载过的模块不会进行二次加载,会去缓存中获取
7 抽取页面公共代码
改善什么现象
1. 相同的资源被重复加载,浪费用户的流量 服务器的成本
2. 包体也大
8 按需加载
最关键的一行是 chunkFilename: '[name].js',,它专门指定动态生成的 Chunk 在输出时的文件名称。 如果没有这行,分割出的代码的文件名称将会是 [id].js。
import('/*webpackChunkName:"show"*/''./show.js').then((show)=> {
show('Webpack');
})
9 plugin
webpack 就像一个生产线,通过一系列流程才能将源文件转换成输出结果,生产线上每个处理流程的职责是单一的,多个流程存在依赖关系
只有完成当前处理后才能交给下一个流程去处理
插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。
10 loader 链式调用 翻译员
Loader 运行在 Node.js 中,你可以调用任何 Node.js 自带的 API
loader 将源代码经过转换后输出新的结果支持链式调用
在你开发一个 Loader 时,请保持其职责的单一性,你只需关心输入和输出
module.exports = function(source){
return source;
}
loader 有同步和异步之分
Webpack 会默认缓存所有 Loader 的处理结果,
加载本地loader
1. npm-link
11 Prepack
Prepack 在编译阶段就预先执行源码得到结果,再把结果输出来以提高性能
而不是在运行时再去求结果
还不够成熟
不能够识别Dom APi 部分Node.js API
存在优化后代码性能更低的情况
存在优化后代码体积更大的情况
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels