Umi: 组件开发插件

Created on 29 Nov 2018  ·  41Comments  ·  Source: umijs/umi

背景

为了更方便的进行组件开发调试,并能很爽的写文档。在调研了流行的 storybook 和 docz 后,选型使用 docz,目前将计划开发 umi-plugin-doczumi-plugin-component,在此跟进与讨论。

项目地址

https://github.com/umijs/umi-plugin-library

进展

  • [ ] 细化方案
  • [x] 第一版演示 2018-12-13
  • [x] 内部第一版脚手架 2018-12-18
  • [x] 对外脚手架 2018-12-31
type(enhancement)

Most helpful comment

调研笔记。

  • 问题

    • package.json 里的各个项是什么意思?

    • cjs, esm, umd, amd 是什么意思?他们是怎么来的?

    • es 2015 和 es6 是什么关系?

    • tree-shaking 怎么实现的?

    • 为什么有 .mjs?

    • 组件打包怎么处理补丁?@babel/plugin-transform-runtime 要不要加 polyfill?

  • 两个功能

    • doc 命令



      • 包括 doc devdoc build


      • 基于 docz 实现


      • 实现上可以再分层,通过 umi-plugin-docz 实现,这样项目要用 docz 也可以用


      • 然后 library 引 umi-plugin-docz 实现 doc 命令



    • build



      • 基于 rollup + babel



    • publish



      • changelog


      • commit


      • tag


      • push



  • 调研

    • htm


    • redux



      • 基于 rollup


      • 打出以下格式





        • lib/redux.js







          • commonjs (cjs)




          • external 依赖




          • 不压缩







        • es/redux.js







          • es module




          • external 依赖




          • 不压缩







        • es/redux.mjs







          • 为浏览器用的 es module




          • es module




          • 不 external 依赖




          • replace NODE_ENV 为 production




          • 压缩







        • dist/redux.js







          • umd,暴露为 Redux 全局变量




          • replace NODE_ENV 为 development




          • 不压缩







        • dist/redux.min.js







          • umd,暴露为 Redux 全局变量




          • replace NODE_ENV 为 production




          • 压缩










    • react-router



      • cjs/react-router.js





        • commonjs



        • external 依赖



        • 同步生成 min 文件





      • esm/react-router.js





        • es module



        • external 依赖



        • babel 配 runtimeHelpers: true,并且加 @babel/transform-runtieme + useESModules: true





      • umd/react-router.js





        • globals = react: React



        • 对外露出 ReactRouter



        • 调 commonjs 插件把 commonjs 转成 esm,让 node_modules 下的模块也能走 tree-shaking






    • reach-router



      • es





        • 把 src 下的文件打到 es 目录下



        • 基于 babel,env + modules: false,不做 modules 转化





      • cjs





        • 把 src 下的文件打到 ./ 根目录



        • 基于 babel, env + modules: 'commonjs'





      • umd





        • umd/reach-router.js







          • 有 min 版本




          • 基于 rollup




          • globals 掉 react 和 react-dom










    • redux-saga


    • immer



      • dist/immer.js





        • cjs



        • 不压缩





      • dist/immer.umd.js





        • umd



        • 压缩





      • dist/immer.module.js





        • es



        • 不压缩






    • mobx



      • 把 src 生成 .build.es5 和 .build.es6


      • 生成以下文件





        • 基于 rollup



        • lib/mobx.js, cjs



        • lib/mobx.module.js, esm



        • lib/mobx.es6.js, esm





      • 生成 umd 包 lib/mobx.umd.js





        • 基于 browserify





      • 基于 envify 生成 lib/mobx.prod.js


      • 基于 uglifyjs 生成





        • lib/mobx.min.js



        • lib/mobx.umd.min.js






  • 几种格式

    • es 5 module system



      • cjs (common js)





        • require 和 module.exports



        • 同步加载



        • 适合 server 端





      • amd





        • Asynchronous Module Definition



        • seajs, requirejs



        • define + require



        • 异步加载



        • 适合 browser 端






    • es 6 modules



      • 来自 es6 / es2015


      • 同时解决 cjs 和 amd 的需要


      • export (default) 和 import


      • 浏览器里怎么用?





        • import()



        • require.ensure()



        • System.import()



        • type="module"






    • umd

  • 产出格式

    • cjs



      • 给谁用?





        • node 端



        • 组件是不是不用产出 cjs 产物?







          • 不是,比如要支持 ssr









      • 怎么产生?倾向后者。





        • babel 直接转,比如把 src 转成 cjs 或 lib,多文件,然后 package.json 里配 lib



        • rollup 转,单文件,比如生成 dist/[name].js







          • 可以区分 development 和 production




          • 可以有 proxy 层,自动引入 dev 或 prod 版本









      • 注意点





        • external dependencies + peerDependencies






    • esm



      • 给谁用?





        • webpack(浏览器端)



        • 浏览器直接用







          • script type="module"







        • node 端?








      • 为什么用?





        • 新版方案,解决 commonjs 和 amd 的方案



        • tree shaking,因为是静态的产出





      • 怎么产生?





        • babel 转,比如把 src 转成 es,多文件,然后 package.json 里配 es



        • rollup 转,单文件,比如生成 dist/[name].esm.js







          • esm 已经可以做 tree-shaking,所以不需要产生多个文件,即可实现按需




          • 单文件在 webpack 使用时更快,因为少了文件系统 io









      • 注意点





        • external dependencies + peerDependencies



        • 根据库的实际情况考虑是否配 sideEffect: false 或者 sideEffect: [文件1, 文件2]






    • umd



      • 给谁用?





        • 浏览器直接引





      • 怎么产生





        • rollup







          • 单文件,比如生成 dist/[name].umd.js




          • 同时生成 min 文件,比如 dist/[name].umd.min.js




          • 然后在 package.json 里配 unpkg 或 umd:main 指向他







        • webpack







          • 感觉会慢且大







        • browserify







          • 过时









      • 注意点





        • 只 external peerDependencies,不 external dependencies







          • 比如我们通常要 external react, react-dom, antd, dva 等




          • rollup 里通过 globals 实现










  • 方案

    • 基于 rollup



      • 相比 webpack





        • 构建速度快



        • 产物小



        • tree-shaking 优势







          • 通过 commonjs 插件,把 node_modules 下的依赖也转成 esm,使之支持 tree-shaking









      • 专注于组件构建,社区成熟



    • 关于配置



      • 配置方式





        • umi 通过插件使用,['umi-plugin-library', {}]



        • bigfish 通过 library 配置





      • 配置项





        • entry: src/index.js



        • extraBabelPlugins







          • 比如为 antd 配置 babel-plugin-import







        • umd







          • globals(别名:externals)









            • 比如 react:React,'react-dom':ReactDOM












        • cjs







          • type: rollup | babel




          • dir: lib




          • proxy: true | false







        • esm







          • type: rollup | babel




          • dir: es







        • doc







          • 透传给 umi-plugin-docz 用










    • 脚手架 MVP



      • 注:不包含 doc 的部分


      • package.json





        • name: foo



        • main: dist/foo.js







          • cjs







        • module: dist/foo.esm.js



        • unpkg: dist/foo.umd.js





      • src





        • Foo.js



        • Bar.js



        • index.js







          • import from Foo.js and Bar.js







        • index.css





      • 输出





        • dist/







          • foo.js




          • foo.esm.js




          • foo.umd.js




          • foo.umd.min.js




          • 一一对应的 css 文件










    • 使用场景



      • react 组件


      • 非 react 组件


      • 独立库


      • 集成在项目中使用





        • 可指定 entry,比如 components/index.js



        • 可指定输出路径,并在此路径包含 package.json







          • name




          • dependencies




          • 等等









      • lerna 项目



    • 包含功能


  • package.json 里的项

    • main



      • 指向 cjs



    • module



      • 指向 esm



    • unpkg



      • 指向 umd



    • umd:main



      • 同 unpkg,用一个就好了



    • typings

    • 这些项在 webpack 里的应用


  • tree shaking

    • 去死代码

    • 依赖 es module 的 Static module structure



      • import 和 export 都是静态的


      • 相比之下,commonjs 的 require 和 exports 是动态的



    • 概念和名词由 rollup 引入

    • sideEffects



      • 可以是 false,也可以是数组


      • 在 100% 的 ESM 世界里是不需要的



  • 脑暴

    • react 包的处理方式

    • mjs

    • 怎么用?

  • 词汇

    • JavaScript

    • ECMAScript

    • ES3



      • 1999



    • ES5



      • 第 5 版 ECMAScript,于 2009 年标准化



    • ES6 / ES2015



      • 第 6 版



    • ES2016



      • 第 7 版



  • JavaScript 来源

    • 1995



      • LiveScript,作为 Netscape Navigator 的一部分


      • 一年半后,更名为 JavaScript



    • 1996



      • Netscape 向 ECMA International 提交标准化 JavaScript


      • 即 ECMAScript



    • 1999



      • ECMAScript 3



    • 2009



      • ECMAScript 5



    • 2015



      • ECMAScript 6



    • 2016



      • ECMAScript 7



