面试题答案
一键面试1. 代码分离与懒加载实现
- 子应用模块拆分:
- 在每个子应用的Webpack配置中,使用
splitChunks
插件。例如:
- 在每个子应用的Webpack配置中,使用
module.exports = {
//...其他配置
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name:'vendors',
chunks: 'all'
}
}
}
}
};
- 这样可以将子应用的第三方依赖模块分离出来,单独打包,避免重复打包。
2. 懒加载实现:
- 在子应用的入口文件或路由处,使用动态导入(import()
语法)来实现懒加载。例如,在Vue子应用中:
const router = new VueRouter({
routes: [
{
path: '/home',
component: () => import('./views/Home.vue')
}
]
});
- 在React子应用中:
import React, { lazy, Suspense } from'react';
import { BrowserRouter as Router, Routes, Route } from'react-router-dom';
const Home = lazy(() => import('./components/Home'));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/home" element={<Home />} />
</Routes>
</Suspense>
</Router>
);
}
2. 处理依赖共享
- 使用externals:
- 在Webpack配置中,通过
externals
配置项将共享依赖声明为外部依赖。例如,如果所有子应用都依赖lodash
,可以这样配置:
- 在Webpack配置中,通过
module.exports = {
//...其他配置
externals: {
'lodash': '_'
}
};
- 这样在打包时,Webpack不会将`lodash`打包进子应用,而是假设运行环境中已经有`lodash`全局变量`_`。
2. CDN引入共享依赖: - 将共享依赖通过CDN引入到主应用的HTML模板中。例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Main App</title>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
</head>
<body>
<div id="app"></div>
<script src="main.js"></script>
</body>
</html>
3. 处理加载顺序问题
- 主应用管理加载顺序:
- 在主应用中,使用一个加载器(如
import - maps - polyfill
)来管理子应用的加载顺序。例如,先加载公共的运行时脚本,再按顺序加载子应用。
- 在主应用中,使用一个加载器(如
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Main App</title>
<script type="importmap">
{
"imports": {
"sub - app - 1": "/sub - app - 1.js",
"sub - app - 2": "/sub - app - 2.js"
}
}
</script>
<script src="https://unpkg.com/import - maps - polyfill"></script>
<script>
importMapsPolyfill.polyfill().then(() => {
import('sub - app - 1').then(() => {
import('sub - app - 2');
});
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
4. 解决资源冲突和加载异常问题
- 资源冲突:
- 命名空间管理:确保每个子应用的CSS类名、JavaScript变量等都有唯一的命名空间。可以使用CSS Modules或BEM命名规范来管理CSS类名,在JavaScript中使用ES6模块来避免全局变量冲突。
- 样式隔离:使用Shadow DOM来隔离子应用的样式,防止样式泄漏到其他子应用或主应用。例如,在子应用的入口文件中创建Shadow DOM:
const app = document.createElement('div');
app.id ='sub - app - 1';
const shadow = app.attachShadow({ mode: 'open' });
shadow.innerHTML = `<style>/*子应用样式*/</style><div>子应用内容</div>`;
document.body.appendChild(app);
- 加载异常:
- 错误捕获:在主应用加载子应用的代码处,使用
try - catch
块捕获加载异常。例如:
- 错误捕获:在主应用加载子应用的代码处,使用
importMapsPolyfill.polyfill().then(() => {
try {
import('sub - app - 1').then(() => {
import('sub - app - 2');
});
} catch (error) {
console.error('子应用加载失败:', error);
}
});
- **重试机制**:对于因网络问题等导致的加载异常,可以实现一个简单的重试机制。例如:
function loadSubApp(subAppName, retries = 3) {
return new Promise((resolve, reject) => {
const load = () => {
import(subAppName)
.then(resolve)
.catch((error) => {
if (retries > 0) {
setTimeout(() => {
load();
}, 1000);
retries--;
} else {
reject(error);
}
});
};
load();
});
}