点击上方“前端印象”,选择“设为星标”第一时间关注技术干货!

开发一个 npm 组件, 你是否了解需要对外导出什么格式的代码?如何让 npm 组件体积尽可能小?

整篇文章按照如下目录进行讲解:

  • 为何需要打包
  • 组件打包输出格式
  • 如何打包 esm 模式代码(感兴趣选读)
  • 减少组件打包体积的最佳实践

为何需要打包

首先,这里的打包概念解释一下, 只要有输出到新目录,就称为打包(免得大家对打包理解概念不一致)。

  • 一份代码,多种消费方式
  • 使用新特性语法,由于一般项目中,会默认不对 node_module 中的库进行编译以提高整个项目的编译速度,所以作为 npm 包,要转换成 es5 ,免得消费方吐槽……

打包格式

按照目前主流的模块系统来区分,可以先看一张图片宏观了解一下:

esm

如果是用 npm 组件来使用, 都推荐使用这种导出模式。

产生方式:
  • rollup 声明 target 为 esm 或者 babel 编译之后生成一个新的目录 (iceworks 的做法)
  • package.json 中声明 module,指向 esm
使用方式:
  • 浏览器通过 引入
  • 作为 npm 使用
特性

由于是静态的,所以可以使用 tree-shaking

umd

使用方式
  • 浏览器通过 引入
  • 浏览器通过 requirejs 或 seajs  引入 【目前这个已经很少使用了】
如何产生
  • rollup 或者 webpack 声明 target 为 umd
  • package.json 中声明 unpkg,指向对应文件

commonjs

使用方式
  • node 端, npm 方式
如何产生
  • rollup 或者 webpack 声明 target 为 commonjs
  • package.json 中声明 main,指向对应文件 。

package.json 中引用优先级如下:target 为 web 时, 依次查找 browser、module 和 main。其他 target , 依次找 module 和 main。因此如果声明了 module, 会优先读取 module 中的路径。

因此, 在导出的时候,同时设置好 main 和 module 字段,这样就可以二者兼具了,在node端,浏览器端都可以正常使用。

webpack 如何打包 esm 模式

这里不讲 rollup , 毕竟写一个 target 就可以解决了。

大家都知道,webpack 的 target 没有支持 esm 模式, 而 rollup 提供了, 为此很多人也在吐槽,为什么 webpack 不做……

我们这使用的是 iceworks , 源码地址[1],它默认支持导出 esm 模式, 那就一起看看它的源码是怎么做的。它是用 build-plugin-component 这个来实现的。【贴部分源码,感兴趣的可以看看】

  • 如果不是 jsx 或 tsx 文件, 则直接 copy 到目标目录,否则经过 bable 处理, 并将后缀改成 js

jsx.png
  • 使用 babel-plugin-import 处理第三方依赖的组件库,且兼容没有 es 模块的第三方组件

ba.png
  • 将 ts 解析生成 d.ts 文件

d.png
  • bable 7 (@babel/preset-env ),若为 esm 模块, 则关闭 module 选项

其实它实现的很简单, 如果是 es 模块, 只是用 babel 将对应的 es6 语法编译成 es5 语法(且不选择modlue), 然后 copy 到新目录 es 下, 对于里面使用到的第三方依赖组件, 用 babel-plugin-import 做一下兼容处理。

组件打包体积的最佳实践

首先,尽可能提供 esm 的格式, 因为它可以走 tree-shaking ,摇掉不必要的文件。【webpack 只要开启 production 模式,就默认有 tree-shaking 功能】

tree-shaking

tree.png
定义

如果被标记为无副作用的模块没有被直接导出使用,打包工具会跳过进行模块的副作用分析评估。由此安全地删除文件中未使用的部分。

在打包阶段,webpack无法准确判断某个文件是否有副作用,所以默认认为所有文件都是有副作用的。也就是说这里sideEffects默认是true。

副作用:一个函数会、或者可能会对函数外部变量产生影响的行为。

  • 模块作用域

将package.json 中sideEffects 设置为 false ,则表示改模块全部忽略副作用

  • 局部文件

package.json 中 sideEffects 数组写对应文件,比如常见的写上 css 文件, 如 antd 的配置

  • 函数级别

/*@__PURE__*/ 声明函数无副作用

只要我们基本保证这个组件包没有对外部对象产生影响,就能设置 sideEffects: false 了

举个栗子:设置了 sideEffects: false  和 未设置 sideEffects: false  的情况如下, 可以看到体积确实减少了不少

image.png

更深入的 sideEffect 可以看看这篇文章[2]

peerDependency

对于消费方可能也用到的组件,写到 peerDependency 中。看下面一张图就可以理解。这样可以减少重复打包。

举一个栗子:

"peerDependencies": {    "react": ">=16.12.0",    "react-dom": ">=16.12.0"}

如上的配置,可以让组件库下的 node_modules 不安装 react,同时指定组件库使用方需安装的 react/reactDOM 的版本。

external

对于打包成 umd 的文件,由于它无法分析是否存在 peerDependencies, 所以如果使用方已有 react、 react-dom 等库,需要在webpack打包时,将 external 剔除掉对应依赖。

wepack5 模块联邦

external 还是静态的,如果项目支持, 还可以使用 wepack5 Module Federation 方式,由使用方动态决定是否下载依赖。

总结

1.  对外提供组件时,同时提供 esm ,commonjs, umd 这3种方式,并且在package 中对应的字段进行声明,以确保这个包可以兼容多环境。