参考

All 41 comments

umi-plugin-component 改成 umi-plugin-library 吧,通用的,不只是 component。

cc @zinkey

就搞一个 umi-plugin-docz 就行,过度分层也没必要。

那应该是 umi-plugin-library 这个插件,然后里面有 docz 这个的一个配置?

plugins: [[
  'umi-plugin-library',
  {
    docz: true,
  }
]]

umi-plugin-library 具体做什么功能呢?

umi-plugin-library 具体做什么功能呢?

如果不包含 doc 的话主要就是构建打包这块,库,组件和应用的打包方式不一样。比如说:

  • react 这些不应该打包进去。
  • 默认应该要转换为 es5,不能包含箭头函数这些。
  • 构建后的内容放到 lib 下面。

docz 也包含了 build,那就是不用 docz 的 build?那 dev 是否包含呢?要是 umi-plugin-library 只包含 build 好像不是很好用,不如给个 umi-plugin-docz dev,build 都有

docz 只是文档,不会包含 library 的 build 的,library 的 build 得通过 rollup 来做。

docz 不仅仅是文档,包含了 build 的

这个 build 分为两种,一种是 doc site build ,另一种是 component 的 build,component 的 build 应该放在 library 中。
如果不分层,将docz 放在 umi-plugin-library中,那 library 同时可以 build doc 也可以 buid component。

