npm是什么意思_【第2109期】CodeSandbox是如何让npm上的模块直接在浏览器端运行的...

前言

前几天无意中看到CSB,有点意思。今日早读文章由字节跳动@众乐翻译授权分享。

@众乐(Ryan),目前就职于今日头条前端业务架构团队,通过平台、基建、工具、文档规范等手段不断挖掘业务中台通用能力,赋能上层业务及团队研发。同时,也在前端智能化、中后台研发提效、Serverless落地业务等方向执着探索。

正文从这开始~~

下文中提到的类似 支持npm相关的词都是指 在浏览器端实现对npm模块的加载、编译构建、打包、渲染&预览。

在开发CodeSandbox的初期,我总是将npm依赖模块的支持列在我们的支持范围之外。我认为在浏览器中安装任意数量的npm包是不可能实现的,即使去想一下我都觉得绝不会有实现思路。

而今天,对npm的支持已经是CodeSandbox最核心的特性之一,所以不管怎么样,我们都已经实现了它。我们做了大量的迭代来让它在任意的场景下都能正常运行;同时,我们也做了非常多的重写,甚至是在该功能已经在线上顺畅运行的今天,我们依然可以对其实现逻辑做改进。在这篇文章中,我首先会介绍刚开始我们是怎么做的,现在我们做到了一个什么程度,以及我们还可以继续做哪些改进。

'第一个'版本

当时我真的不知道如何去达成这一切,所以我做了一个非常简单的版本来在浏览器端能支持npm:

0d2d7b921f8467c1f22236e19eca50fd.png

这个版本对npm的支持非常简单。它甚至不是真正的npm支持,我只是局部安装了npm依赖,然后以已经安装的某个依赖项为入口找到它所有的依赖项,然后去一个个的执行(英文原文:I just installed the dependencies locally and stubbed every dependency call with an already installed dependency. 我理解其实现过程大致如下,比如package.json依赖了a模块,a本身依赖了b跟c,c依赖了d,在执行a的时候就需要先找到a的所有依赖项b,c,d,然后一层层的执行下去,有点像cmd规范的sea.js或者commonjs规范的require.js这些模块加载器的执行机制)。这种实现方式,对于依赖模块达到4000个并且有不同版本诉求的场景的话,很明显是非常不具备可扩展性的。

尽管这个版本不是很具备可用性,但是它却给了我勇气让我可以看到,在一个沙箱环境中至少是可以让两个依赖模块正常运行起来的。

webpack版本

我其实对第一个版本非常满意,并且我觉得它值得一个MVP(对于CodeSandbox的第一版发布)。我甚至认为,如果不施展魔法的话,在浏览器端去安装任意的一个模块是不可能的,直到偶然的机会我看到了https://esnextb.in。他们已经支持从npm上安装任意模块,你只需要在package.json中定义他们,就可以魔法般的正常运行了!

对于我来说,这是一个重要的学习时刻!我从来甚至都不敢去想能支持npm,因为始终觉得那不可能。只有在看到对于“可能”的活生生的证据之后,我才开始对它进行更多的思考。在我消除 支持npm这一想法之前,我确实应该首先去探索下它的可能性才对。

那么理所当然的,我开始思考如何去达成这一目的。而且刚开始我觉得把它给过渡复杂化了。第一个版本我觉得仅仅是在脑子里想的话我是完全hold不住的,因此我不得不把它画下来:

a1852cb8d0433907c42b9524fade69c9.png

这种过于复杂的方案却有一个优点,那就是:最终的实现要比预想的简单的多!

我了解到,webpack的DLLPlugin可以打包依赖项,并且使用一个manifest清单来标记打出的js包包含哪些依赖项。这份清单看起来是这样的:

{

"name": "dll_bundle",

"content": {

"./node_modules/fbjs/lib/emptyFunction.js": 0,

"./node_modules/fbjs/lib/invariant.js": 1,

"./node_modules/fbjs/lib/warning.js": 2,

"./node_modules/react": 3,

"./node_modules/fbjs/lib/emptyObject.js": 4,

"./node_modules/object-assign/index.js": 5,

"./node_modules/prop-types/checkPropTypes.js": 6,

"./node_modules/prop-types/lib/ReactPropTypesSecret.js": 7,

"./node_modules/react/cjs/react.development.js": 8

}

}

每一个路径都映射一个模块id。如果我想引入 React,我只需要调用 dll_bundle(3),然后我就得到了React!这对我们的需求来说简直就是完美,于是我开始行动,并思考出了一个下面的系统:

cc2bc4ba0cd2600ae0f15c4c59106e40.png

注:服务的源代码可以在这里找到:https://github.com/CompuIves/codesandbox-bundler 这个服务还包含了将任意的CodeSandbox项目代码发布到npm上(这真的很酷)的代码,我们后来取消了这个功能。

对于打包的每一个请求,我将在 tmp/:hash下面创建一个新的目录࿰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值