Ken*_*ong 11 single-page-application reactjs webpack webpack-2 create-react-app
我有一个单页应用程序,我在每条路线上编码拆分.当我部署新版本的应用时,如果用户仍然打开该页面并访问之前未访问过的路由,则用户通常会收到错误.
另一种情况是,如果应用程序启用了服务工作程序,也会发生这种情况.当用户在新部署后访问页面时,服务工作者将从缓存中提供服务.然后,如果用户尝试访问不在其缓存中的页面,则他们将获得块加载失败.
目前我在我的应用程序中禁用了代码拆分以避免这种情况,但我一直很好奇处理这个问题的最佳方法是什么.我已经考虑过在用户完成加载初始页面后预加载所有其他路由,我相信这可能会解决路由上代码拆分的问题.但是,假设我想对组件进行代码拆分,那么这意味着我必须设法确定何时以及如何预加载所有这些组件.
所以我想知道人们如何处理单页应用程序的这个问题?谢谢!(我目前正在使用create-react-app)
Jor*_*dan 17
我更喜欢让用户刷新而不是自动刷新(这可以防止无限刷新循环错误的可能性)。
以下策略适用于 React 应用程序,在路由上拆分代码:
将您的 index.html 设置为从不缓存。这可确保请求您的初始资产的主文件始终是最新的(通常它并不大,因此不缓存它应该不是问题)。请参阅MDN 缓存控制。
对块使用一致的块散列。这确保只有更改的块才会具有不同的散列。(参见下面的 webpack.config.js 片段)
不要在部署时使 CDN 的缓存失效,这样旧版本在部署新版本时就不会丢失它的块。
在路由之间导航时检查应用程序版本,以便通知用户他们是否在旧版本上运行并请求他们刷新。
最后,以防万一 ChunkLoadError确实发生:添加一个错误边界。(参见下面的错误边界)
optimization: {
moduleIds: 'hashed',
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
// vendor chunk
vendor: {
name: 'vendor',
// async + async chunks
chunks: 'all',
// import file path containing node_modules
test: /node_modules/,
priority: 20
},
}
}
Run Code Online (Sandbox Code Playgroud)
optimization: {
moduleIds: 'hashed',
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
// vendor chunk
vendor: {
name: 'vendor',
// async + async chunks
chunks: 'all',
// import file path containing node_modules
test: /node_modules/,
priority: 20
},
}
}
Run Code Online (Sandbox Code Playgroud)
注意:确保清除内部导航事件上的错误(例如,如果您正在使用 react-router),否则错误边界将在内部导航之后持续存在,并且只会在真正的导航或页面刷新时消失。
我们的 create-react-app 中的问题是脚本标记引用的块不存在,因此它在我们的 index.html 中抛出错误。这是我们得到的错误。
Uncaught SyntaxError: Unexpected token < 9.70df465.chunk.js:1
Run Code Online (Sandbox Code Playgroud)
更新
我们解决这个问题的方法是让我们的应用程序成为一个渐进式网络应用程序,这样我们就可以利用服务工作者。
将 create react 应用程序转换为 PWA 很容易。PWA 上的 CRA 文档
然后,为了确保用户始终使用最新版本的 service worker,我们确保每当有更新的 worker 等待时,我们都会告诉它 SKIP_WAITING,这意味着下次刷新浏览器时,他们将获得最新版本代码。
Uncaught SyntaxError: Unexpected token < 9.70df465.chunk.js:1
Run Code Online (Sandbox Code Playgroud)
Bellow 是我们尝试的第一件事,并且确实遇到了一些无限循环
我让它工作的方法是在 index.html 的所有脚本标签上方添加一个 window.onerror 函数。
<script>
window.onerror = function (message, source, lineno, colno, error) {
if (error && error.name === 'SyntaxError') {
window.location.reload(true);
}
};
</script>
Run Code Online (Sandbox Code Playgroud)
我希望有更好的方法,但这是我能想到的最好方法,并且感觉这是一个非常安全的解决方案,因为 create-react-app 不会编译或构建任何语法错误,这应该是我们唯一的情况得到一个语法错误。
| 归档时间: |
|
| 查看次数: |
633 次 |
| 最近记录: |