关于结构,我想分两个部分:

umi-plugin-docz

包含: docz 相关, doc 界面,doc的插件,对doc的增强,定制的东西比较多,比如支持 theme,相对 library 较独立。

使用方式:
umi doc [--dev] // 跑 doc server
umi doc --build // build
umi doc --deploy // 部署

umi-plugin-library

包含:打包, 可以打包任何东西,umi-tools build 能做吗?

使用方式:
umi library --build [ --input /src/component --output /lib ]

其他使用方式
umi dev --doc?
umi build --doc ?
umi build --library ?

优点:看起来umi命令没那么多。
缺点:侵入 umi代码。

你们的意见呢?

我的建议是这样,不侵入 umi 代码,

$ umi docz build
$ umi docz dev
$ umi docz deploy

$ umi library dev
$ umi library build

就 umi library 好了,docz 只是 umi library 依赖的文档工具,不需要在命令行展现。

就 umi library 好了,docz 只是 umi library 依赖的文档工具,不需要在命令行展现。

好,我就这样先搞一波。

@clock157 是2012-12-13? 2018-12-13!

$ umi lib dev
$ umi lib build

看看能不能加个 lib 的 alias,毕竟最后也是放到 lib 目录

加了 https://github.com/umijs/umi/pull/1585 一个 _modifyCommand 这个插件方法,可以实现命令行别名。

别名内置就好了,参考 umi gumi generate

umi library dev 需要调用 umi dev 吗?还是说完全独立的一套构建?

按我理解,library 要么用 test 调,要么用 docz 调吧。

umi 的 library 可以在一些纯打包 component 的项目中使用吗?比如 ant-design。

目前有一些类似的方案:

@xiaoxiangmoe 这个需求就是为了解决这种场景,使得 umi 能够支持组件或者库的开发。

目前 library 实现了 dev 和 build,在这两个方向进行了一系列探索,反馈一下我的思路,大家有没有补充或问题:

dev

进度:可以正常调试,主题的还比较简陋。

  • 基于 docz,支持 mdx 编写组件文档。
  • 通过定制 docz-theme-antd,调研 docz 内部实现,发现可以很方便的进行定制。组件官网,文档说明,组件演示,典型页面,演示站,在同一套代码中即可实现。
  • 基于 webpack,使用 umi 运行时配置能比较好的兼容组件运行。

build

进度:可以打包组件,生成es5, es6 库文件,打的包已可以应用于项目。umd 还在调研

  • 调研了 antd material-ui bootstrap 等多个 ui 框架,普遍的做法是:用babel 编译一个 es5 的组件lib,编译一个 es6 的支持模块加载,最后再打包一个 umd 的包支持全家桶引用和浏览器使用。
  • 目前基于 babel 实现了 es5 和 es6 的库编译。支持css_modules,抽出了 less,并生产一个单独的样式文件。拿 ant-design-pro 打了一个产物已发布 testumilibrary-ant-design-pro 有兴趣可以看下,可以跑起来,样式正常。
  • umd 包准备试一下 rollup, 但是 umd 包需要将一些依赖打进去,这样才能兼容浏览,但 rollup 打依赖可能存在一大堆 named export 错需要解决,这方面经验稍后借鉴下 @xiaoxiangmoe 提到的 microbundle。除了 rollup ,还在犹豫是否使用 webpack 打包 umd ? 因为开发调试使用都是 webpack, 方案也比较成熟。大家的意见?rollup 的优势是 treeshaking, 现在 webpack 也支持,还有其他优点吗?

test

进度: 测试还未推进,build 搞好学习下 antd 目前应用的 jest + enzyme。如有兴趣的同学可以帮下我,最近业务太忙了= =;

我建议是直接用 af-webpack,既然在 umi 体系内,能复用的东西用一套就好,rollup 比起 webpack 其实没有本质的优势,遇到自定义配置时还得学和写另一套配置方式。