2. 尽可能提供 esm 模式,并且如果这个组件没有影响外部变量时,设置 sideEffect 为 false, 让使用方可以最大的 tree-shaking 。对于公用的依赖包,将其写入 peerDependencies 中。

3. 若要提供 umd 模式, 在打包时, 将对应公用依赖写入 external 剔除对应依赖。

参考资料

[1]

源码地址: https://github.com/ice-lab/iceworks

[2]

文章: https://zhuanlan.zhihu.com/p/40052192

??? 欢迎留言讨论 ???

推荐阅读   前端学习计算机网络——IP地址的划分及其分类   前端学习计算机网络——详解DNS具体作用过程

  【TCP/IP】图解TCP的通信机制

   建议收藏 | 最全的JavaScript常见的操作数组的函数方法宝典

   多图生动详解浏览器与Node环境下的Event Loop

   HTML5新特性drag API 实现拖放功能

END

❤支持三连

1.看到这里了就点个在看支持下吧,你的在看是我创作的动力。

2.关注公众号前端印象「一起交流进步」

3.关注公众号回复【加群】,拉你进技术交流群一起玩转前端。

npm run build 打包 之后怎么用_npm 组件你应该知道的事相关推荐

  1. vue-cli脚手架npm run build打包后图片路径问题 2018.11.21

    2018/11/21 最近在自己尝试做一个vue的项目,发现了一个打包以后出现的路径问题 使用npm run dev 可以正常打开项目,图片路径不会出错,使用脚手架npm run build 打包以后 ...

  2. npm run build 打包报错primordials is not defined的解决方法

    npm run build 打包报错primordials is not defined的解决方法 D:\uniapp项目\huishua_web_agent>npm run build> ...

  3. vue项目执行npm run build 打包出现某些图片,字体,资源文件路径404,无法加载的问题

    如图所示: 如果出现如图的错误.首先我们第一步是考虑进入dist文件夹里面的static文件夹 正常情况下static文件夹是非常干净的 如果你发现你的static文件夹出现了多余的img.fonts ...

  4. npm run build 打包爬坑记(1)

    npm run build 打包爬坑记 先说说打包过程,npm run build 后放入phpstudy里面,访问本地ip,查看phpstudy的端口号,就能访问页面了(访问地址:http://19 ...

  5. yarn build 和 npm run build打包有什么区别

    yarn build 和 npm run build打包有什么区别 结论: 没区别,yarn build === yarn run build === npm run build

  6. npm run build打包失败

    使用npm run build命令打包Angular项目时报错,错误信息如下: WARNING in budgets, maximum exceeded for initial. Budget 2 M ...

  7. vue2.0项目部署到服务器_vue项目运行npm run build打包后如何发布到服务器?

    运行npm run build后,怎么发布到服务器? 这样就打包成功了.然后我的项目根目录就会多一个dist文件夹,里面包含static文件夹(存放img.css.js等文件)和index.html. ...

  8. npm run build打包产生的build文件夹通过nginx部署到服务器上访问(centos8)

    首先在当前目录下,用npm run build命令将文件打包到build文件夹(或者是其他文件夹名) 把build目录传到服务器上 打开终端(提一句,Windows在Microsoft store里新 ...

  9. npm run build 打包命令

    vue使用npm run build命令打包项目 当我们使用vue-cli脚手架完成一个项目的时候,下一步肯定会想要怎么把这个项目放到互联网上或者本地直接打开呢,我们在本地调试的时候只要命令行执行np ...

最新文章

  1. Android资源文件 - 使用资源存储字符串 颜色 尺寸 整型 布尔值 数组
  2. Zoom市值达586亿美元,放中国科技巨头能排第6!净利润暴涨135倍,每天3亿人开会...
  3. Android PullToRefreshListView设置各个item之间的间距
  4. python做网络的仿真_用python自动化仿真HFSS,超简易
  5. Robot Framework(十二) javascript基础
  6. 属性绑定与双向数据绑定
  7. 基于SSM的家庭理财系统
  8. [收藏】正确使用SqlConnection对象,兼谈数据库连接池
  9. 对论文中模型进行编程实现时的注意要求和总结
  10. JS中原型和原型链的详细讲解(附代码示例)以及 new关键字具体做了什么的详细讲解
  11. 位(bit), 字节(byte), 字(word),双字(dword or Qword)释义
  12. 温莎计算机应用硕士是针对国际学生的吗,留学温莎大学
  13. Invalid byte tag in constant pool 19
  14. 【21天习惯养成记~~day17晚】
  15. JavaScript中e.keycode详解
  16. MySQL事务、MySQL索引、MySQL索引数据结构详解
  17. 【NOIP2005 提高组】篝火晚会
  18. 数据产品经理类型划分和工作汇报框架
  19. 海洋大学计算机分数线,江苏海洋大学2020录取分数线(附2017-2020年分数线)
  20. 简单的python画图小实例

热门文章

  1. 零基础学python
  2. android jni通过cmake使用第三方静态库和动态库
  3. go 关闭通道的必要性
  4. 复杂对象的组装与创建——建造者模式
  5. idea git里的用户怎么修改
  6. leetcode 140. Word Break II | 140. 单词拆分 II(动态规划)
  7. 2019秋季PAT甲级考试心得
  8. Scala教程之:Option-Some-None
  9. Java中弹出对话框的方法
  10. 栈解析html文件,利用栈将html源码解析为节点树