什么是模块化
将一个复杂的程序依照一定的规则封装成几个文件,并进行组合在一起。每个模块的内部数据是私有的,只是向外暴露一些接口(方法)与外部其它模块通信。
模块化优点
1. 避免名称空间的冲突
2. 更好的分离,实现按需加载
3. 提高代码的复用性,维护性
模块化历史进程
CJS
CJS是
CommonJs
缩写,nodejs
指定的标准,服务端的模块化规范。优点: 所有模块同步加载。
缺点: 服务器端运行可以,浏览器端就会造成js解析阻塞,页面加载速度缓慢。
let a = require('包名称') module.exports = {a} // exports.a = a
AMD
Asynchronous Module Definition / 异步模块定义; 经典实现框架:
require.js
优点: 支持模块异步加载,加载速度快。
缺点:
1. 会有引入成本,没有考虑按需加载; AMD 是预加载,加载某个模块前,这个模块的依赖模块需要先加载完成。
2. 因为是异步加载,加载顺序不一定,可能遇到某个依赖中用到的另一个依赖还没加载到
// 通过define定义模块 define('amdModule', ['deps1', 'deps2'], (deps1, deps2) => { // 业务逻辑 let count = 0 const increase = function(){++count} deps1() deps2() return { increase } }) // 引用模块 reuire(['amdModule'], amdModule => { amdModule.increase() })
CMD
Common Module Definition / 通用模块定义; 主要应用框架
sea.js
// program.js define(function(require, exports, module) { var inc = require('increment').increment; var a = 1; inc(a); // 2 module.id == "program"; });
优点: 按需执行,依赖就近,用到的依赖都是确定加载并执行完成的
缺点:
执行等待时间会叠加。因为每个文件执行时是同步执行 , 因此时间是所有文件解析执行时间之和,尤其在文件较多较大时,这 种缺点尤为明显。
AMD 和 CMD 区别:
AMD 通过 require.js实现
CMD 通过 sea.js实现
1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... }) // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() ... })
ESM
ES Modules ; esma 模块化标准
优点: 通过一种最统一的形态整合了所有JS的模块化
import {ref} from 'vue' export {}
为什么选 vite
现实问题
在游览器支持 ESM 前, javascript
并没有提供原生机制让开发者以模块化的方式进行开发。
所以市场上出现了 webapck , rollup, patcel
等打包工具, 处理我们的项目源码模块串联成可以在游览器中运行的文件。
然而,当构建的项目越来越大时,这些 JavaScript
开发的工具也出现了性能瓶颈;通常需要很长时间才能启动开发服务器,即使使用 HMR
热加载,
文件修改后的效果也需要等待几秒才能反映出来,这种迟钝的反馈对开发效率大打折扣。
vite
的宗旨就是处理以上问题。利用逐渐发展的es
新特性解决问题:游览器开始原生支持ES
模块,且越来越多js
工具使用编译型语言编写。
缓慢的服务器启动
webpack
之类冷启动打包工具,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。简而言之,需要webpack
内置服务器将应用整体代码打包编译后,形成一个或多个 bundles
,或者说是 静态资源 ,才能提供服务。
即使采用了代码拆分,也需要一次生成所有路由下的编译后文件(这也是为什么代码拆分对开发模式没有帮助)。这也导致服务启动时间随着项目复杂度而指数增长。
vite
是基于原生的ES module
,浏览器厂商的不懈努力,现代游览器已经支持import/export
模块化形式;vite
启动服务器时,不需要整个应用提交编译文件,游览器已经原生支持模块化了,游览器请求对应的路由URL
时,提供对应的编译后文件,实现了真正的路由懒加载,这个比起webpack
就要节省不少时间;vite
将应用中的模块分为 依赖 和 源码 两类,在这两块做了些事件,改进了服务器的启动时间依赖 大多为在开发时不会变动的纯
javascript
。 一些较大的依赖处理代价也高,这些依赖代码可能存在多种模块化格式(如ESM
,CommonJs
AMD
,UMD
等等。这个时候vite
会进行 esbuild 预构建依赖 ,将其转为ESM
模块,以支持vite
。对于有许多内部模块的
ESM
依赖转换为单个模块,减少HTTP
请求,以提高后续页面加载性能 。源码 通常包含一些并非直接是
javascript
的文件(例如:TS, JSX, CSS, 或者 Vue/Svelte组件
),也需要使用 esbuild 编译,不同与webpack
整体编译,vite
是在游览器请求路由URL
时,才对改文件编译,然后提供给游览器。因为esbulid
编译够快,这种每次页面加载后即刻编译的其实是不会影响页面渲染的。
vite 是如何实现的
参考资料
###
vite 简介
使用原生 ESM 文件,无需打包 (启动快!
无论程序大小如何,都始终极快的热加载 HMR (轻量快速的热加载!
开箱即用,生态丰富
构建工具
当我们习惯了在
node
中编写代码的方式后,在回到前端编写html, css, js
这些东西会感觉到各种的不便。比如:不能放心的使用模块化规范 (游览器兼容问题),即使可以使用模块化规范也会面临模块过多时的加载问题。我们就迫切的希望有一款工具可以对代码进行打包,将多个模块打包成一个文件,这样一来即解决了兼容性问题(
esm
代码转为旧代码),又解决了模块过多的问题。构建工具就起到这样一个作用,通过构建工具可以使用
ESM
规范编写的代码转换为旧的JS
语法,这样可以使得所有的游览器都可以支持代码。- 构建工具优点类似代码的编译,执行的代码是编译后的代码
评论区