esbuild v0.18.14 已经发布了。esbuild 是一个Go 编写的 JavaScript 打包和压缩工具,支持 TypeScript,性能超强:
此版本引入了两个新的加载器,名为 global-css
和 local-css
,以及两个新的伪类选择器 :local()
和 :global()
。这是流行的CSS模块方法的部分实现,用于避免在CSS中无意间的名称冲突。因为社区中的其他人已经开始使用“CSS模块”来指代完全不同的东西,所以些功能不再这么称呼。
.className
和 #idName
的标识符在 global-css
加载器中是全局的,在 local-css
加载器中是局部的。全局标识符在所有文件中都是相同的(这就是CSS通常的工作方式),但是在不同的文件中,局部标识符是不同的。如果两个单独的CSS文件使用相同的局部标识符 .button
,esbuild会自动重命名其中一个,以防止它们发生冲突。这与esbuild如何自动重命名在不同JS文件中具有相同名称的JS局部变量以避免名称冲突的方式类似。
只有在使用esbuild的打包器来打包导入CSS文件的JS文件时,使用 local CSS 名称与esbuild才有意义。这么做的话,esbuild会为CSS文件中的每个本地名称生成一个export。JS代码可以导入这些名称,并在构建HTML DOM时使用它们。例如:
// app.js import { outerShell } from './app.css' const div = document.createElement('div') div.className = outerShell document.body.appendChild(div)
/* app.css */ .outerShell { position: absolute; inset: 0; }
当你将此与 esbuild app.js --bundle --loader:.css=local-css --outdir=out
捆绑在一起时,你现在会得到以下的东西(注意本地CSS名称 outerShell
已被重命名):
// out/app.js (() => { // app.css var outerShell = "app_outerShell"; // app.js var div = document.createElement("div"); div.className = outerShell; document.body.appendChild(div); })();
/* out/app.css */ .app_outerShell { position: absolute; inset: 0; }
仅当启用了打包功能时,使用此功能才有意义,原因有两个:一是因为你的代码需要 import
重命名的本地名称以便使用它们,二是因为esbuild需要能够在单次打包操作中处理所有包含本地名称的CSS文件,以便成功地重命名冲突的本地名称以避免冲突。
如果你在全局CSS文件中(使用 global-css
加载器),你可以使用 :local()
创建一个本地名称,如果你在本地CSS文件中(使用 local-css
加载器),你可以使用 :global()
创建一个全局名称。因此,选择 global-css
加载器与 local-css
加载器只是设定了标识符的默认行为,但你可以根据需要在每个案例中进行覆盖。例如:
:local(.button) { color: red; } :global(.button) { color: blue; }
使用esbuild处理这个CSS文件,无论是使用 global-css
或 local-css
加载器,结果都会类似于这样:
.stdin_button { color: red; } .button { color: blue; }
esbuild为本地CSS名称生成的名称是实现细节,不打算在任何地方硬编码。应该在JS或HTML中引用本地CSS名称的唯一方式是使用与esbuild捆绑的JS中的 import
语句,如上所示。例如,当 --minify
启用时,esbuild将使用一种不同的名称生成算法,该算法生成尽可能短的名称(类似于esbuild如何压缩JS中的本地标识符)。
如果给它们不同的文件扩展名,可以轻松地同时使用全局CSS文件和本地CSS文件。例如,你可以将 --loader:.css=global-css
和 --loader:.module.css=local-css
传递给esbuild,这样 .css
文件默认仍然使用全局名称,但 .module.css
文件默认使用本地名称。
css
加载器与 global-css
加载器不同。在 css
加载器中, :local
和 :global
注释不会被启用,而会原封不动地传递。这让你有可能使用esbuild处理包含这些注释的CSS,同时保留这些注释。这也意味着,目前本地CSS名称默认是被禁用的(因为 css
加载器目前是CSS文件的默认加载器)。在未来的版本中, :local
和 :global
的语法可能会默认启用。
esbuild的实现目前并未与其他类似工具中的模块化CSS的实现对齐功能。这只是一个初步发布,包含了一些基本行为的部分实现,以启动该过程。未来的版本可能会添加更多行为。特别是,这个版本并未实现:
composes
指令- 为未使用的本地CSS进行抖动优化
- 关键帧动画、网格线、
@container
、@counter-style
等的本地名称。
发布公告中表示,这是esbuild最受欢迎的问题!虽然这个版本仍然没有完全解决问题,但这是朝该方向迈出的重要的第一步。
此外,另一项变化是在CSS中解析 :is
, :has
, :not
,以及 :where。
随着这个版本的发布,esbuild现在将会解析这些伪类选择器的内容作为选择器列表。这意味着你现在会在这些选择器中得到无效选择器语法的语法警告。这也意味着esbuild的CSS嵌套转换的行为与以前略有不同,因为esbuild现在是在一个抽象语法树上操作,而不是一个令牌流。例如:
/* Original code */ div { :where(.foo&) { color: red; } } /* Old output (with --target=chrome90) */ :where(.foo:is(div)) { color: red; } /* New output (with --target=chrome90) */ :where(div.foo) { color: red; }
发布公告:https://github.com/evanw/esbuild/releases/tag/v0.18.14
还没有评论,来说两句吧...