rollup 的优势是 treeshaking, 现在 webpack 也支持,还有其他优点吗?

看下构建产物的区别呢?比如尺寸。

语雀那边组件开发需求蛮强烈的,bigfish 上了之后可以从他们那里开始试水。

我的想法。

基本思路

  • 通过 umi-plugin-library 露出

    • 基于 rollup

  • doc 部分下沉到 umi-plugin-docz 里,然后在 umi-plugin-library 里调他,并透传参数

命令行

$ umi lib doc dev
$ umi lib doc build
$ umi lib doc publish
$ umi lib build
$ umi lib test
$ umi lib publish

注:

  • umi libumi library 的别名

配置方式

  • umi 通过插件使用,['umi-plugin-library', {}]
  • bigfish 通过 library 配置

配置项

  • entry: String | Object

    • 默认 src/index.(t|j)sx?

  • extraBabelPlugins: Array

    • 比如为 antd 配置 babel-plugin-import

  • umd: Object | false

    • 值为 false 时不生成

    • globals: Object

    • name: String

  • cjs: Object | false

    • 值为 false 时不生成

    • type: rollup | babel

    • 默认 rollup

    • dir: String

    • 默认 lib

    • proxy: Boolean

    • 默认 false

  • esm: Object | false

    • 值为 false 时不生成

    • type: rollup | babel

    • 默认 rollup

    • dir: String

    • 默认 es

  • doc

    • 透传给 umi-plugin-docz

脚手架 MVP

仅考虑 build 部分,实际脚手架需添加 doc 和 test 部分。

package.json

  • name: 'foo'
  • main: 'dist/foo.js

    • cjs

  • module: 'dist/foo.esm.js'

    • es modules

  • unpkg: 'dist/foo.umd.js'
  • sideEffects

    • 按需配置,可以是 false 或数组

src

  • index.js

    • import from Foo.js and Bar.js

  • index.css
  • Foo.js
  • Bar.js

dist (build 后输出)

  • foo.js
  • foo.esm.js
  • foo.umd.js
  • foo.umd.min.js
  • 以及相关 css 文件

