我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。

本文作者:修能

朝闻道,夕死可矣

何为 Molecule?

轻量级的 Web IDE UI 框架——Molecule

我们开源了一个轻量的 Web IDE UI 框架

Molecule实现数栈至简前端开发新体验

前言

构建通常指的是把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码。在前端发展的过程中,源代码的模块体系在不断的更新,最终产物也在不断的更新。而随之也使得构建工具也在不断更新换代。

而目前来看,基于前端的细化领域下,针对不同领域下的构建工具也日新月异。来看看 Molecule 该如何选择构建工具呢?

Molecule 的需求

首先,我们需要分析 Molecule 对构建工具的需求有什么?

老版本的问题

  1. 本地开发和 build 的构建工具不同,不得不增加 web 命令来执行一个预览的任务,确保 build 后的产物没问题。
  2. 慢,由于使用 tsc 作为编译,所以编译较慢。
  3. 部分变量无法复用,导致重复定义。

代码编译

由于 Molecule 的代码是用 ESM 的模块书写,且 Molecule 面向的是 Web 应用。通常来说面向 Web 应用的依赖库是需要提供 ESM 的代码实现 tree shaking 的作用的。

所以我们这里需要把 ESM 书写的 Molecule 代码通过构建工具编译成 ESM。

思考:为什么要把 ESM 代码编译成 ESM?

  1. 将 TypeScript 编译成 JavaScript
  2. 将高级语法编译成低级语法

除此之外,由于我们考虑到 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();

做两件事

  1. 别名重定位
  2. 将文件中的样式文件改为 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(';', ',');
}
})
);
}
}

做两件事

  1. :export干掉
  2. :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

Molecule 在构建工具中的选择的更多相关文章

  1. [翻译]在gulp构建工具中使用PostCSS

    前言 PostCSS已经在一段时间内迅速普及,如果你还不知道PostCSS或还没有使用它,我建议你看一下之前的一篇介绍文章<PostCSS简介>,其中介绍了使用PostCSS的基本方法,包 ...

  2. 前端构建工具-fis3使用入门

    FIS3 是面向前端的工程构建工具.解决前端工程中性能优化.资源加载(异步.同步.按需.预加载.依赖管理.合并.内嵌).模块化开发.自动化工具.开发规范.代码部署等问题. 官网地址是: https:/ ...

  3. Java构建工具:如何用Maven,Gradle和Ant+Ivy进行依赖管理

    原文来自:https://zeroturnaround.com/rebellabs/java-build-tools-how-dependency-management-works-with-mave ...

  4. 前端自动化构建工具--Gulp&&Webpack

    前端构建工具的作用可以认为是对源项目文件或资源进行文件级处理,将文件或资源处理成需要的最佳输出结构和形式. 在处理过程中,我们可以对文件进行模块化引入.依赖分析.资源合并.压缩优化.文件嵌入.路径替换 ...

  5. Build Tool(构建工具)

    what: 构建工具能够帮助你创建一个可重复的.可靠的.携带的且不需要手动干预的构建.构建工具是一个可编程的工具,它能够让你以可执行和有序的任务来表达自动化需求.假设你想要编译源代码,将生成的clas ...

  6. 取代 Maven?这款项目构建工具性能提升 300%

    在 GitHub 上闲逛的时候,发现了一个新的项目:maven-mvnd,持续霸占 GitHub trending 榜单好几天了. maven-mvnd,可以读作 Maven Daemon,译作 Ma ...

  7. Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

    Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用 Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.cs ...

  8. Java 中三大构建工具:Ant、Maven和Gradle

    Java世界中主要有三大构建工具:Ant.Maven和Gradle 目前:Ant已经销声匿迹.Maven也没落了,而Gradle的发展则如日中天. Maven的主要功能主要分为5点,分别是依赖管理系统 ...

  9. ASP.NET5之客户端开发:Grunt和Gulp构建工具在Visual Studio 2015中的高效的应用

    Grunt和Gulp是Javascript世界里的用来做自动压缩.Typescript编译.代码质量lint工具.css预处理器的构建工具,它帮助开发者处理客户端开发中的一些烦操重复性的工作.Grun ...

  10. 如何选择JavaScript构建工具之Babel、Browserify、Webpack、Grunt以及Gulp

    当我们开始一个新的 JavaScript 项目时,我们需要考虑的第一件事就是搭建一个前端编译环境.但是在面对众多的 JavaScript 构建工具时,我们却无所适从,不知道究竟哪一个才是最适合我们的. ...

随机推荐

  1. 在行情一般的情况下,就说说23级应届生如何找java工作

    Java应届生找工作,不能单靠背面试题,更不能在简历中堆砌和找工作关系不大的校园实践经历,而是更要在面试中能证明自己的java相关商业项目经验.其实不少应届生Java求职者不是说没真实Java项目经验 ...

  2. 【原创】xenomai UDD介绍与UDD用户态驱动示例

    目录 xenomai UDD与用户态驱动示例 一.UDD介绍 二.UDD原理及框架 1. 内存映射 2. 中断处理 UDD与UIO的区别 3. linux UIO与xenomai UDD框架对比 3. ...

  3. GoFrame v2.5 版本发布,企业级 Golang 开发框架

    大家好啊,GoFrame 框架今天发布了 v2.5.0 正式版本啦! 本次版本主要是对已有功能组件以及开发工具上的改进工作.其中,开发工具新增了 gf gen ctrl 命令,以规范化定义.开发 AP ...

  4. C语言循环坑 -- continue的坑

    文章目录 前言 一.continue语法 1.continue的作用 2.语法 二.大坑项目 题目 分析 正确写法 三.进坑调试 第一种 第二种 总结 前言 在使用continue和break时,会出 ...

  5. 离线自动化部署CDH

    离线CDH集群自动化部署工具 离线CDH集群安装与部署的自动化脚本工具,简单支持「离线一键装机」. 脚本将对系统配置做出一定修改,使用前请务必确认当前服务器无其他人员.任务使用,以免造成不必要的麻烦, ...

  6. Qt+GDAL开发笔记(二):在windows系统msvc207x64编译GDAL库、搭建开发环境和基础Demo

    前言   上一篇使用mingw32版本的gdal,过程曲折,为更好的更方便搭建环境,在windows上msvc方式对于库比较友好.   大地坐标简介 概述   大地坐标(Geodetic coordi ...

  7. DXP TreeList 目录树

    DXP TreeList 目录树 1.需求背景 需要一个支持勾选,拖动节点,保存各节点顺序的目录树. 2.创建目录树 在treeList控件中添加两个colunm 用来显示绑定数据和显示值. 接下来对 ...

  8. 加密算法解析:MD5、DES和RAS的工作原理与特点

    一.MD5不可逆加密 1.1-理解MD5 MD5公开的算法,任何语言实现后其实都是一样的.通用的 不可逆加密:原文--加密--密文,密文无法解密出原文 1.2-MD5封装 using System.I ...

  9. [golang]使用tail追踪文件变更

    简介 借助 github.com/hpcloud/tail ,可以实时追踪文件变更,达到类似shell命令tail -f的效果. 示例代码 以下示例代码用于实时读取nginx的access.log日志 ...

  10. CentOS7更新OpenSSH

    前言 整个过程不要断开ssh链接,如有必要可使用telnet远程操作. 系统版本:centos 7.9 OpenSSL版本:1.0.2k -> 1.1.1q OpenSSH版本:7.4p1 -& ...