前端:大家的 API 都是怎么导入导出的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
tlerbao
V2EX    程序员

前端:大家的 API 都是怎么导入导出的?

  •  1
     
  •   tlerbao 2024-02-18 22:08:06 +08:00 2671 次点击
    这是一个创建于 630 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Q:大家通常会选择下面哪种方案,指点一下理由;方案三中普通和箭头哪个更好?

    方案一

    // 分别导出 export function funA(){} export function funB(){} export function funC(){} ... // 分别导入(按需) import {funA,funB,...} from 'XX' 

    方案二

    // 分别导出 + 默认导出 export function funA(){} export function funB(){} export function funC(){} ... export default { funA,funB,funC } // 可默认全部导入也可按需导入 import {funA,funB} from 'XX' 或 import Api from 'xx' Api.funA... 

    方案三

    // 直接默认导出全部 export default { // 普通好? funA(){}, // 箭头好? funB: () => {} } // 默认导入 import Api from 'XXX' 
    29 条回复    2024-02-20 09:21:48 +08:00
    webszy
        1
    webszy  
       2024-02-18 22:12:22 +08:00
    方案 1 ,方便 tree-shaking
    webszy
        2
    webszy  
       2024-02-18 22:14:13 +08:00
    再换成 箭头函数 更好

    @webszy
    tlerbao
        3
    tlerbao  
    OP
       2024-02-18 22:16:53 +08:00
    @webszy #2 咱就是说假设 default 有 5 个接口,那么 import default 和只导入其中两个最后在打包体积上能差多啥哈哈。是不是中小项目完全不用考虑这个。
    codehz
        4
    codehz  
       2024-02-18 22:20:52 +08:00
    不是可以 import * as Api from 'XXX' 吗
    webszy
        5
    webszy  
       2024-02-18 22:22:37 +08:00
    @tlerbao 是的,不考虑优化你想怎么写就怎么写,既然你都问这个问题了,为什么不把优化做好,哪怕减少 0.1kb 对不对
    kneo
        6
    kneo  
       2024-02-18 22:23:08 +08:00 via Android
    看具体情况。细粒度的函数肯定是一二。复杂点的业务有时候也用得着三。关键还是看实际怎么用的。要是用的别扭就再琢磨琢磨。
    XCFOX
        7
    XCFOX  
       2024-02-18 22:24:48 +08:00
    几乎不用 export default ,因为 export default 不方便配合桶文件使用
    tlerbao
        8
    tlerbao  
    OP
       2024-02-18 22:26:41 +08:00
    @kneo 在打包体积效率上有没有差很多
    IvanLi127
        9
    IvanLi127  
       2024-02-18 22:27:05 +08:00
    从编码风格上来说,我选方案一,它看起来直观。方案二写起来怕漏掉,方案三缩进太多。
    tlerbao
        10
    tlerbao  
    OP
       2024-02-18 22:27:21 +08:00
    @XCFOX 知识盲区,什么叫方便配合桶文件使用?
    tlerbao
        11
    tlerbao  
    OP
       2024-02-18 22:28:47 +08:00
    @webszy #5 方案一你说换成箭头更好但是在 Webstorm 下,箭头函数没有类型注解,不如普通 function 来的直观
    不知道你能不能看见图,红线标注的普通函数默认有类型注解,不用悬停鼠标就知道返回什么类型哈
    webszy
        12
    webszy  
       2024-02-18 22:39:15 +08:00
    @tlerbao 这个不清楚,我没碰到过这个问题,不用箭头函数也可以,箭头函数其实就是原型简化了一点,如果你有 babel 转译了其实还是 function
    XCFOX
        13
    XCFOX  
       2024-02-18 22:41:53 +08:00
    桶文件本身不提供任何实现,而是重新导出其他模块的导出,一个典型的桶文件是: https://github.com/microsoft/TypeChat/blob/main/src/index.ts

    重新导出语句 export * from 'xxx' 是无法导出 export default 的。

    假如你有这样的文件结构:
    src/
    |-- utils/
    | |-- format.ts
    | |-- validate.ts
    | |-- index.ts
    并且在 src/utils/format 中使用 export default ,
    那么始终得使用 import '../utils/format' 导入。

    但是如果你使用桶文件,通常只需要 import '../utils'
    rabbbit
        14
    rabbbit  
       2024-02-18 22:43:04 +08:00
    const funA = () => {}
    export {funA}

    import {funA} from "xxx"
    tlerbao
        15
    tlerbao  
    OP
       2024-02-18 22:45:51 +08:00
    @XCFOX #13 那这样直接全部导入了,打包体积会不会很大哈。
    tlerbao
        16
    tlerbao  
    OP
       2024-02-18 22:46:19 +08:00
    @rabbbit 我 11 楼的回复就有这个差别
    XCFOX
        17
    XCFOX  
       2024-02-18 22:49:58 +08:00
    @tlerbao #15 不会,有 tree shaking
    tlerbao
        18
    tlerbao  
    OP
       2024-02-18 22:52:55 +08:00
    @XCFOX #17 太专业,你说的 tree shaking ,是某些插件自动,还是 vite 什么的有这个,虽然全部导入了,但是用到什么打包什么?瞎猜
    iOCZS
        19
    iOCZS  
       2024-02-18 23:05:17 +08:00
    @tlerbao esmoudle
    XCFOX
        20
    XCFOX  
       2024-02-18 23:06:01 +08:00
    @tlerbao 使用 vite 的话,在 dev 模式下不会自动 tree shaking ,但在 build 时会 tree shaking ,使用 webpack 始终会自动 tree shaking
    tlerbao
        21
    tlerbao  
    OP
       2024-02-18 23:47:54 +08:00
    @XCFOX #20 假设 import '../utils' 导入了 format.ts 的全部和 validate.ts 的全部,您的意思,假设我代码中只调用了 format 和 validate 中的部分,那么 vite 在打包的时候会自动 tree shaking ?是这个意思吗?
    lyxxxh2
        22
    lyxxxh2  
       2024-02-19 13:10:57 +08:00
    几个接口 直接写
    十几个接口 方案 3
    二十几个接口 方案 1

    方案 2: 感觉有点无语 1 和 3 的缝合怪
    CLMan
        23
    CLMan  
       2024-02-19 13:15:23 +08:00   2
    这个可以参考 google typescript style guidle ,只需要使用 1 ,不建议使用 2,3 ,也没有什么必须使用 2,3 的场景。

    至于上面说的桶文件,其实更多是基于兼容性和习惯( Deno 作者吐槽为设计错误),并不是说这种设计就是好的。通常情况下,仅限于包级别使用( src/index.js )。

    如果考虑浏览器兼容,需要 iife 模式(脚本模式),rollup 对 1,2 产生相同的结果,因此也不需要必须使用默认导出。

    我也不知道当初 es 是为啥设计默认导出,我一直以来猜测是为了兼容 iife 模式,一个库提供一个全局对象,避免污染 global 作用域。但没有证据能证明我的猜测。
    CLMan
        24
    CLMan  
       2024-02-19 14:48:45 +08:00   1
    @CLMan 我翻了下 ECMAScript 的早期相关讨论,终于找到了一个相关文档: https://archives.ecma-international.org/2014/misc/2014misc6.html

    这个文档证明了我的以上猜测,默认导出设计的初衷就是为了兼容类似 jQuery 这样 ES6 之前的流行的 JS 使用模式(全局单例对象),也确实如文档所说,给当时的 JS 使用者以及后来的 JS/TS 使用者造成了混乱。

    这是典型的编程语言设计时因缺乏长远考虑,给后来的使用者带来困扰,后来的使用者还必须得考古才能理解其应用场景,了解语言的缺陷仅为了避免使用该缺陷是当代的编程语言学习者常常面临的情况。
    tlerbao
        25
    tlerbao  
    OP
       2024-02-19 15:02:47 +08:00
    @CLMan #24 兄弟,太专业了吧
    SchneeHertz
        26
    SchneeHertz  
       2024-02-19 16:54:14 +08:00
    function funA(){}
    function funB(){}
    function funC(){}
    ...

    export default { funA,funB,funC }

    import {funA,funB} from 'XX'
    // or
    import XX from 'XX'

    只是习惯
    mark2025
        27
    mark2025  
       2024-02-19 18:58:57 +08:00
    1. 尽量避免同时使用具名导出和默认导出
    2. 推荐统一使用具名导出
    CLMan
        28
    CLMan  
       2024-02-20 08:46:58 +08:00
    @CLMan 补充下,默认导出目前还是有一些应用场景:

    - 使用 JS/TS 作为配置文件,rollup,jest,vite 等框架的配置文件都是采用默认导出

    除了以上场景,一般情况下自己的代码都没有必须使用默认导出的必要。
    alleluya
        29
    alleluya  
       2024-02-20 09:21:48 +08:00
    @CLMan 默认导出这个贺老吐槽过好多回 主要原因就是你回复里说的 语言设计时因缺乏长远考虑 导致后来使用时出现了混乱 和 nodejs 用 cjs 而不是 esm 也有关系吧我记得
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1436 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 46ms UTC 16:34 PVG 00:34 LAX 08:34 JFK 11:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86