调研笔记。

  • 问题

    • package.json 里的各个项是什么意思?

    • cjs, esm, umd, amd 是什么意思?他们是怎么来的?

    • es 2015 和 es6 是什么关系?

    • tree-shaking 怎么实现的?

    • 为什么有 .mjs?

    • 组件打包怎么处理补丁?@babel/plugin-transform-runtime 要不要加 polyfill?

  • 两个功能

    • doc 命令



      • 包括 doc devdoc build


      • 基于 docz 实现


      • 实现上可以再分层,通过 umi-plugin-docz 实现,这样项目要用 docz 也可以用


      • 然后 library 引 umi-plugin-docz 实现 doc 命令



    • build



      • 基于 rollup + babel



    • publish



      • changelog


      • commit


      • tag


      • push



  • 调研

    • htm


    • redux



      • 基于 rollup


      • 打出以下格式





        • lib/redux.js







          • commonjs (cjs)




          • external 依赖




          • 不压缩







        • es/redux.js







          • es module




          • external 依赖




          • 不压缩







        • es/redux.mjs







          • 为浏览器用的 es module




          • es module




          • 不 external 依赖




          • replace NODE_ENV 为 production




          • 压缩







        • dist/redux.js







          • umd,暴露为 Redux 全局变量




          • replace NODE_ENV 为 development




          • 不压缩







        • dist/redux.min.js







          • umd,暴露为 Redux 全局变量




          • replace NODE_ENV 为 production




          • 压缩










    • react-router



      • cjs/react-router.js





        • commonjs



        • external 依赖



        • 同步生成 min 文件





      • esm/react-router.js





        • es module



        • external 依赖



        • babel 配 runtimeHelpers: true,并且加 @babel/transform-runtieme + useESModules: true





      • umd/react-router.js





        • globals = react: React



        • 对外露出 ReactRouter



        • 调 commonjs 插件把 commonjs 转成 esm,让 node_modules 下的模块也能走 tree-shaking






    • reach-router



      • es





        • 把 src 下的文件打到 es 目录下



        • 基于 babel,env + modules: false,不做 modules 转化





      • cjs





        • 把 src 下的文件打到 ./ 根目录



        • 基于 babel, env + modules: 'commonjs'





      • umd





        • umd/reach-router.js







          • 有 min 版本




          • 基于 rollup




          • globals 掉 react 和 react-dom










    • redux-saga


    • immer



      • dist/immer.js





        • cjs



        • 不压缩





      • dist/immer.umd.js





        • umd



        • 压缩





      • dist/immer.module.js





        • es



        • 不压缩






    • mobx



      • 把 src 生成 .build.es5 和 .build.es6


      • 生成以下文件





        • 基于 rollup



        • lib/mobx.js, cjs



        • lib/mobx.module.js, esm



        • lib/mobx.es6.js, esm





      • 生成 umd 包 lib/mobx.umd.js





        • 基于 browserify





      • 基于 envify 生成 lib/mobx.prod.js


      • 基于 uglifyjs 生成





        • lib/mobx.min.js



        • lib/mobx.umd.min.js






  • 几种格式

    • es 5 module system



      • cjs (common js)





        • require 和 module.exports



        • 同步加载



        • 适合 server 端





      • amd





        • Asynchronous Module Definition



        • seajs, requirejs



        • define + require



        • 异步加载



        • 适合 browser 端






    • es 6 modules



      • 来自 es6 / es2015


      • 同时解决 cjs 和 amd 的需要


      • export (default) 和 import


      • 浏览器里怎么用?





        • import()



        • require.ensure()



        • System.import()



        • type="module"






    • umd

  • 产出格式

    • cjs



      • 给谁用?





        • node 端



        • 组件是不是不用产出 cjs 产物?







          • 不是,比如要支持 ssr









      • 怎么产生?倾向后者。





        • babel 直接转,比如把 src 转成 cjs 或 lib,多文件,然后 package.json 里配 lib



        • rollup 转,单文件,比如生成 dist/[name].js







          • 可以区分 development 和 production




          • 可以有 proxy 层,自动引入 dev 或 prod 版本









      • 注意点





        • external dependencies + peerDependencies






    • esm



      • 给谁用?





        • webpack(浏览器端)



        • 浏览器直接用







          • script type="module"







        • node 端?








      • 为什么用?





        • 新版方案,解决 commonjs 和 amd 的方案



        • tree shaking,因为是静态的产出





      • 怎么产生?





        • babel 转,比如把 src 转成 es,多文件,然后 package.json 里配 es



        • rollup 转,单文件,比如生成 dist/[name].esm.js







          • esm 已经可以做 tree-shaking,所以不需要产生多个文件,即可实现按需




          • 单文件在 webpack 使用时更快,因为少了文件系统 io









      • 注意点





        • external dependencies + peerDependencies



        • 根据库的实际情况考虑是否配 sideEffect: false 或者 sideEffect: [文件1, 文件2]






    • umd



      • 给谁用?





        • 浏览器直接引





      • 怎么产生





        • rollup







          • 单文件,比如生成 dist/[name].umd.js




          • 同时生成 min 文件,比如 dist/[name].umd.min.js




          • 然后在 package.json 里配 unpkg 或 umd:main 指向他







        • webpack







          • 感觉会慢且大







        • browserify







          • 过时









      • 注意点





        • 只 external peerDependencies,不 external dependencies







          • 比如我们通常要 external react, react-dom, antd, dva 等




          • rollup 里通过 globals 实现










  • 方案

    • 基于 rollup



      • 相比 webpack





        • 构建速度快



        • 产物小



        • tree-shaking 优势







          • 通过 commonjs 插件,把 node_modules 下的依赖也转成 esm,使之支持 tree-shaking









      • 专注于组件构建,社区成熟



    • 关于配置



      • 配置方式





        • umi 通过插件使用,['umi-plugin-library', {}]



        • bigfish 通过 library 配置





      • 配置项





        • entry: src/index.js



        • extraBabelPlugins







          • 比如为 antd 配置 babel-plugin-import







        • umd







          • globals(别名:externals)









            • 比如 react:React,'react-dom':ReactDOM












        • cjs







          • type: rollup | babel




          • dir: lib




          • proxy: true | false







        • esm







          • type: rollup | babel




          • dir: es







        • doc







          • 透传给 umi-plugin-docz 用










    • 脚手架 MVP



      • 注:不包含 doc 的部分


      • package.json





        • name: foo



        • main: dist/foo.js







          • cjs







        • module: dist/foo.esm.js



        • unpkg: dist/foo.umd.js





      • src





        • Foo.js



        • Bar.js



        • index.js







          • import from Foo.js and Bar.js







        • index.css





      • 输出





        • dist/







          • foo.js




          • foo.esm.js




          • foo.umd.js




          • foo.umd.min.js




          • 一一对应的 css 文件










    • 使用场景



      • react 组件


      • 非 react 组件


      • 独立库


      • 集成在项目中使用





        • 可指定 entry,比如 components/index.js



        • 可指定输出路径,并在此路径包含 package.json







          • name




          • dependencies




          • 等等









      • lerna 项目



    • 包含功能


  • package.json 里的项

    • main



      • 指向 cjs



    • module



      • 指向 esm



    • unpkg



      • 指向 umd



    • umd:main



      • 同 unpkg,用一个就好了



    • typings

    • 这些项在 webpack 里的应用


  • tree shaking

    • 去死代码

    • 依赖 es module 的 Static module structure



      • import 和 export 都是静态的


      • 相比之下,commonjs 的 require 和 exports 是动态的



    • 概念和名词由 rollup 引入

    • sideEffects



      • 可以是 false,也可以是数组


      • 在 100% 的 ESM 世界里是不需要的



  • 脑暴

    • react 包的处理方式

    • mjs

    • 怎么用?

  • 词汇

    • JavaScript

    • ECMAScript

    • ES3



      • 1999



    • ES5



      • 第 5 版 ECMAScript,于 2009 年标准化



    • ES6 / ES2015



      • 第 6 版



    • ES2016



      • 第 7 版



  • JavaScript 来源

    • 1995



      • LiveScript,作为 Netscape Navigator 的一部分


      • 一年半后,更名为 JavaScript



    • 1996



      • Netscape 向 ECMA International 提交标准化 JavaScript


      • 即 ECMAScript



    • 1999



      • ECMAScript 3



    • 2009



      • ECMAScript 5



    • 2015



      • ECMAScript 6



    • 2016



      • ECMAScript 7



