Day_03 : 让 Vite 来开启你的Vue 微谈模组化与演进(下)

Hi Da Gei Ho~ 我是 Winnie , 今天来到了第三天

前情提要:

在昨天的文章中,我们简单的解释了下 模组 与 模组化 是什麽之後,今天我们将继续 简单了解 JS模组化规范 的 演进过程。

不知道大家记不记得,在上篇的文章我们有说到 早期的JavaScript 是还没有模组化的概念的,所以在当时 只能以function 档案来区分并透过<script><script/> 的方式来载入,就像以下程序码:

//Monday.js
function Monday(month, day){
return month+"/"+day
}

//Tuesday.js
function Tuesday(month, day){
return month+"/"+day
}

//Wednesday.js
function Wednesday(month, day){
return month+"/"+day
}

<html lang="en">
  <body>
    <script type="text/javascript" src="../lib/juqery.js"></script>
    <script type="text/javascript" src="../js/Monday.js"></script>
    <script type="text/javascript" src="../js/Tuesday.js"></script>
    <script type="text/javascript" src="../js/Wednesday.js"></script>
  </body>
</html>

**依照上面程序码载入的方式,如果使用不小心很容易就会导致以下缺点:

  • 命名的冲突 导致污染全域
    //a.js
    var Wednesday = '9/15'
    .... 略
    //b.js
     var Wednesday = '9/16'
    ....略
    console.log(Wednesday) 

从上程序码来看,原本应该 星期三应该是9/15,但因为其他命名相同的冲突而被覆盖 输出 9/16

  • 引入的档案相互依赖性高,顺序很重要

    如:Wednesday.js 依赖了Tuesday.js 那麽载入时就必须先使用Tuesday.js再使用Wednesday.js,一但顺序相反,就很容易出错

IIFE

後来为解决 命名冲突及污染全域的问题 ,进而发展出 IIFE(立即执行函式) 模拟模组的方式,而IIFE的就如同他名字一样,当下被宣告function就会立即执行

其中在模拟模组化的过程中,还 使用到了 JavaScript的特性 闭包Closures 让区域变数和方法锁在内部,将需要给外部使用的变数传出去,而这样的好处就是区域性的变数 就不会污染到全域性作用域

(function(){
    var name = 'winnie;
    var sayHello = function (){
        console.log('hello ! I'm'+ name);
    }
    sayHello(); // hello! I'm winnie
})()

虽然以上 实现了简单的程序码模组化,同时也解决了污染作用域的问题,但针对 管理 相互依赖的问题还是依然存在。

所以随着技术的进步(老话一句),为了能让人们更方便,所以後期在 Node.js 中大家也开始发展出许多方便的第三模组库供人使用,因此针对模组化也有了不同的规范版本,其中 像是 我们常听到的 CommonJSAMDCMD 还有 近期的ES6 module

而在这麽多规范中,想必大家应该常常会看到 require/module.exportsimport/exports 的用法吧?

是的!接着我们就要来介绍这两个的规范,分别是 common.js & ES6 module (抱歉!其实 AMD、CMD也常见,後续有机会会再补上 )

ES5 之前 的 Common JS

如果大家有印象,在 Common JS标准最主要的规范就是输出模组时用 module.exports,引入时用 require

范例如下:


// banana.js

//一个一个 汇出

exports.banana = 'I m banana'
module.exports.banana = function(){}

//整体汇出
module.exports = {  banana: 'I m banana', banana:function(){}}



const banana = require('./banana.js')
console.log(banana.banana) // 'I m banana'

而这个用法在当时也被Node.js采用 ,所以现今我们时常会在各种程序码中 看到这个形式来做模组的输出与引用。
但很可惜的是,虽然Common.js被Node.js采用成模组化的规范,但很可惜的是,在浏览器上面依然没办法使用 ,简单来说 就是 浏览器 只看得懂 JavaScript 啊,而这也是我们 现今为何要使用 打包工具 的最主要原因。

对!终於提到 打包工具,现在你终於能稍微知道为什麽要用Webpack了啊!

画重点!!就是在当时 浏览器的原生并不支援 CommonJS),必须透过打包工具的编译 才能在浏览器上面使用。

ES6 Module

而 ES6 出来之後,模组化 有了正式的规范,也就是近期很常看到的 import 与 export的形式

范例如下:

// hello.js
// 多个输出名称
  export function sayHello(){  
  console.log('Hello');
}

  export function sayBye(){  
  console.log('Bye');
}

// 单一输出  (这边需注意的是 一只档案中只能有一个 export default)

function sayGoodnight(){
  console.log(‘Goodnight’)
}

export default sayGoodnight

---------------------------------
// other.js
// 引入hello模组的sayHello方法
  import { sayHello, sayBye } from './hello';
  sayHello(); // => Hello
  sayBye(); // => Bye

这就是 ES6 Module 。

到这边,你可能会想既然原生都支持了,为何还要打包工具?

但事情是这样的,人生有十之八九不会照着我们想走的走。

所以在 ES6 Module 这边也是一样,虽然是浏览器原生支持的,但还是有在某些浏览器不支援的问题,就像下面这张图一样

而同时如果在 Node.js 上面试图执行 import 这个语法,也还出现一个 SyntaxError: Unexpected identifier 的错误,因为 Node.js 不认识 import。但总不可能因为不支援就要抛弃他人写好的给力模组吧。

综合以上这些可能会碰到的问题,如果想要人生顺利,我们还是需要透过 打包工具 来帮我们处理掉这些问题。

小结:

最後,这篇文章简单的针对 JS中 模组化从有到无的出现过程及常见模组化规范(其实还少讲了很多XD,像是AMD、CMD)进行了描述,虽然可能不是说得很详细,但这篇文章的最主要目的还是想透过 模组化的微历史 来了解 为何使用打包工具来编译的目的。

如果文章有错误的地方,再麻烦不吝啬的给予指教 谢谢 !!


<<:  [Day5] 第一章贴图

>>:  【D1】前言与规划

【在 iOS 开发路上的大小事-Day16】透过 Firebase 来管理使用者 (Sign in with E-mail 篇) Part2

昨天我们已经将注册帐号、帐号登入实作完成了,今天我们要来把剩下的帐号登出以及密码重设功能来实作完成 ...

Day28 - 数学、字串函数

如同许多的程序语言,SQL 本身也有内建函数,像是前些天的篇幅内曾用的 COUNT, SUM, AV...

【从零开始的 C 语言笔记】第二十三篇-Switch条件式

不怎麽重要的前言 上一篇介绍了两个小题目,稍微带过解题的思路,以及多重回圈(巢状回圈)的概念。 现在...

CSS微动画 - 卡片简约动态效果,低调的小心机

Q: 剩下 5 篇来点实用也不实用的范例吧~~ A: 毕竟效果还是要看设计的美感,这是很看天份的(...

C#学习笔记2:变数、变数宣告与命名规则

这是我一边学习一边写下的笔记,如果内容有错,恳请在下方留言跟我说,我会非常感谢的!!! 变数 「变数...