- 前端
- UI组件
【免费下载链接】golden-layout
A multi window layout manager for webapps
导读
Golden-Layout 是一个面向 Web 应用的多窗口布局管理器(multiwindow layout manager),支持拖拽重排、原生弹窗(popout)、多框架集成与主题化。本文以仓库内的 构建工具链设计文档 为主线,结合当前仓库的实际构建脚本与 TypeScript 配置,系统讲解 Golden-Layout 如何把一套 TypeScript 源码同时产出 ES2015+ESM、ES5+ESM、ES5+UMD 三种形态的 JS 产物,以及 LESS/SCSS 双轨样式产物。读完本文,你将理解该项目的产物矩阵设计初衷、真实的编译/打包命令、样式自动前缀与主题分离的实现原理,并能据此自行构建、复用或二次开发这套工具链。
一、工具链的设计目标:一份源码,四种消费场景
TOOLCHAIN.md 开篇以 “Requirements” 列出了 Golden-Layout 对 JavaScript 代码产物的核心要求,它本质上是在回答一个问题:一个开源库应该以哪些形态交付,才能同时服务好不同技术栈的消费方?
针对 JS 代码,文档明确了五个约束:
- 使用与时俱进的 JavaScript 编写,并保留升级到 TypeScript 的能力(原文:Use up-to-date JavaScript, with an option to upgrade to typescript);
- 产出ES2015 + ESM版本,供基于 webpack 的现代打包型使用方消费;
- 产出ES5 + ESM版本,同样面向 webpack 使用方,但兼容更老的目标环境;
- 产出ES5 + UMD完整打包产物,供“裸用”(baremetal,即直接
<script>引入、不经过模块打包器)的场景消费; - 绝不打包任何第三方依赖(Donotbundle any dependencies)。
这五条约束勾勒出一个非常清晰的交付矩阵:同一份语义,针对“现代打包器 / 旧环境打包器 / 裸引入”三种消费者,分别提供语法与模块格式都不同的产物。第五条尤其关键——不内联依赖意味着库的体积可控、与使用方依赖树不冲突,这也是其package.json中声明"sideEffects": false以支持 tree-shaking 的配套设计。
值得一提的是,文档写作时该项目还是纯 JavaScript + Babel 的设想,而当前仓库已经完成了“升级到 TypeScript”的演进:package.json的main指向dist/cjs/index.js、module指向dist/esm/index.js、typings指向dist/types/index.d.ts,且files字段仅发布dist/**/*与src/**/*。也就是说,原文档中“有朝一日升级 TS”的规划已经落地。
针对样式,文档同样列出四点要求:
- 使用 CSS 预处理器(CSS preprocessor)以获得更好的可扩展性;
- 引入 autoprefixer 将样式编译到所有受支持浏览器;
- 将主题(themes)与基础样式(base style)分离,按需默认引入;
- 保留输出 Sass mixins 的能力(如 Angular Material 场景下的集成)。
这四个要求对应到当前仓库,分别由 LESS/SCSS 双轨源码、postcss + autoprefixer 处理管线、src/less/themes/与src/scss/themes/的主题目录、以及 样式构建脚本 中的原始 SCSS 拷贝机制来实现,详见下文第三、四节。
二、方案的演进:从 Babel 设想走向 ts-loader 现实
原文档的 “Idea” 一节给出了最初的工具链构想:
- 使用Babel完成 ESnext → 降级转译,配合 webpack/babel-loader;
- 一旦升级到 TS,就用ts-loader替换 babel-loader;
- 使用 less/sass-loader 转译样式;
- 按文末的目录结构产出。
当前仓库的落地情况与这一设想高度吻合,且“升级 TS”这一步已经完成——如今webpack 不再经手 Babel,而是直接使用 ts-loader,这正对应原文档预写的“replace babel-loader by ts-loader”路线。
可以从两个层面验证这一点:
1. JS 产物由 tsc 与 webpack 分工完成
package.json中的构建脚本清晰地划分了职责:
"build:module": "tsc -p tsconfig.module.json", "build:module:api": "tsc -p tsconfig.module.api.json", "build:module:full": "tsc -p tsconfig.module.full.json", "build:module:strip": "tsc -p tsconfig.module.strip.json", "build:cjs": "tsc -p tsconfig.cjs.json", "build:bundles": "webpack --config ./scripts/webpack.config.js"tsc -p tsconfig.module.json(tsconfig.module.json)以module: es2020、outDir: dist/esm产出ESM 模块,同时开启declaration与declarationMap,声明文件落入lib/;tsc -p tsconfig.cjs.json(tsconfig.cjs.json)以module: commonjs、outDir: dist/cjs产出CommonJS 版本;webpack --config ./scripts/webpack.config.js负责产出UMD 与 ESM 的完整打包产物(见下文)。
其中 tsconfig.base.json 统一约定了target: es2015、严格模式全家桶(strict、strictNullChecks、noImplicitAny、noImplicitThis、noImplicitOverride、alwaysStrict、noImplicitReturns、noFallthroughCasesInSwitch等),并开启sourceMap、装饰器支持与downlevelIteration,是所有子配置的公共底座。另外三个 module 变体(module.api关闭stripInternal、module.strip开启stripInternal、module.full)用于 API 提取与文档生成时的不同可见性需求——这正是配合api-extractor/api-documenter做公开 API 面管理的机制。
2. UMD / ESM 完整包由 webpack 配置生成
scripts/webpack.config.js 导出四份配置,全部以src/index.ts为入口:
const generateUmdConfig = (isDev) => ({ ...generateCommonConfig(isDev), ...generateTsLoaderBlock('tsconfig.module.json'), output: { filename: isDev ? './bundle/umd/golden-layout.js' : './bundle/umd/golden-layout.min.js', library: { name: 'goldenLayout', type: 'umd' }, } });- UMD 变体:
library.type: 'umd'且library.name: 'goldenLayout',产出可直接以<script>引入、挂载为全局goldenLayout的裸用版本,并同时生成golden-layout.js(开发版)与golden-layout.min.js(生产压缩版); - ESM 变体:
experiments.outputModule: true配合library.type: 'module',产出 ESM 完整包,兼顾“完整打包”与“可被打包器静态分析”两种诉求; - 开发模式下通过
SourceMapDevToolPlugin注入 sourcemap,生产模式关闭devtool并交给 webpack 默认压缩。
注意一个细节:原文档规划的是dist/umd/goldenlayout.min.js等路径,而当前 webpack 输出到bundle/umd与bundle/esm。这正体现了工具链文档的“指导性”而非“教条性”——目录名可以随工程演进调整,但产物矩阵(ES2015+ESM / ES5+ESM / ES5+UMD)被完整继承了下来。
三、样式构建管线:LESS 为主、SCSS 为辅的双轨制
原文档要求“CSS 预处理器 + autoprefixer + 主题分离 + 可选 Sass mixins”,当前仓库的实现是以 LESS 为基础样式源、自动派生 SCSS 的双轨机制,核心证据在 goldenlayout-base.less 的头部注释中:
Base styling is done in less. However it is converted to goldenlayout-base.scss so that themes can also be developed using SCSS. All changes to base style should be done in goldenlayout-base.less. Do NOT make changes directly in goldenlayout-base.scss.
翻译成工程规则就是:基础样式只允许改 LESS 源文件,SCSS 版本通过less2sass自动生成,SCSS 使用者不应直接修改生成物。对应的package.json脚本为:
"update:scss": "npx del-cli ./src/scss/goldenlayout-base.scss && npx copyfiles -f ./src/less/goldenlayout-base.less ./src/scss && npx less2sass ./src/scss/goldenlayout-base.less && npx del-cli ./src/scss/goldenlayout-base.less"这条脚本的流程是:清掉旧 SCSS → 把 LESS 拷贝进src/scss/→ 用less2sass转成 SCSS → 删除中间产生的 LESS。最终 src/scss/goldenlayout-base.scss 成为 SCSS 使用方的入口,而被 主题变量文件 以@use "../goldenlayout-base.scss";引入。
真正执行“LESS 渲染 + autoprefixer + 分发”的是一段独立 Node 脚本 scripts/css.js,它用原生less.render()把每个.less文件渲染为 CSS,再交给postcss([autoprefixer])处理:
const lessFile = fs.readFileSync(filePath, 'utf8'); const lessOutput = await less.render(lessFile); const prefixedOutput = await postcss([autoprefixer]).process(lessOutput.css, { from: filePath }); fs.writeFileSync(outputPath, prefixedOutput.css); fs.writeFileSync(lessRawOutputFile, lessFile); // 同时把原始 less 拷贝到 dist该脚本一次性完成四类任务:
- 渲染
src/less/goldenlayout-base.less为dist/css/goldenlayout-base.css,并保留原始 LESS; - 遍历
src/less/themes/下每个主题(dark / light / borderless-dark / translucent / soda),逐一渲染并拷贝; - 把
src/scss/goldenlayout-base.scss与src/scss/themes/下的主题 SCSS原样拷贝到dist/scss/——这正是原文档“保留输出 Sass mixins 能力”的落地:SCSS 使用方拿到的是可直接@use/@import的源码,而非被编译后的 CSS; - 将
src/img/下的按钮图标(popout、maximise、close、popin 等)拷贝到dist/img/。
主题与基础样式分离的结构在源码目录中一目了然:
src/less/ ├── goldenlayout-base.less # 基础样式(唯一权威源) └── themes/ ├── goldenlayout-dark-theme.less ├── goldenlayout-light-theme.less ├── goldenlayout-borderless-dark-theme.less ├── goldenlayout-translucent-theme.less └── goldenlayout-soda-theme.less基础样式只负责布局骨架(.lm_root、.lm_row、.lm_content、.lm_splitter、.lm_header、.lm_tab、.lm_dragProxy、.lm_dropTargetIndicator等结构类),主题层才负责配色。例如 SCSS 主题文件 _goldenlayout-var-theme.scss 展示了“SCSS 变量 + CSS 自定义属性”的现代主题化范式——所有颜色都用var(--color-layout-*, 默认值)声明,从而允许使用方在不改库源码的情况下,通过覆盖 CSS 变量实现运行时换肤:
$baseBkgdColor: var(--color-layout-base-bkgd, #000000); $focusedTabBkgdColor: var(--color-layout-focused-tab-bkgd, #354be3); $dropDownArrowForeColor: var(--color-layout-drop-down-arrow-fore, #ffffff);这样,基础样式(布局结构)、主题变量(配色体系)、CSS 变量覆盖(运行时定制)三者各司其职,恰好完整兑现了原文档“Separate themes from base style”“Keep the option to ship sass mixins”两条样式要求。
四、产物目录结构:设计蓝图与现状对照
原文档在文末给出了一幅理想化的目录蓝图:
- root - src (input code) - js - LayoutManager.js - less - base.less - theme-dark.less - theme-light.less - index.js - dist (output products) - css - goldenlayout.css - umd (completely bundled variant) - goldenlayout.min.js - goldenlayout.min.js.map - goldenlayout.js - module (ES5 code, ESM modules) - index.js - js - LayoutManager.js - es2015 (ES6 code, ESM modules) - index.js - js - LayoutManager.js对照当前仓库,这个蓝图在分类思想上被完整保留,在具体路径上有所演化:
| 蓝图角色 | 蓝图路径 | 当前仓库实际路径 | 说明 |
|---|---|---|---|
| 输入源码 | src/js/LayoutManager.js | src/ts/layout-manager.ts | 已从 JS 升级为 TS,且按功能拆分为config/、container/、controls/、items/、utils/等模块目录 |
| 样式输入 | src/less/base.less等 | src/less/goldenlayout-base.less+src/less/themes/ | 命名细化,主题独立成目录 |
| 入口 | src/index.js | src/index.ts | 公开 API 面由 src/index.ts 统一导出(GoldenLayout、LayoutManager、ComponentContainer、Header、Tab、EventEmitter等) |
| CSS 产物 | dist/css/goldenlayout.css | dist/css/goldenlayout-base.css+dist/css/themes/*.css | 与“主题分离”要求一致 |
| UMD 完整包 | dist/umd/* | bundle/umd/golden-layout.js/.min.js | webpack 输出到bundle/ |
| ES5+ESM | dist/module/* | dist/esm/*(tsc 产出,ES2020 模块 +target: es2015) | 由tsconfig.module.json生成 |
| ES2015+ESM | dist/es2015/* | 语义上并入dist/esm/(当前统一为target: es2015的 ES 模块) | 实际构建中未再拆分两个 ESM 版本 |
从实现事实看,当前仓库用tsc 产出模块化产物(dist/esm、dist/cjs)、用webpack 产出完整打包产物(bundle/umd、bundle/esm)的分工,精准还原了原文档“module = 零打包的 ESM 模块”与“umd = completely bundled variant”的定位差异。ES5 的兼容性由target: es2015+ 现代浏览器的browserslist(package.json中声明了 Chrome/Firefox/Edge/Safari/iOS 的最近版本与 Firefox ESR)共同保障,autoprefixer 则按同一份browserslist给 CSS 加厂商前缀。
五、端到端构建:一条命令产出全部产物
把上面的所有环节串起来,就是package.json中的总构建命令:
"build": "npm run clean && npm run build:cjs && npm run build:module:api && npx api-extractor run --local --verbose && npm run test:build && npm run build:styles"这条命令的流水线为:
npm run clean—— 清空dist/、lib/、test/dist/等历史产物(对应clean:dist、clean:lib、clean:test);npm run build:cjs—— tsc 产出 CommonJS 版本到dist/cjs;npm run build:module:api—— tsc 产出带完整内部 API 的 ESM 版本(stripInternal: false);npx api-extractor run --local --verbose—— 依据 api-extractor.json 从声明文件中提取并校验公开 API 面,生成temp/golden-layout.api.json与 等 报告文件;npm run test:build—— 编译测试代码(tsc -p test/tsconfig.json);npm run build:styles—— 执行 scripts/css.js,产出 CSS/主题并拷贝 SCSS 与图片。
而完整的 JS 产物(含 UMD / ESM 打包版)通过npm run build:ts && npm run build:bundles或按需单独执行npm run build:bundles生成。测试侧则由npm test(Karma + ChromeHeadless 单次运行)与npm run test:watch(持续监听)支撑,test/specs/ 下存放 drag、event-emitter、ground-item、empty-stack 等单元与交互测试,确保工具链产出的行为与源码语义一致。
对于希望直接消费该库的开发者,package.json的exports语义(main→ CJS、module→ ESM)让 webpack / Rollup 等打包器可以自动选择最优版本;需要裸引用的场景则使用bundle/umd/golden-layout.min.js并在全局拿到goldenLayout命名空间。
六、小结:一份文档背后的工程方法论
纵观 src/TOOLCHAIN.md 与当前仓库的实现,可以提炼出 Golden-Layout 工具链的三个核心原则:
- 以消费场景反推产物形态:在写第一行代码之前,先明确现代打包器、旧环境打包器、裸
<script>引入三类消费者分别需要什么语法与模块格式,再设计构建矩阵; - 编译链路允许技术演进:文档预演的 “Babel → ts-loader” 路线已被真实执行,说明工具链文档的价值在于锁定“目标与边界”(如不打包依赖、ESM/UMD 双形态、主题与基础样式分离),而非锁死具体工具名;
- 样式与 JS 采用同样的多形态策略:LESS 权威源 → CSS + SCSS 派生、主题独立成包、autoprefixer 统一兼容——既满足 LESS 生态又保留 SCSS mixins 能力,同时用 CSS 变量为运行时主题化留出接口。
这份文档是理解 Golden-Layout 交付体系的钥匙:它解释了为什么仓库里同时存在tsconfig.cjs.json、tsconfig.module.json及多个变体,为什么scripts/下既有 webpack 配置又有独立的 CSS 脚本,也解释了dist/与bundle/两类产物的由来。基于这套机制,你既可以一键复现整个构建流程,也可以按同样的“产物矩阵”方法论去设计自己的开源库工具链。
关键参考文件:构建工具链设计文档 src/TOOLCHAIN.md;总构建脚本与依赖清单 package.json;UMD/ESM 打包配置 scripts/webpack.config.js;样式编译与分发脚本 scripts/css.js;LESS 基础样式 src/less/goldenlayout-base.less;SCSS 主题变量范式 src/scss/themes/_goldenlayout-var-theme.scss;公共 TS 编译配置 tsconfig.base.json、tsconfig.module.json、tsconfig.cjs.json;公开 API 入口 src/index.ts。
- 前端
- UI组件
【免费下载链接】golden-layout
A multi window layout manager for webapps
相关推荐
Golden Layout构建与部署指南:从源码到生产环境的完整流程
Golden Layout构建与部署指南:从源码到生产环境的完整流程 Golden Layout是一个强大的JavaScript多窗口布局管理器,能够帮助开发者
前端UI组件tauri-build 构建时模块深度解析:Tauri 应用从 build.rs 到跨平台产物的构建管线
tauri build 构建时模块深度解析:Tauri 应用从 build.rs 到跨平台产物的构建管线 tauri build 是 Tauri 应用工程中的核
桌面应用跨平台移动开发ScriptCat MV3 构建流水线与 Manifest 打包深度解析:从 Rspack 到 Chrome / Firefox 双端产物
ScriptCat MV3 构建流水线与 Manifest 打包深度解析:从 Rspack 到 Chrome / Firefox 双端产物 ScriptCat(
前端开发者工具插件系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考