参考

超赞!虽然我也调研过好些库,但是没有通过这样的形式进行整理和输出,知识成了个人的一次性消费,今后也要这样带着问题去调研和整理。😁

学习了,就是专业啊。不愧是我偶像

我还有很多疑问🤔️:

  1. 比如entry: String | Objectumd: Object | false,很多地方用了 Array 和 Object,而这里面具体是 Array<String>,还是 Array<{foo:string,bar?:number,baz:number|string}> ,作为文档的阅读者,我并不清楚这些,建议用更严格的 TypeScript 类型签名指定
  2. build,基于 rollup + babel,那么是通过 babel 提供 TypeScript 的支持,还是 rollup-plugin-typescript2 提供 TypeScript 支持,比如 rollup-plugin-typescript2 的一些配置,比如 transformers,babel 是否有对应的解决方案?
  3. publish 是在 ci 上 push 到某个分支执行,还是得用户手动执行,是否要测试和 lerna 的 publish 的兼容性,因为 lerna 以及它的插件也提供了 changelog/commit/tag/push 等功能
  4. 纯网页端的库是否要提供 cjs?(是否有无浏览器运行的测试库依赖 cjs? ssr 可以不依赖 cjs 吗?)
  5. <package>.module 字段和 moment 里的<package>."jsnext:main"字段有什么关系?<package>.typings<package>.types有什么区别?
  6. es module 是否要提供压缩版本的,给浏览器端的 type='module'使用?比如 foo.esm.min.js
  7. 是否要提供 css 的 tree shaking?我们因为库很庞大时候,css 代码可能会很多,有 TypeScript 的 transformer 做了类似的事情:https://github.com/Brooooooklyn/ts-import-plugin
  8. 由于是提供库,我们是否要提供 css 的 class 名的规则自定义?毕竟不是直接最下游的用户,可以无脑 uglify 加 hash
  9. 哪些包应该打包进 umd,哪些应该作为依赖?我用 umd 会不会出现上游的 A 和 B 都依赖 moment,于是我加载了两个 moment?
  10. 可指定 entry,entry 是否要像 micro bundle 里一样使用 source 字段?这会影响到下游的 source package 的使用吗?比如 https://github.com/parcel-bundler/parcel/pull/1101

@xiaoxiangmoe 好问题,我找时间整理下。

  1. 比如entry: String | Objectumd: Object | false,很多地方用了 Array 和 Object,而这里面具体是 Array<String>,还是 Array<{foo:string,bar?:number,baz:number|string}> ,作为文档的阅读者,我并不清楚这些,建议用更严格的 TypeScript 类型签名指定

好,等我先熟悉下 Typescript。

  1. build,基于 rollup + babel,那么是通过 babel 提供 TypeScript 的支持,还是 rollup-plugin-typescript2 提供 TypeScript 支持,比如 rollup-plugin-typescript2 的一些配置,比如 transformers,babel 是否有对应的解决方案?

我倾向于 typescript 的方案全部统一到 babel 里做,这样可以顺便让 webpack 和 rollup 里保持一致,没必要有多种方案。cra 也是用的 babel 处理 typescript。

  1. publish 是在 ci 上 push 到某个分支执行,还是得用户手动执行,是否要测试和 lerna 的 publish 的兼容性,因为 lerna 以及它的插件也提供了 changelog/commit/tag/push 等功能

publish 不是核心功能,只做简单的,比如 changelog 生成、交互式升版本、打 tag、push 等。不做和 lerna 的整合,用 lerna 的场景直接用 lerna-changelog + lerna publish 就行了。

  1. 纯网页端的库是否要提供 cjs?(是否有无浏览器运行的测试库依赖 cjs? ssr 可以不依赖 cjs 吗?)

个人认为 cjs 是给 node 环境用的,因为 webpack/rollup 都走 esm 了,但不排除一些老的打包工具(比如 systemjs.js,webpack 1 等等)不支持 esm,还在使用 cjs。

