Optimizing Micro‑Frontend Applications with Dependency Sharing and CDN Externalization
This article explains how to reduce bundle size and improve load speed of large micro‑frontend projects by sharing common dependencies through CDN externalization, using tools such as qiankun, vite‑plugin‑cdn‑import, and Rollup plugins for HTML generation.
Introduction
As micro‑frontend architecture gains popularity, projects often split a front‑end application into many independent sub‑applications, each with its own node_modules bundle. In a company using the qiankun framework with a Vue 3 host app, over 400 sub‑apps lead to duplicated third‑party code, hurting performance.
Optimization Strategies
Common code‑level optimizations such as lazy loading and static asset compression are well known; this article focuses on two packaging‑level techniques: gzip compression and dependency sharing . The latter is explored in depth.
Initial Load Files of a Typical Project
A vanilla project without special bundling configuration typically loads the following files on first visit:
File
Purpose
Size
Load Time
0.js
Route page content
(prefetch cache)
60 ms
app.js
Main non‑route code
893 kB
12 ms
chunk‑vendors.js
Third‑party dependencies from node_modules 37.9 MB
427 ms
The bulk of the payload comes from chunk‑vendors.js , which contains duplicated third‑party libraries across sub‑apps.
Dependency Sharing Concept
When many sub‑apps each bundle their own node_modules, the same libraries (e.g., Vue core, state management, linting tools) are downloaded repeatedly. By externalizing these common libraries and loading them once via a CDN, all sub‑apps can reuse the cached copies, dramatically reducing download size and improving perceived performance.
How to Implement Dependency Sharing
Externalizing Dependencies via CDN
The simplest approach is to mark frequently used libraries as external dependencies and load them from a CDN instead of bundling them into each sub‑app.
Using vite-plugin-cdn-import
Install the plugin: npm install vite-plugin-cdn-import --save-dev Then add it to vite.config.js:
import { defineConfig } from 'vite';
import cdnImport from 'vite-plugin-cdn-import';
export default defineConfig({
plugins: [
cdnImport({
imports: [
{
// library name, e.g., 'react'
libraryName: 'react',
// CDN URL for the library
url: 'https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js',
prod: true, // use CDN in production
dev: false // do not use CDN in development
},
// add more libraries as needed
]
})
]
});When building or running the dev server, the listed dependencies are injected as <script> tags pointing to the CDN URLs.
In the configuration above, libraryName specifies the package to replace, and url is the CDN location. The prod and dev flags control usage in different environments.
Note: configuring each dependency manually can be tedious for large projects.
Using rollup-plugin-html and rollup-plugin-node-resolve
Another method is to generate an HTML file that includes all bundled node_modules as separate <script> tags.
Install the required plugins:
npm install --save-dev rollup-plugin-html rollup-plugin-node-resolve rollup-plugin-terserCreate a custom Rollup plugin to emit an index.html with script tags:
import resolve from '@rollup/plugin-node-resolve';
import html from '@rollup/plugin-html';
import { terser } from 'rollup-plugin-terser';
import { defineConfig } from 'rollup';
const generateHTML = () => {
return {
name: 'generate-html',
generateBundle(options, bundle) {
const scriptTags = Object.keys(bundle)
.filter(fileName => fileName.endsWith('.js'))
.map(fileName => `<script src="${fileName}"></script>`)
.join('
');
const htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My App</title>
</head>
<body>
${scriptTags}
</body>
</html>`;
this.emitFile({
type: 'asset',
fileName: 'index.html',
source: htmlContent
});
}
};
};
export default defineConfig({
input: 'src/main.js',
output: {
dir: 'dist',
format: 'esm',
entryFileNames: 'static/js/[name]-[hash].js',
chunkFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/assets/[name]-[hash][extname]'
},
plugins: [
resolve(),
terser(),
generateHTML()
]
});The generateHTML plugin scans the bundle for JavaScript files and injects them as script tags, producing an HTML entry point that loads shared dependencies from the CDN when configured accordingly.
The generateBundle hook iterates over bundle assets, creates <script> tags for each .js file, and writes an index.html asset.
Conclusion
By externalizing common libraries and sharing them across micro‑frontend sub‑applications—either via vite-plugin-cdn-import or custom Rollup HTML generation—teams can dramatically shrink bundle sizes, reduce duplicate network requests, and achieve faster load times for both host and child apps.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.
