How SREWorks Scaled Its Frontend: Monorepo, Webpack & Remote Component Strategies
This article details how the open‑source SREWorks frontend evolved through a monorepo restructure, selective use of Webpack and Rollup, remote component loading, and build optimizations to achieve a more extensible, plug‑in‑friendly low‑code platform for cloud‑native operations.
Project Background
SREWorks is an open‑source cloud‑native intelligent operation platform for enterprise‑level complex services. Its frontend, built with React and Ant Design, provides a serverless, configuration‑driven low‑code solution where users can design pages via visual interaction or JSON, configuring component properties, nesting, layout, data binding, and dynamic logic.
Evolution Analysis
Facing a nearly 100k‑line codebase, limited documentation, and divergent update frequencies across the designer, model, and component layers, the team identified several challenges: lack of runtime remote component loading, difficulty splitting a large shared framework, and the need for finer‑grained package updates.
Monorepo Architecture Evolution
Adopting a monorepo (single repository, multiple packages) simplifies module structure and dependency management, enables independent builds, and improves code reuse.
Using Lerna and Yarn Workspaces (v1.4), the project was split into the following npm packages:
@sreworks/app (main application)
@sreworks/components
@sreworks/widgets
@sreworks/framework
@sreworks/shared-utils
These packages are linked via the workspace, allowing real‑time synchronization of dependencies without publishing to npm.
Build Tool Selection: Webpack vs Rollup
The team evaluated Webpack and Rollup, summarizing their strengths and weaknesses:
Tool
Webpack
Rollup
Advantages
Hot Module Replacement (HMR)
Improved tree‑shaking in v5
Code splitting for better initial load
ESM output support
Smaller bundle size
Cleaner output without excess helper code
Native tree‑shaking
Simple plugin system
ESM output support
Disadvantages
Complex configuration and many internal utilities
No built‑in HMR; requires plugins for CommonJS
Consequently, Webpack 5 was chosen for the main app (required HMR) and Rollup for sub‑packages (smaller, simpler builds).
Smooth Migration Strategy
To avoid rebuilding the entire monorepo for each change, remote component loading was introduced. Components are packaged as UMD modules, uploaded to a CDN, and dynamically injected via script tags at runtime.
(function(){
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = url; // component URL
document.getElementById('targetDomId').appendChild(script);
})();
script.addEventListener('load',callback,false);Batch loading can be performed with an async helper:
const loadRemoteComp = async () => {
let remoteCompList = ["url_a","url_b","url_c",...];
try {
const pros = remoteCompList.map(item => loadSingleComp(item));
window['REMOTE_COMP_LIST'] = await Promise.all(pros);
} catch (error) {
console.log(error);
}
};
loadRemoteComp();SystemJS is used to handle browser compatibility, error handling, and module isolation.
Build Optimizations
Three major optimizations reduced the final bundle from 5.5 MB (gzip) to 1.6 MB:
Unified dependency versions across sub‑packages, shrinking size to 2.8 MB.
Externalized large libraries (React, React‑DOM, AntD) via externals and loaded them from CDN, with a fallback script for private cloud environments.
Adjusted critical component paths, cutting another 70 % of size and reducing build time from 74 s to 23 s.
const namespace = {
appRoot: path.resolve('src'),
appAssets: path.resolve('src/assets'),
// Reduce duplicate deps in sub‑packages
'@ant-design': path.resolve(process.cwd(),'node_modules','@ant-design'),
'js-yaml': path.resolve(process.cwd(),'node_modules','js-yaml'),
'ace-builds': path.resolve(process.cwd(),'node_modules','ace-builds'),
'brace': path.resolve(process.cwd(),'node_modules','brace'),
'lodash': path.resolve(process.cwd(),'node_modules','lodash')
};
...
resolve: {
alias: paths.namespace,
modules: ['node_modules'],
extensions: ['.json','.js','.jsx','.less','scss']
}, externals: {
// Exclude heavy deps from bundle
'react': 'React',
'react-dom': 'ReactDOM',
'antd': 'antd',
...
},Component Extensibility & Plug‑in
To support custom extensions, the frontend offers JSXRender for simple static components, but not full property or data binding. Remote component scaffolding (@sreworks/widget-cli) enables packaging React or Vue components as UMD modules, publishing them to CDN, and loading/removing them at runtime.
createVueInstance(targetElement, reactThisBinding) {
const { component, on, ...props } = reactThisBinding.props;
reactThisBinding.vueInstance = new Vue({
el: targetElement,
data: props,
render(createElement) {
return createElement(VUE_COMPONENT_NAME, { props: this.$data, on }, [wrapReactChildren(createElement, this.children)]);
},
components: {
[VUE_COMPONENT_NAME]: component,
'vuera-internal-react-wrapper': ReactWrapper
}
});
}This approach resolves both the need for React‑based extensions and the integration of legacy Vue components.
Evolution Summary
The monorepo refactor, selective build tool usage, remote component architecture, and systematic optimizations have resulted in a clearer dependency graph, lower entry barriers for contributors, finer‑grained updates, faster builds, and a path toward incremental TypeScript adoption.
Alibaba Cloud Big Data AI Platform
The Alibaba Cloud Big Data AI Platform builds on Alibaba’s leading cloud infrastructure, big‑data and AI engineering capabilities, scenario algorithms, and extensive industry experience to offer enterprises and developers a one‑stop, cloud‑native big‑data and AI capability suite. It boosts AI development efficiency, enables large‑scale AI deployment across industries, and drives business value.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