理论上,给浏览器用的库且无 ssr 需求是可以不生成 cjs 格式,不过我觉得还是都提供吧,万一以后有 ssr 需求了呢?

  1. <package>.module 字段和 moment 里的<package>."jsnext:main"字段有什么关系?<package>.typings<package>.types有什么区别?

jsnext:main 是技术发展的中间产物吧,现在应该不太用了。比如 webpack 默认的 resovle 字段是:browser -> module -> main,所以写了通常也没有用。

我的理解是:

  • main: es5
  • module: es5 + esm
  • jsnext:main: es next,包括 esm,通常是指向 src/index.js

参考:https://github.com/jsforum/jsforum/issues/5

  1. es module 是否要提供压缩版本的,给浏览器端的 type='module'使用?比如 foo.esm.min.js

我觉得可以提供,但默认先不开,然后输出名是 foo.mjsfoo.min.mjs。另外,这种使用方式短时间内我觉得流行不起来,在我调研的库里只有 redux 里有输出这种格式。

  1. 是否要提供 css 的 tree shaking?我们因为库很庞大时候,css 代码可能会很多,有 TypeScript 的 transformer 做了类似的事情:https://github.com/Brooooooklyn/ts-import-plugin

可以自行配置,但不内置的工具里。

  1. 由于是提供库,我们是否要提供 css 的 class 名的规则自定义?毕竟不是直接最下游的用户,可以无脑 uglify 加 hash

处理 css 命名冲突的方案有很多,应用自己选就好了,工具层不做限制。

  • css 前缀
  • css modules
  • bem
  • css in js
  1. 哪些包应该打包进 umd,哪些应该作为依赖?我用 umd 会不会出现上游的 A 和 B 都依赖 moment,于是我加载了两个 moment?

这也应该是工具使用者决定的,moment、react、react-dom 我觉得通常都不应该打到 umd 包里。

  1. 可指定 entry,entry 是否要像 micro bundle 里一样使用 source 字段?这会影响到下游的 source package 的使用吗?比如 https://github.com/parcel-bundler/parcel/pull/1101

配置不在 package.json 里,而是作为插件的配置项。source 不支持,我觉得用不到。

我倾向于 typescript 的方案全部统一到 babel 里做,这样可以顺便让 webpack 和 rollup 里保持一致,没必要有多种方案。cra 也是用的 babel 处理 typescript。

cra 使用 babel 处理 TypeScript,但是禁止了 CustomTransformers 的使用,而我们未来可能会基于 TypeScript 的 CustomTransformers 做很多工作,比如非 js 文件的类型签名在编译期的生成和检查等(比如 css-module 的类型签名,现在我们只能基于 language service plugin 来做基于编辑器的编辑阶段的检查,而不会影响到编译期)。

Babel 的 AST 和 TypeScript 的 AST 差别挺大的,不方便做这些事情。我觉得我们应该推进 cra 使用 ts-loader 来支持 CustomTransformers。

publish 不是核心功能,只做简单的,比如 changelog 生成、交互式升版本、打 tag、push 等。

也就是「我们每次的 publish 是人手动介入的,在 cli 里交互式地 publish」的意思吗?

内部分享版。

《如何打包组件?》

Why,组件为什么要打包?

  • 组件是一层抽象,他需要输出,给项目用
  • 源码并不能直接用

    • es6

    • es modules

    • ...

What

src -> dist,做输出,给项目用

输出什么?

  • 来源于需求,有人用才会有输出
  • amd
  • cjs
  • esm

    • 浏览器版

    • node 版

  • umd

模块历史

通过 package.json 看各种格式

  • main

    • 指向 cjs

  • module

    • 指向 esm

  • unpkg

    • 指向 umd

  • umd:main

    • 同 unpkg,用一个就好了

  • typings
  • 这些项在 webpack 里的应用
  • sideEffects

    • 可以是 false,也可以是数组

    • 拿来做 tree-shaking


    • 在 100% 的 ESM 世界里是不需要的

名词解释,ES6, ES2015, EMCAScript, JavaScript, ES Next ...

  • JavaScript 来源

    • 1995



      • LiveScript,作为 Netscape Navigator 的一部分


      • 一年半后,更名为 JavaScript



    • 1996



      • Netscape 向 ECMA International 提交标准化 JavaScript


      • 即 ECMAScript



    • 1999



      • ECMAScript 3



    • 2009



      • ECMAScript 5



    • 2015



      • ECMAScript 6



    • 2016



      • ECMAScript 7



  • ES Next

    • = babel ?

How

  • 从需求到实现(从怎么用到怎么实现)

