Molecule 在构建工具中的选择
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。
本文作者:修能
朝闻道,夕死可矣
何为 Molecule?
轻量级的 Web IDE UI 框架——Molecule
我们开源了一个轻量的 Web IDE UI 框架
Molecule实现数栈至简前端开发新体验
前言
构建通常指的是把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码。在前端发展的过程中,源代码的模块体系在不断的更新,最终产物也在不断的更新。而随之也使得构建工具也在不断更新换代。
而目前来看,基于前端的细化领域下,针对不同领域下的构建工具也日新月异。来看看 Molecule 该如何选择构建工具呢?
Molecule 的需求
首先,我们需要分析 Molecule 对构建工具的需求有什么?
老版本的问题
- 本地开发和 build 的构建工具不同,不得不增加 web 命令来执行一个预览的任务,确保 build 后的产物没问题。
- 慢,由于使用 tsc 作为编译,所以编译较慢。
- 部分变量无法复用,导致重复定义。
代码编译
由于 Molecule 的代码是用 ESM 的模块书写,且 Molecule 面向的是 Web 应用。通常来说面向 Web 应用的依赖库是需要提供 ESM 的代码实现 tree shaking 的作用的。
所以我们这里需要把 ESM 书写的 Molecule 代码通过构建工具编译成 ESM。
思考:为什么要把 ESM 代码编译成 ESM?
- 将 TypeScript 编译成 JavaScript
- 将高级语法编译成低级语法
除此之外,由于我们考虑到 Node.js 后续发展以 Pure ESM 为主,且 Molecule 针对 CommonJS 的场景较少,故我们不考虑输出 CommonJS 的产物。
类型
需要支持输出类型。
样式
Molecule 中使用 BEM 作为类名规范,通常情况下使得需要在 Sass 中和 JavaScript 中都定义相同变量名。而类 Sass-in-JS 使得我们可以从 Sass 中导出变量名,在 JS 文件中使用。
这就使得构建工具不仅要支持 Sass 的编译,同时还需要支持插件,允许我们做 Sass-in-JS 的需求。
其他
其他相关文件,例如 JSON,PNG 等文件需要支持拷贝至相关指定目录。
调研构建工具
Webpack
Webpack 是目前构建工具中的老大哥了,作为顶级老牌构建工具,几乎所有场景都能适用。
缺点也仅仅是冗余代码较多,配置项太多,体积较大等。
Rollup
作为面向 JS 类库而出现的构建工具。其和 Webpack 相比,在打包后产生的冗余代码少,体积较小,功能专注。缺点仅仅是不支持 HMR。
Vite
直接排除
Parcel
Parcel 目前看作是面向 Web 应用的零配置,高速度的 Webpack。其有一个致命的弱点是,自定义插件支持不如 Webpack。这会让我们无法实现 Sass-in-JS。
2.0 可能有所改善,我不清楚。不予评价
swc
swc 在某种程度上,是 babel 和 tsc 的竞品,属于比较底层的构建工具。和 esbuild 同类型,只是 esbuild 基于 Go,swc 基于 Rust。
esbuild
extremely fast JavaScript Compiler
babel
很好,就是慢
tsc
很好,就是更慢。有一个优点,只有 tsc 能支持输出类型。
方案实施
由于大多数的构建工具都是 bundler,并不符合 Molecule 的定位。故采取的方案是 esbuild + Sass + tsc 的方案。
esbuild 取其作为 Compiler 的部分,Sass 取其编译 SCSS 文件的部分,tsc 负责编译出类型文件。
tsx 相关文件输出
transformCtx = await esbuild.context({
entryPoints,
bundle: false,
format: 'esm',
outdir: dist,
jsx: 'automatic',
plugins: [
{
name: 'alias',
setup(build) {
build.onLoad({ filter: /.*/ }, async (args) => {
const source = await fs.promises.readFile(args.path, 'utf8');
const contents = sassLoader(alias(source, args.path));
return {
contents,
loader: args.path.endsWith('.tsx') ? 'tsx' : 'ts',
};
});
},
},
],
});
await transformCtx.watch();
做两件事
- 别名重定位
- 将文件中的样式文件改为 css
样式文件输出
/**
*
* @param {string} entry
*/
async function _transform(entry) {
const res = await sass.compileAsync(entry);
const regex = /^:export {(\n|.)+}$/m;
const target = entry.replace(/src\//, 'esm/').replace(/.scss/, '.css');
const dirname = path.dirname(target);
if (!fs.existsSync(dirname)) {
fs.mkdirSync(dirname, { recursive: true });
}
const css = res.css.replace(regex, '');
fs.writeFileSync(target, css);
if (regex.test(res.css)) {
const exportModules = res.css.match(regex)[0];
fs.writeFileSync(
path.join(dirname, styleVariablesFileName),
exportModules
.replace(':export', 'export default')
.replace(/: .*;/gm, (substring) => {
const stringLiteral = /(?<="|')\S+(?="|')/g;
if (!stringLiteral.test(substring)) {
const startIdx = substring.indexOf(':');
const endIdx = substring.indexOf(';');
return `:"${substring.substring(startIdx + 1, endIdx).trim()}",`;
} else {
return substring.replace(';', ',');
}
})
);
}
}
做两件事
- 把
:export干掉 - 把
:export的内容放到当前目录下的style__variables.js的目录中
类型文件输出
类型文件异步输出,防止阻塞
async function transformTyping() {
typingCtx = spawn('tsc && (concurrently "tsc -w" "tsc-alias -w")', {
stdio: 'inherit',
shell: true,
});
}
其他文件输出
/**
*
* @param {string} filePath
*/
function _copyFile(filePath) {
const dest = filePath.replace(/src\//, 'esm/');
const dirname = path.dirname(dest);
if (!fs.existsSync(dirname)) {
fs.mkdirSync(dirname, { recursive: true });
}
fs.createReadStream(filePath, 'utf-8').pipe(fs.createWriteStream(dest));
}
遗留问题
- 增量编译的问题
- 代码压缩
欢迎大家就以上问题留言讨论!
最后
欢迎关注【袋鼠云数栈UED团队】~
袋鼠云数栈UED团队持续为广大开发者分享技术成果,相继参与开源了欢迎star
- 大数据分布式任务调度系统——Taier
- 轻量级的 Web IDE UI 框架——Molecule
- 针对大数据领域的 SQL Parser 项目——dt-sql-parser
- 袋鼠云数栈前端团队代码评审工程实践文档——code-review-practices
- 一个速度更快、配置更灵活、使用更简单的模块打包器——ko
Molecule 在构建工具中的选择的更多相关文章
- [翻译]在gulp构建工具中使用PostCSS
前言 PostCSS已经在一段时间内迅速普及,如果你还不知道PostCSS或还没有使用它,我建议你看一下之前的一篇介绍文章<PostCSS简介>,其中介绍了使用PostCSS的基本方法,包 ...
- 前端构建工具-fis3使用入门
FIS3 是面向前端的工程构建工具.解决前端工程中性能优化.资源加载(异步.同步.按需.预加载.依赖管理.合并.内嵌).模块化开发.自动化工具.开发规范.代码部署等问题. 官网地址是: https:/ ...
- Java构建工具:如何用Maven,Gradle和Ant+Ivy进行依赖管理
原文来自:https://zeroturnaround.com/rebellabs/java-build-tools-how-dependency-management-works-with-mave ...
- 前端自动化构建工具--Gulp&&Webpack
前端构建工具的作用可以认为是对源项目文件或资源进行文件级处理,将文件或资源处理成需要的最佳输出结构和形式. 在处理过程中,我们可以对文件进行模块化引入.依赖分析.资源合并.压缩优化.文件嵌入.路径替换 ...
- Build Tool(构建工具)
what: 构建工具能够帮助你创建一个可重复的.可靠的.携带的且不需要手动干预的构建.构建工具是一个可编程的工具,它能够让你以可执行和有序的任务来表达自动化需求.假设你想要编译源代码,将生成的clas ...
- 取代 Maven?这款项目构建工具性能提升 300%
在 GitHub 上闲逛的时候,发现了一个新的项目:maven-mvnd,持续霸占 GitHub trending 榜单好几天了. maven-mvnd,可以读作 Maven Daemon,译作 Ma ...
- Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用
Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.cs ...
- Java 中三大构建工具:Ant、Maven和Gradle
Java世界中主要有三大构建工具:Ant.Maven和Gradle 目前:Ant已经销声匿迹.Maven也没落了,而Gradle的发展则如日中天. Maven的主要功能主要分为5点,分别是依赖管理系统 ...
- ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用
Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grun ...
- 如何选择JavaScript构建工具之Babel、Browserify、Webpack、Grunt以及Gulp
当我们开始一个新的 JavaScript 项目时,我们需要考虑的第一件事就是搭建一个前端编译环境.但是在面对众多的 JavaScript 构建工具时,我们却无所适从,不知道究竟哪一个才是最适合我们的. ...
随机推荐
- #Powerbi 10分钟,理解 Rankx 排名函数
一:本文思维导图及示例数据图 1.1思维导图 1.2 示例数据图 二:度量值示例 2.1 函数简介 RANKX 首先为的每一行计值表达式,将结果临时存储为一个值列表.然后在当前筛选上下文中计值,将得 ...
- Node版本更新及切换
Node版本升级 # 清除npm缓存 npm cache clean -f # n模块是专门用来管理nodejs的版本,安装n模块 npm install -g n 1.Windows 由于n命令是在 ...
- snmptt解析中文trap消息
项目中使用了中国电信系统集成公司的虚拟化平台,为通过zabbix监控,接收HyperCenter发送的告警,需要将trap消息中的汉语编码转译.网络上snmptt资料不多,官网文档也不甚友好,通过参考 ...
- 关于微信小程序原生组件与uniApp混合开发过程遇到的问题与解决方式
前言: 在实际开发过程中,尤其是小程序的开发,我们常常会遇到一些在文档中解决不了的问题,在这里,我就浅谈一下我遇到的一些问题 1.小程序的构建框架是uni-app,却突然被要求用原生的微信小程序代码来 ...
- vivo 场景下的 H5无障碍适配实践
作者:vivo 互联网前端团队- Zhang Li.Dai Wenkuan 随着信息无障碍的建设越来越受重视,开发人员在无障碍适配中也遇到了越来越多的挑战.本文是笔者在vivo开发H5项目做无障碍适配 ...
- 【LaTeX】环境配置以及中文支持
目录 网页环境 Overleaf 本地环境 TeX Live TeXstudio VSCode 安装 LaTeX Workshop 扩展 编译链配置 正向同步 反向同步 其他可选配置 中文支持 XeL ...
- Cookies 完全指南
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:佳岚 前言 Cookie实际上是一小段的文本信息,它产生的 ...
- cpu分布式训练论文阅读
Large Scale Distributed Deep Networks Downpour SGD: 模型的副本采用异步方式从参数服务器(Parameter Server)中获取参数w和上传Δw到参 ...
- SQL注入简介
SQL注入(SQL Injection)是一种计算机安全漏洞,它允许攻击者通过操纵应用程序的输入来执行恶意的SQL查询,从而访问.修改或删除数据库中的数据.这种攻击通常发生在应用程序未正确验证.过滤或 ...
- python基础:集合(set)字典(direction)介绍
三.字典(dict) 1.字典的创建赋值创建字典In [2]: d = {1,True,"hello"} In [3]: type(d)Out[3]: set #字典由key和va ...