Dynamic and On-Demand Loading
Preloading Strategies
Intersection Observer-Based Preloading
// Implementing preloading for images/components
const preloadObserver = new IntersectionObserver (( entries ) => {
entries. forEach ( entry => {
if (entry.isIntersecting) {
const lazyComponent = entry.target;
import ( `./components/ ${ lazyComponent.dataset.component } ` )
. then ( module => {
const Component = module .default;
new Component (). mount (lazyComponent);
preloadObserver. unobserve (lazyComponent);
});
}
});
});
// Usage in HTML
< div data-component = " LazyComponent " class = " lazy-component " ></ div >
Route-Based Preloading
// Adding preloading logic in route configuration
const routes = [
{
path : ' /dashboard ' ,
component : () => import ( /* webpackPrefetch: true */ ' ./Dashboard ' ),
// Alternatively, use webpackPreload
// component: () => import(/* webpackPreload: true */ './Dashboard')
}
];
Comparison of Preloading Methods
Method Advantages Disadvantages Use Cases webpackPrefetchPreloads during browser idle time May waste bandwidth Large but infrequently used components webpackPreloadHigh-priority preloading May block critical resources Critical path resources Intersection Observer On-demand preloading Slightly complex implementation Resources in the visible viewport
Lazy Loading Implementation
Intersection Observer-Based Lazy Loading
function lazyLoadImages () {
const images = document. querySelectorAll ( ' img[data-src] ' );
const observer = new IntersectionObserver (( entries ) => {
entries. forEach ( entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer. unobserve (img);
}
});
});
images. forEach ( img => observer. observe (img));
}
Component Lazy Loading with Dynamic Imports
const LazyComponent = React. lazy (() => import ( ' ./LazyComponent ' ));
function App () {
return (
< div >
< h1 >My App</ h1 >
< React.Suspense fallback ={ < div >Loading...</ div > } >
< LazyComponent />
</ React.Suspense >
</ div >
);
}
Comparison of Lazy Loading Strategies
Strategy Advantages Disadvantages Use Cases Dynamic Import Code splitting friendly Requires React support React applications Intersection Observer Good performance Requires manual implementation General-purpose solution Intersection Observer + Dynamic Import Optimal performance Complex implementation Complex applications
Dynamic Import Syntax
Basic Dynamic Import
// Dynamically importing a module
import ( ' ./module.js ' )
. then ( module => {
// Use the module
module . doSomething ();
})
. catch ( err => {
// Handle errors
console. error ( ' Module loading failed ' , err);
});
Dynamic Import with Namespace
// Dynamically importing specific exports
import ( ' ./module.js ' ). then (({ default: mainExport , namedExport }) => {
// Use exports
});
Dynamic Import with React
const DynamicComponent = React. lazy (() => import ( ' ./DynamicComponent ' ));
function App () {
return (
< React.Suspense fallback ={ < div >Loading...</ div > } >
< DynamicComponent />
</ React.Suspense >
);
}
Dynamic Import with Error Boundaries
class ErrorBoundary extends React . Component {
state = { hasError : false };
static getDerivedStateFromError ( error ) {
return { hasError : true };
}
render () {
if ( this .state.hasError) {
return < div >Loading failed</ div >;
}
return this .props.children;
}
}
const DynamicComponent = React. lazy (() => import ( ' ./DynamicComponent ' ));
function App () {
return (
< ErrorBoundary >
< React.Suspense fallback ={ < div >Loading...</ div > } >
< DynamicComponent />
</ React.Suspense >
</ ErrorBoundary >
);
}
State Management Solutions
Tool Features Use Cases Disadvantages Redux Predictable, rich middleware Large, complex applications Complex configuration MobX Simple, reactive Small to medium applications Debugging challenges Zustand Lightweight, simple Small to medium applications Limited features Context API Native support Simple state sharing Performance issues Recoil Atomic state React ecosystem Emerging tool
State Sharing Strategies
Simple Sharing with Context API
// Create Context
const AppContext = React. createContext ();
// Provide Context
function AppProvider ({ children }) {
const [state, setState] = React. useState ({});
return (
< AppContext.Provider value ={ { state, setState } } >
{ children }
</ AppContext.Provider >
);
}
// Use Context
function Component () {
const { state, setState } = React. useContext (AppContext);
// ...
}
Cross-Application Sharing with Redux
// Configure Redux store in main application
const store = createStore (rootReducer);
// Sub-application accessing the store
function ChildApp () {
const dispatch = useDispatch ();
const state = useSelector ( state => state);
// ...
}
// Pass store to sub-application during rendering
< Provider store ={ store } >
< ChildApp />
</ Provider >
Comparison of State Sharing Methods
Method Advantages Disadvantages Use Cases Context API Native support, simple Performance issues Small applications Redux Powerful features Complex configuration Large applications Zustand Simple and easy to use Limited features Small to medium applications Custom Events Flexible Hard to maintain Simple communication
State Isolation Solutions
Module Federation-Based State Isolation
// Main application configuration
new ModuleFederationPlugin ({
name : ' host ' ,
shared : {
react : { singleton : true },
' react-dom ' : { singleton : true },
' @app/store ' : { singleton : false } // Do not share store
}
});
// Sub-application configuration
new ModuleFederationPlugin ({
name : ' remote ' ,
filename : ' remoteEntry.js ' ,
exposes : {
' ./store ' : ' ./src/store ' // Expose own store
},
shared : {
react : { singleton : true },
' react-dom ' : { singleton : true },
' @app/store ' : { singleton : false } // Do not share store
}
});
Scope-Based State Isolation
// Use Symbol as state identifier
const STATE_SYMBOL = Symbol ( ' appState ' );
function createState () {
const state = {};
return new Proxy (state, {
get ( target , prop ) {
if (prop === STATE_SYMBOL) return state;
return target[prop];
}
});
}
// Each application has its own state instance
const appState1 = createState ();
const appState2 = createState ();
Comparison of State Isolation Methods
Method Advantages Disadvantages Use Cases Module Federation Official support Complex configuration Micro frontend architectures Scope Isolation Simple and direct Requires manual management Small applications Web Worker True isolation High communication cost Computation-intensive tasks
Styling Solutions
CSS Modules
Basic Usage
// Component styles
import styles from ' ./Button.module.css ' ;
function Button () {
return < button className ={ styles.button } >Click me</ button >;
}
Global Styles
/* Use :global in CSS Module file */
: global (.global - class) {
color: red;
}
Dynamic Class Names
function Button ({ primary }) {
return (
< button
className ={ ` ${ styles.button } ${ primary ? styles.primary : '' } ` }
>
Click me
</ button >
);
}
Styled Components
Basic Usage
import styled from ' styled-components ' ;
const Button = styled. button `
background: ${ props => props.primary ? ' blue ' : ' gray ' } ;
color: white;
padding: 10px 20px;
` ;
function App () {
return < Button primary >Click me</ Button >;
}
Theme Support
import { ThemeProvider } from ' styled-components ' ;
const theme = {
colors : {
primary : ' blue ' ,
secondary : ' gray ' ,
},
};
function App () {
return (
< ThemeProvider theme ={ theme } >
< Button >Click me</ Button >
</ ThemeProvider >
);
}
Emotion
Basic Usage
/** @jsxImportSource @emotion/react */
import { css } from ' @emotion/react ' ;
const buttonStyle = css `
background: blue;
color: white;
padding: 10px 20px;
` ;
function Button () {
return < button css ={ buttonStyle } >Click me</ button >;
}
Style Injection Order Control
import { CacheProvider } from ' @emotion/react ' ;
import createCache from ' @emotion/cache ' ;
const cache = createCache ({ key : ' css ' , prepend : true });
function App () {
return (
< CacheProvider value ={ cache } >
< Button />
</ CacheProvider >
);
}
Tailwind CSS Integration
Basic Configuration
// tailwind.config.js
module . exports = {
content : [ ' ./src/**/*.{js,jsx,ts,tsx} ' ],
theme : {
extend : {},
},
plugins : [],
};
Usage Example
function Button () {
return (
< button className = " bg-blue-500 text-white font-bold py-2 px-4 rounded " >
Click me
</ button >
);
}
JIT Mode
// tailwind.config.js
module . exports = {
mode : ' jit ' ,
// ...
};
Comparison of Styling Solutions
Solution Advantages Disadvantages Use Cases CSS Modules Simple, native support Requires build tools Traditional React applications Styled Components Component-level styling Runtime overhead Dynamic styling needs Emotion Flexible, good performance Slightly complex configuration High-performance requirements Tailwind CSS Utility-first Requires learning Rapid development
Internationalization Support
Multi-Language Solution Design
Implementation with i18next
import i18n from ' i18next ' ;
import { initReactI18next } from ' react-i18next ' ;
i18n
. use (initReactI18next)
. init ({
resources : {
en : {
translation : {
welcome : ' Welcome ' ,
},
},
zh : {
translation : {
welcome : ' Welcome ' ,
},
},
},
lng : ' en ' ,
fallbackLng : ' en ' ,
interpolation : {
escapeValue : false ,
},
});
export default i18n;
Dynamic Language Pack Loading
import i18n from ' ./i18n ' ;
async function loadLanguage ( lang ) {
if ( ! i18n. hasResourceBundle (lang, ' translation ' )) {
const { default : resources } = await import ( `./locales/ ${ lang } .json` );
i18n. addResourceBundle (lang, ' translation ' , resources);
}
i18n. changeLanguage (lang);
}
Dynamic Language Pack Loading
Code Splitting with Webpack
// Dynamically import language packs
const loadLanguage = async ( lang ) => {
const module = await import (
/* webpackChunkName: "lang-[request]" */ `./locales/ ${ lang } .json`
);
return module .default;
};
Pre-Caching with Service Worker
// Pre-cache language packs in Service Worker
self. addEventListener ( ' install ' , ( event ) => {
event. waitUntil (
caches. open ( ' i18n-cache ' ). then (( cache ) => {
return cache. addAll ([ ' /locales/en.json ' , ' /locales/zh.json ' ]);
})
);
});
Time Zone Handling
Using date-fns-tz for Time Zone Handling
import { formatInTimeZone } from ' date-fns-tz ' ;
const date = new Date ();
const options = {
timeZone : ' America/New_York ' ,
year : ' numeric ' ,
month : ' numeric ' ,
day : ' numeric ' ,
hour : ' numeric ' ,
minute : ' numeric ' ,
};
const formatted = formatInTimeZone (date, ' America/New_York ' , options);
Using Intl API for Time Zone Handling
const date = new Date ();
const formatter = new Intl. DateTimeFormat ( ' en-US ' , {
timeZone : ' Asia/Shanghai ' ,
year : ' numeric ' ,
month : ' numeric ' ,
day : ' numeric ' ,
hour : ' numeric ' ,
minute : ' numeric ' ,
});
const formatted = formatter. format (date);
Security Mechanisms
XSS Protection
// Sanitize HTML with DOMPurify
import DOMPurify from ' dompurify ' ;
function sanitizeInput ( input ) {
return DOMPurify. sanitize (input);
}
// Use in React
function SafeHtml ({ html }) {
return < div dangerouslySetInnerHTML ={ { __html : sanitizeInput (html) } } />;
}
CSP Strategy
<!-- Set CSP in HTML -->
< meta
http-equiv = " Content-Security-Policy "
content = " default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline' "
/>
CSRF Protection
Using CSRF Token
// Backend generates token
app. get ( ' /api/csrf-token ' , ( req , res ) => {
res. json ({ token : req. csrfToken () });
});
// Frontend usage
async function fetchData () {
const { token } = await fetch ( ' /api/csrf-token ' ). then ( res => res. json ());
const response = await fetch ( ' /api/data ' , {
method : ' POST ' ,
headers : {
' Content-Type ' : ' application/json ' ,
' X-CSRF-Token ' : token,
},
body : JSON . stringify ({ data : ' value ' }),
});
}
Content Security Policy (CSP)
Complete CSP Configuration Example
< meta
http-equiv = " Content-Security-Policy "
content = "
default-src 'self';
script-src 'self' https://cdn.example.com 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
connect-src 'self' https://api.example.com;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
"
/>
Dynamic CSP Adjustment
// Dynamically set CSP based on environment
function setCSPHeader ( req , res , next ) {
const csp = process.env. NODE_ENV === ' production '
? " default-src 'self'; "
: " default-src *; " ;
res. setHeader ( ' Content-Security-Policy ' , csp);
next ();
}
Authentication and Authorization
JWT Implementation
// Return JWT after login
app. post ( ' /login ' , ( req , res ) => {
const user = authenticate (req.body);
if (user) {
const token = jwt. sign (user, process.env. JWT_SECRET , { expiresIn : ' 1h ' });
res. json ({ token });
} else {
res. status ( 401 ). json ({ error : ' Invalid credentials ' });
}
});
// Protected route
app. get ( ' /protected ' , ( req , res ) => {
const token = req.headers.authorization?. split ( ' ' )[ 1 ];
try {
const decoded = jwt. verify (token, process.env. JWT_SECRET );
res. json ({ user : decoded });
} catch {
res. status ( 401 ). json ({ error : ' Invalid token ' });
}
});
OAuth2 Integration
// Integrate OAuth2 with passport.js
const passport = require ( ' passport ' );
const OAuth2Strategy = require ( ' passport-oauth2 ' ).Strategy;
passport. use ( new OAuth2Strategy ({
authorizationURL : ' https://auth.example.com/oauth/authorize ' ,
tokenURL : ' https://auth.example.com/oauth/token ' ,
clientID : process.env. CLIENT_ID ,
clientSecret : process.env. CLIENT_SECRET ,
callbackURL : " http://localhost:3000/auth/callback "
},
function ( accessToken , refreshToken , profile , cb ) {
// Find or create user
User. findOrCreate ({ oauthId : profile.id }, function ( err , user ) {
return cb (err, user);
});
}));
// Route configuration
app. get ( ' /auth ' , passport. authenticate ( ' oauth2 ' ));
app. get ( ' /auth/callback ' ,
passport. authenticate ( ' oauth2 ' , { failureRedirect : ' / ' }),
( req , res ) => res. redirect ( ' /dashboard ' )
);
Authentication in Micro Frontend Environments
// Main application sets authentication state
window.__AUTH_STATE__ = {
token : ' ... ' ,
user : { id : 1 , name : ' John ' }
};
// Sub-application retrieves authentication state
function getAuthState () {
return window.__AUTH_STATE__;
}
// Sub-application sets authentication state
window.parent.__AUTH_STATE__ = { ... };
Summary
Engineering practices in micro frontend architectures require comprehensive consideration of multiple aspects:
Dynamic and On-Demand Loading : Optimize resource loading and improve application performance through preloading strategies, lazy loading implementations, and dynamic import syntax.
State Management Solutions : Select appropriate global state management tools, establish state sharing and isolation strategies to ensure state consistency while avoiding pollution.
Styling Solutions : Choose between CSS Modules, Styled Components, Emotion, or Tailwind CSS based on project needs, balancing development efficiency and performance.
Internationalization Support : Design multi-language solutions, implement dynamic language pack loading, and handle time zones to meet global requirements.
Security Mechanisms : Implement XSS protection, CSRF protection, CSP strategies, and authentication/authorization to ensure application security.
Each aspect’s implementation requires trade-offs and adjustments based on specific project needs and technology stacks. Engineering practices in micro frontend architectures are an ongoing optimization process, requiring continuous refinement as projects evolve and teams grow.