cjs

  • 怎么用?

    • node 端

    • 组件是不是不用产出 cjs 产物?



      • 不是,比如要支持 ssr



  • 怎么产生?倾向后者。

    • babel 直接转,比如把 src 转成 cjs 或 lib,多文件,然后 package.json 里配 lib

    • rollup 转,单文件,比如生成 dist/[name].js



      • 可以区分 development 和 production


      • 可以有 proxy 层,自动引入 dev 或 prod 版本



  • 注意点

    • external dependencies + peerDependencies

esm

  • 怎么用?

    • webpack(浏览器端)

    • 浏览器直接用



      • script type="module"



    • node 端?


  • 为什么用?

    • 新版方案,解决 commonjs 和 amd 的方案

    • tree shaking,因为是静态的产出

  • 怎么产生?

    • babel 转,比如把 src 转成 es,多文件,然后 package.json 里配 es

    • rollup 转,单文件,比如生成 dist/[name].esm.js



      • esm 已经可以做 tree-shaking,所以不需要产生多个文件,即可实现按需


      • 单文件在 webpack 使用时更快,因为少了文件系统 io



  • 注意点

    • external dependencies + peerDependencies

    • 根据库的实际情况考虑是否配 sideEffect: false 或者 sideEffect: [文件1, 文件2]

umd

  • 怎么用?

    • 浏览器直接引

  • 怎么产生

    • rollup



      • 单文件,比如生成 dist/[name].umd.js


      • 同时生成 min 文件,比如 dist/[name].umd.min.js


      • 然后在 package.json 里配 unpkg 或 umd:main 指向他



    • webpack



      • 感觉会慢且大



    • browserify



      • 过时



  • 注意点

    • 只 external peerDependencies,不 external dependencies



      • 比如我们通常要 external react, react-dom, antd, dva 等


      • rollup 里通过 globals 实现



社区的库是怎么用的?

  • htm
  • redux

    • 基于 rollup

    • 打出以下格式



      • lib/redux.js





        • commonjs (cjs)



        • external 依赖



        • 不压缩





      • es/redux.js





        • es module



        • external 依赖



        • 不压缩





      • es/redux.mjs





        • 为浏览器用的 es module



        • es module



        • 不 external 依赖



        • replace NODE_ENV 为 production



        • 压缩





      • dist/redux.js





        • umd,暴露为 Redux 全局变量



        • replace NODE_ENV 为 development



        • 不压缩





      • dist/redux.min.js





        • umd,暴露为 Redux 全局变量



        • replace NODE_ENV 为 production



        • 压缩






  • react-router

    • cjs/react-router.js



      • commonjs


      • external 依赖


      • 同步生成 min 文件



    • esm/react-router.js



      • es module


      • external 依赖


      • babel 配 runtimeHelpers: true,并且加 @babel/transform-runtieme + useESModules: true



    • umd/react-router.js



      • globals = react: React


      • 对外露出 ReactRouter


      • 调 commonjs 插件把 commonjs 转成 esm,让 node_modules 下的模块也能走 tree-shaking



  • reach-router

    • es



      • 把 src 下的文件打到 es 目录下


      • 基于 babel,env + modules: false,不做 modules 转化



    • cjs



      • 把 src 下的文件打到 ./ 根目录


      • 基于 babel, env + modules: 'commonjs'



    • umd



      • umd/reach-router.js





        • 有 min 版本



        • 基于 rollup



        • globals 掉 react 和 react-dom






  • redux-saga
  • immer

    • dist/immer.js



      • cjs


      • 不压缩



    • dist/immer.umd.js



      • umd


      • 压缩



    • dist/immer.module.js



      • es


      • 不压缩



  • mobx

    • 把 src 生成 .build.es5 和 .build.es6

    • 生成以下文件



      • 基于 rollup


      • lib/mobx.js, cjs


      • lib/mobx.module.js, esm


      • lib/mobx.es6.js, esm



    • 生成 umd 包 lib/mobx.umd.js



      • 基于 browserify



    • 基于 envify 生成 lib/mobx.prod.js

    • 基于 uglifyjs 生成



      • lib/mobx.min.js


      • lib/mobx.umd.min.js



  • react

    • 也是基于 rollup,但太复杂,没时间看。。

方案

https://github.com/umijs/umi/issues/1550#issuecomment-449780074

2018 年最后一刻,提交了一版。剩下的 2019优化下 😂

https://github.com/umijs/umi-plugin-library/pull/new/refactor/use_monorepo_manage_project

已可用,后续改进在 https://github.com/umijs/umi-plugin-library/issues 跟进。

mark

开发的组件变多之后,性能上很卡,很吃内存

继续学习。

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zemzheng picture zemzheng  ·  3Comments

ironyfive picture ironyfive  ·  3Comments

afc163 picture afc163  ·  3Comments

Artoria-0x04 picture Artoria-0x04  ·  3Comments

y2891663091 picture y2891663091  ·  4Comments