We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
如果直接发布 .vue 或者 .jsx 文件,用户使用的时候需要跟着源码编译一遍,影响用户的开发以及发布的构建速度。但是不构建也有不构建的好处,看完下文关于构建的权衡取舍就明白了。
.vue
.jsx
core-js
core-js 有两个包,分别是 : core-js、core-js-pure。core-js 以全局的方式引入 polyfill,如:import "core-js/stable/set";;而 core-js-pure 引入 polyfill 时不会污染全局,如:import Set from "core-js-pure/stable/set";。
core-js-pure
polyfill
import "core-js/stable/set";
import Set from "core-js-pure/stable/set";
@babel/transform-runtime
假设我们有这段代码需要编译:
export const p = new Promise();
使用 @babel/preset-env 处理 core-js,配置如下:
@babel/preset-env
["@babel/preset-env", { useBuiltIns: "usage", corejs: 3 }]
编译结果:
import 'core-js/modules/es.object.to-string.js'; import 'core-js/modules/es.promise.js'; var p = new Promise(); export { p };
使用 @babel/transform-runtime 处理 core-js,配置如下:
["@babel/plugin-transform-runtime", { corejs: 3 }]
import _Promise from '@babel/runtime-corejs3/core-js-stable/promise'; var p = new _Promise(); export { p };
从上述两个编译结果可以看出 @babel/preset-env 处理 core-js 采用的是污染全局的方式,而 @babel/transform-runtime 采用的是 core-js-pure 不会污染全局变量,两者不能建议同时使用,可能引发不可预知的问题。其中还有一个很重要的区别是:@babel/transform-runtime 不认 @babel/preset-env 的 targets 配置,不管设置的浏览器版本有多高,都会引入 polyfill没,还是上面的代码,修改配置如下:
targets
{ presets: [["@babel/preset-env", { useBuiltIns: false, // corejs: 3 targets: { browsers: [ 'chrome >= 91' ] }, }]], plugins: [ ["@babel/plugin-transform-runtime", { corejs: 3 }] ] }
编译的结果还是会带 polyfill:
import _Promise from '@babel/runtime-corejs3/core-js-stable/promise'; const p = new _Promise(); export { p };
Babel
APP: 仅仅使用 @babel/transform-runtime 处理 helpers,对于 core-js,因为不清楚有哪些第三方依赖包需要并且没有被引入的 polyfill,有两种选择:1)不介意最终包的大小:直接配置 useBuiltIns: "entry",根据 targets 全量引入 polyfill;2)介意包的大小,不介意生产构建的速度,配置 useBuiltIns: "usage",对所有依赖包用 babel 过一遍(如果不对所有依赖包处理,有可能会漏掉依赖包中需要 polyfill),根据targets按需引入 polyfill。
helpers
useBuiltIns: "entry"
useBuiltIns: "usage"
babel
Library: 配置useBuiltIns: false,避免全局的 polyfill 对应用造成影响,使用 @babel/transform-runtime 处理 helpers。对于 polyfill 有两种选择:1)不处理,交给使用方自行处理。2)使用 @babel/transform-runtime 处理 core-js,因为不能指定targets 会使最终构建的包比较大。对于这个问题,Babel 官方有还在实验阶段的方案 babel-polyfill。
useBuiltIns: false
从 es6 2015年出道,现代浏览器在 2016-2017 年基本已支持:
es6
从 can i use 中也可以查到 es6 的支持度其实很高了:
can i use
vue3 从高调宣称不支持IE11,到迷之激进构建,tsconfig.json直接上 esnext,直呼:好家伙。(花了69块钱给尤大发个私信咨询,没得到回复)
vue3
esnext
vue3 版本的 element-plus 也是直接上 es6,如果要用 vue3,支持的浏览器其实也老不到哪去,太老跑不了 Proxy。
element-plus
Proxy
这时 Babel 就派不上大用场了,因为 Babel 的 targets 不能配置指定某个 es 版本,翻了下 github 的 issues,官方说:用户指定 targets 会是比较好的选择, 因为浏览器可能支持了大部分 es6 语法(不是全部)和部分 es7 语法,此时设置 targets 是更合理的。
es
es7
可选的方案: 1)大名鼎鼎的 esbuild,现在已经有部分应用在生产使用了,element-plus的组件有一种构建类型也是用 esbuild,但是截至目前(2021年6月20日)作者依然不建议直接在生产使用。
esbuild
2)小众一点点 swc,用 Rust 实现,主打也是快,但是有些语法不支持传送门,用的人也比较少。
swc
3) 使用更大名鼎鼎的 tsc,因为 ts 是 js 的超集,所以是可以用 ts 的编译器直接编译 js 的,真香。
tsc
ts
js
前面铺垫了这么多,大家因该知道怎么做的,直接进入 FAQ【逃】
用 webpack 或者 Rollup 将一个个的 .css .less .js .jsx .vue 编译成 .css .js。如非特殊需求,不建议自己封装 @vue/compiler-sfc,SFC 的写法太多了,template,render,setup,css var。一步小心可能会踩坑。
.css
.less
.js
@vue/compiler-sfc
template
render
setup
css var
业务组件库通常不太需要换肤等各种场景,但是需要避免避免全局样式污染。如果不是非常大的团队,交给应用构建其实也是没舍恩么问题的。要构建的尽量做到简单的按需加载,不需要使用 babel-plugin-import 啥的,使用插件实现 css 的反向注入,如:
babel-plugin-import
之前写了 Rollup 插件,有需要的话后续发布出来(挺简单的,自己实现一个也不难)。
我们构建的是 PC 端的 vue3 组件库,跟着尤大走,最终构建的目标版本是 es6,编译器用是 tsc,构建工具 Rollup。
Rollup
The text was updated successfully, but these errors were encountered:
将 esnext 编译到 es6,编译工具 esbuild、tsc、swc 都不会处理 js api,只编译语法,根据作者们的描述,polyfill 不属于编译的范畴,可以通过其他方式实现。所以"使用这些工具依旧得考虑 polyfill 的问题"。
Sorry, something went wrong.
顺带补几个点:
对于库的构建,目前没有特别优雅的方式处理 polyfill,要么存在全局污染问题,要么接受比较大的构建体积 如果所有的库都处理 polyfill,而技术体系又不一样,不能通过 tree-shaking 过滤,那么将会导致应用的构建体积非常大 库的使用者,比开发者更清楚应该兼容什么环境,用什么 polyfill Advice for library authors who use polyfills? w3ctag/polyfills#6 这里有一些大佬的讨论
No branches or pull requests
预备知识1:为什么要构建?
如果直接发布
.vue
或者.jsx
文件,用户使用的时候需要跟着源码编译一遍,影响用户的开发以及发布的构建速度。但是不构建也有不构建的好处,看完下文关于构建的权衡取舍就明白了。预备知识2:
core-js
有哪几种用法?core-js
有两个包,分别是 :core-js
、core-js-pure
。core-js
以全局的方式引入polyfill
,如:import "core-js/stable/set";
;而core-js-pure
引入polyfill
时不会污染全局,如:import Set from "core-js-pure/stable/set";
。预备知识3:和
@babel/transform-runtime
都可以处理core-js
,有什么区别?假设我们有这段代码需要编译:
使用
@babel/preset-env
处理core-js
,配置如下:编译结果:
使用
@babel/transform-runtime
处理core-js
,配置如下:编译结果:
从上述两个编译结果可以看出
@babel/preset-env
处理core-js
采用的是污染全局的方式,而@babel/transform-runtime
采用的是core-js-pure
不会污染全局变量,两者不能建议同时使用,可能引发不可预知的问题。其中还有一个很重要的区别是:@babel/transform-runtime
不认@babel/preset-env
的targets
配置,不管设置的浏览器版本有多高,都会引入polyfill
没,还是上面的代码,修改配置如下:编译的结果还是会带
polyfill
:预备知识4:如果使用
Babel
处理 js,库和应用的构建分别推荐什么样的配置?APP: 仅仅使用
@babel/transform-runtime
处理helpers
,对于core-js
,因为不清楚有哪些第三方依赖包需要并且没有被引入的polyfill
,有两种选择:1)不介意最终包的大小:直接配置useBuiltIns: "entry"
,根据targets
全量引入polyfill
;2)介意包的大小,不介意生产构建的速度,配置useBuiltIns: "usage"
,对所有依赖包用babel
过一遍(如果不对所有依赖包处理,有可能会漏掉依赖包中需要polyfill
),根据targets
按需引入polyfill
。Library: 配置
useBuiltIns: false
,避免全局的polyfill
对应用造成影响,使用@babel/transform-runtime
处理helpers
。对于polyfill
有两种选择:1)不处理,交给使用方自行处理。2)使用@babel/transform-runtime
处理core-js
,因为不能指定targets
会使最终构建的包比较大。对于这个问题,Babel
官方有还在实验阶段的方案 babel-polyfill。预备知识5:都 2021 了,是否能重新思考构建?我们是否还有必要把代码编译到 es5 ?
从
es6
2015年出道,现代浏览器在 2016-2017 年基本已支持:从
can i use
中也可以查到 es6 的支持度其实很高了:vue3
从高调宣称不支持IE11,到迷之激进构建,tsconfig.json直接上esnext
,直呼:好家伙。(花了69块钱给尤大发个私信咨询,没得到回复)vue3
版本的element-plus
也是直接上es6
,如果要用vue3
,支持的浏览器其实也老不到哪去,太老跑不了Proxy
。预备知识6:如何将 js 代码编译到
es6
?这时
Babel
就派不上大用场了,因为Babel
的targets
不能配置指定某个es
版本,翻了下 github 的 issues,官方说:用户指定targets
会是比较好的选择, 因为浏览器可能支持了大部分es6
语法(不是全部)和部分es7
语法,此时设置targets
是更合理的。可选的方案:
1)大名鼎鼎的
esbuild
,现在已经有部分应用在生产使用了,element-plus
的组件有一种构建类型也是用esbuild
,但是截至目前(2021年6月20日)作者依然不建议直接在生产使用。2)小众一点点
swc
,用 Rust 实现,主打也是快,但是有些语法不支持传送门,用的人也比较少。3) 使用更大名鼎鼎的
tsc
,因为ts
是js
的超集,所以是可以用ts
的编译器直接编译js
的,真香。�开始组件库的构建
前面铺垫了这么多,大家因该知道怎么做的,直接进入 FAQ【逃】
FAQ1: 如何实现组件库按需记载?
用 webpack 或者 Rollup 将一个个的
.css
.less
.js
.jsx
.vue
编译成.css
.js
。如非特殊需求,不建议自己封装@vue/compiler-sfc
,SFC 的写法太多了,template
,render
,setup
,css var
。一步小心可能会踩坑。FAQ2: 业务组件库构建需要特别注意什么?
业务组件库通常不太需要换肤等各种场景,但是需要避免避免全局样式污染。如果不是非常大的团队,交给应用构建其实也是没舍恩么问题的。要构建的尽量做到简单的按需加载,不需要使用
babel-plugin-import
啥的,使用插件实现 css 的反向注入,如:之前写了 Rollup 插件,有需要的话后续发布出来(挺简单的,自己实现一个也不难)。
FAQ3:你们使用的什么构建方案?
我们构建的是 PC 端的
vue3
组件库,跟着尤大走,最终构建的目标版本是es6
,编译器用是tsc
,构建工具Rollup
。The text was updated successfully, but these errors were encountered: