ESM Import与Bundleless

前言

随着前端模块化的发展,在nodejs领域的模块化主要分为了common.js,umd,es module三大种类。其中umd是可以兼容浏览器运行的,common.js只能在nodejs环境运行,es module是属于未来的一种前端模块化,能够同时满足服务端和浏览器端的代码编写。es module也是现在前端工程师写代码最常用的模式。模块化的写法大家也不会陌生,也是未来重要的发展方向。

写法如下:

import fs from 'fs';

有别于common.js的写法:

const fs = require('fs');
兼容性情况

其实浏览器也支持esm import了,但是兼容性情况不容乐观。基于lukeed/dimport的兼容方案,其实我们在大部分的浏览器都可以大胆使用该属性。浏览器的esm import把我们带进一个全新的时代(服务端模块和浏览器模块同步的时代),被称为Bundle Free时代(或者可以被称为Bundleless)。结合Bundle Free可以减少不必要的代码打包,充分利用浏览器的每一分性能。

<!-- dimport 兼容方案 -->
<!-- Load the "module" version on browsers that can support it. -->
<script type="module" src="https://unpkg.com/dimport?module" data-main="/bundle.js"></script>
 
<!-- Load the "nomodule" version on older browsers – acts as fallback! -->
<script type="nomodule" src="https://unpkg.com/dimport/nomodule" data-main="/bundle.js"></script>

ESM Import

其实,最早将ESM Import引入到前端页面开发的是Polymer/lit-html,它将模版模块化,直接带到浏览器。然后激发了preact的调整,基于Tagged_templates创造出developit/htm语法,这样一来,JSX的语法直接能在浏览器使用,当然也部分失去渲染函数的魅力。用JS字符串模版新特性替代了JSX,却能让preact直接能在浏览器运行,当时掀起了一定的影响。

<!DOCTYPE html>
<html lang="en">
  <title>htm Demo</title>
  <script type="module">
    import { html, Component, render } from 'https://unpkg.com/htm/preact/standalone.module.js';

    class App extends Component {
      addTodo() {
        const { todos = [] } = this.state;
        this.setState({ todos: todos.concat(`Item ${todos.length}`) });
      }
      render({ page }, { todos = [] }) {
        return html`
          <div class="app">
            <${Header} name="ToDo's (${page})" />
            <ul>
              ${todos.map(todo => html`
                <li key="${todo}">${todo}</li>
              `)}
            </ul>
            <button onClick=${() => this.addTodo()}>Add Todo</button>
            <${Footer}>footer content here<//>
          </div>
        `;
      }
    }

    const Header = ({ name }) => html`<h1>${name} List</h1>`

    const Footer = props => html`<footer ...${props} />`

    render(html`<${App} page="All" />`, document.body);
  </script>
</html>

其中浏览器端的esm是可以支持相对路径和远端https路径的,前提是所有静态资源要在服务当中,不能以文件路径引入,例如file://开头的资源,这也是对脚本资源的安全考虑。

伴随着Chrome的占有率的提高,以及移动端浏览器的统一和成熟,其实以现代浏览器对esm的支持情况,意味着未来的前端框架渐渐往浏览器原生靠近。前端工程化将我们带到了打包和编译的阶段,js被压缩到一个文件当中,变量都是混淆的,但是打包编译速度和打包的体积永远是我们离不开的话题。webpack的发展已经进入到瓶颈期,项目构建的消耗已经受限于电脑配置和性能。

ESM Import的到来意味着JS资源可以直接被浏览器应用,它也会越来越碎,有很多不常变动的资源可以外部引入。伴随着多资源的并行引用,http2.0刚好解决资源并发性能的问题,也正是说,资源的 ESM Import 和 Bundle Free 的趋势是符合现代浏览器的发展规律的。

Bundleless

业界上,Bundleless的实现主要是vitesnowpack。尤雨溪已经将vue3的工程化逐渐改变成vite,vite的出现有悖于vue-cli3。vue-cli3更多是webpack的深层封装。webpack最大的问题就是打包性能的问题,如果MPA,你可以通过减少打包入口来提高打包效率。但是当你的项目是一个异常庞大SPA的情况下,由于你不是多页面框架(mpa),所以当你的页面有一个文件变动的时候,需要重新构建一个完整bundle,即使你用happypack 或者 thread-loader 压榨电脑的每一寸性能,都达不到高效的开发效率。

而vite则是Bundle Free的实现,它的出现主要是有效减少开发编译时间,因为Bundle Free的原理就在于每一个文件都是独立的import。Node 端和浏览器端的文件基本是对等的,每当一个文件有变动的时候,只需要替换其中一个文件即可。所以它在大型业务项目的开发中,有着很不错的体验。

尤大大的Twitter

由于vue不同于渲染函数,很多语法是模版约定的。熟悉vue原理的同学就知道,它有对应的compiler,将模版转换为createElement的函数,这些函数才可以在浏览器直接运行。每一个独立的vue文件,都会转换成相应的js文件,它们在浏览器上直接运作。vite的基本原理就是在本地调试的时候将修改过的文件转换成为js文件,然后再通过ESM Import引入本地项目当中。vite2.0已经支持了部分预打包机制并且支持react,它可以将部分common.js的npm依赖封装成为esm模块,保证了第三方仓库的可用性,大家可以放心大胆使用。

当然,vite也有妥协,生产模式上vite还是采用了rollup的打包方式,在考虑兼容性的情况下,让代码转换为旧浏览兼容的模式。唯一的缺点就是增加了开发和生产环境的差异性。所以资深的前端工程师在使用vite的时候要注意回归一下兼容性的问题。

同样,snowpack也是采用了开发模式Bundle Free,而生产模式还是提供bundle为可选择模式。就此看出Bundle Free并非完全适用于生产环境。

优点

  • SPA开发效率高,每个页面独立
  • 与浏览器http2的并发请求契合
  • 与浏览器的ESM Import契合
  • 与deno的ESM Import契合
  • 依赖清晰

缺点

  • 兼容性不好,生产还是考虑打包模式
  • 如果生产使用bundle-free的加载效率问题
  • 依赖需要都满足esm(antd不满足,vite2.0已经支持了部分预打包机制)
  • 开发与生产的不一致性

对未来的畅想

来自《The Third Age of JavaScript》

作为一个从Jquery走过来的前端工程师,你会明白以前的浏览器是弱化前端模块化,没有前端工程化的,所有的资源都是静态引入,前端项目的维护性是很弱的。但是结构是清晰的,学习成本非常低。进入了第二个时代,也就是webpack引领的前端工程化时代,前端项目就变成了一个JS文件,各种工具层出不穷,学习成本非常高。2020后可能会进入第三个时代,这个时代是属于Bundle Free或者Bundleless,部分前端项目可能会回到直接引用的状态,部分项目则是混合依赖的情况,在另一个程度,给前端性能优化带来了另一个可能。

  • 第一阶段:Jquery时代(直接依赖)
  • 第二阶段:前端工程化(打包依赖)
  • 第三阶段:Bundle Free?(混合依赖)

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容