javascript - "TypeError: Không thể tải module được nhập động" trên cài đặt Vue/Vite vanilla
Chúng tôi có một thiết lập Vue/Vite cơ bản và tôi đang nhận được TypeError: Failed to fetch dynamically imported module trên các bản ghi Sentry.
Có vẻ như các lỗi này có mối quan hệ theo thời gian với việc triển khai mới lên sản xuất, mặc dù tôi không có đủ dữ liệu để xác nhận. Nó không xảy ra trên môi trường cục bộ và chỉ xuất hiện trên mã đã triển khai.
Tôi đã thấy một số câu hỏi tương tự về các thiết lập của react, nhưng không có câu trả lời nào thỏa đáng.
Tôi cũng đã tìm thấy một câu hỏi tương tự liên quan đến việc nhập khẩu động các tệp svg, nhưng lỗi của chúng tôi xảy ra với các thành phần đầy đủ.
Nơi duy nhất mà chúng tôi sử dụng các thành phần nhập khẩu động là trên định tuyến:
export const router = createRouter({
history: routerHistory,
strict: true,
routes: [
{
path: '/',
name: routes.homepage.name,
component: () => import('@/views/Home.vue'),
children: [
{
path: '/overview',
name: routes.overview.name,
component: () => import('@/views/Overview.vue'),
},
// other similar routes
],
},
],
});
Các phiên bản phụ thuộc của chúng tôi:
"vue": "^3.0.9",
"vue-router": "^4.0.5",
"vite": "^2.0.5",
Bất kỳ thông tin bổ sung nào về vấn đề này và cách gỡ lỗi nó sẽ rất được đánh giá cao!
Câu trả lời #1
Khi bạn nhập động một route/component, trong quá trình build nó sẽ tạo ra một chunk riêng biệt. Theo mặc định, tên file của chunk được băm theo nội dung của chúng - Overview.abc123.js. Nếu bạn không thay đổi mã component, giá trị băm sẽ giữ nguyên. Nếu mã component thay đổi, giá trị băm cũng thay đổi - Overview.32ab1c.js. Điều này rất tốt cho việc caching.
Bây giờ đây là những gì xảy ra khi bạn gặp lỗi này:
- Bạn triển khai ứng dụng
- Phần Home của bạn có một liên kết đến đường dẫn
/overview, điều này sẽ tảiOverview.abc123.js - Khách hàng truy cập trang web của bạn
- Bạn thực hiện các thay đổi trong mã của mình, không nhất thiết là đối với chính thành phần Overview, nhưng có thể là đối với một số thành phần con mà Overview nhập vào.
- Bạn triển khai các thay đổi, và Overview hiện được xây dựng với một hash khác -
Overview.32ab1c.js - Khách hàng nhấp vào liên kết
/overview- nhận được lỗiFailed to fetch dynamically imported module, vìOverview.abc123.jskhông còn tồn tại
Đó là lý do tại sao các lỗi có sự tương quan với việc triển khai. Một cách để khắc phục là không sử dụng các tuyến được nạp lười, nhưng đó không phải là giải pháp tuyệt vời khi bạn có nhiều tuyến nặng - điều đó sẽ làm cho gói chính của bạn trở nên lớn.
Câu trả lời #2
Câu trả lời được chấp nhận giải thích chính xác khi nào lỗi này xảy ra nhưng thực sự không cung cấp một giải pháp tốt.
Cách tôi khắc phục vấn đề này là bằng cách sử dụng một trình xử lý lỗi trên bộ định tuyến. Trình xử lý lỗi này đảm bảo rằng khi lỗi này xảy ra (tức là khi một phiên bản mới của ứng dụng được triển khai), lần thay đổi tuyến tiếp theo sẽ kích hoạt tải lại trang một cách hoàn toàn thay vì tải động các mô-đun. Mã code trông như sau:
router.onError((error, to) => {
if (error.message.includes('Failed to fetch dynamically imported module') || error.message.includes("Importing a module script failed")) {
window.location = to.fullPath
}
})
Trong đó router là phiên bản vue-router của bạn.
Câu trả lời #3
Trong trường hợp của tôi, lỗi xảy ra do không thêm phần mở rộng .vue vào tên mô-đun.
import MyComponent from 'components/MyComponent'
Nó hoạt động trong cài đặt webpack, nhưng với Vite thì cần có phần mở rộng tệp:
import MyComponent from 'components/MyComponent.vue'
Câu trả lời #4
Tôi đã gặp phải vấn đề y hệt. Trong trường hợp của tôi, một số tuyến hoạt động và một số thì không. Giải pháp khá dễ dàng. Tôi chỉ cần khởi động lại máy chủ phát triển.
Câu trả lời số 5
Giải pháp của Wouter Sioen thì tốt, nhưng sau khi sửa lỗi này tôi gặp phải một vấn đề khác khi xảy ra lỗi chunkLoad: Không thể đọc các thuộc tính của undefined (đang đọc 'fullPath'). Giải pháp của tôi cho vấn đề đó là:
router.onError((error, to) => {
if (
error.message.includes('Failed to fetch dynamically imported module') ||
error.message.includes('Importing a module script failed')
) {
if (!to?.fullPath) {
window.location.reload();
} else {
window.location = to.fullPath;
}
}
