Vue.js路由懒加载(Webpack)封装函数触发Webpack警告求助
这个警告的核心原因是Webpack的静态代码分析机制:Webpack在打包时需要提前识别哪些文件要被分割成独立chunk,当你用require(path)这种完全动态的路径(path是变量)时,Webpack没法静态解析出具体要加载的文件,所以会抛出"Critical dependency"的警告,导致构建异常。
下面给你几个可行的解决方案,按推荐程度排序:
1. 使用ES动态import语法封装(推荐)
Vue Router官方现在更推荐用ES2015的import()语法来实现懒加载,Webpack对这种写法的静态分析支持更好,还能通过魔法注释自定义chunk名称:
import Vue from 'vue' import VueRouter from 'vue-router' import App from './App.vue' Vue.use(VueRouter) import About from './components/About.vue' import Other from './components/Other.vue' // 封装懒加载函数 const lazyLoader = (componentName) => { // 魔法注释:Webpack会把chunk命名为组件名,方便调试 return () => import(/* webpackChunkName: "[request]" */ `./components/${componentName}.vue`) } const LazyAbstraction = lazyLoader('LazyLoadMePlease') const Home = { template: '<div><h2>Home Page</h2></div>'} const Contact = { template: '<div><h2>Contact Page</h2></div>'} const routes = [ { path: '/', component: Home }, { path: '/about', component: About }, { path: '/lazy', component: LazyAbstraction }, { path: '/contact', component: Contact }, { path: '/other', component: Other } ] const router = new VueRouter({ routes, mode: 'history' }) new Vue({ el: '#app', router, render: h => h(App) })
这里我们只传组件名,固定路径前缀./components/,Webpack能静态分析出要打包该目录下所有匹配的.vue文件,同时魔法注释让chunk命名更清晰。
2. 改进require.ensure的封装方式
如果你坚持用require.ensure,同样需要让路径有静态可分析的部分,不要用完全动态的变量:
let lazyLoader = function(componentName) { return r => require.ensure([], () => r(require(`./components/${componentName}.vue`))) } // 使用时传组件名即可 const LazyAbstraction = lazyLoader('LazyLoadMePlease')
这种写法和动态import的思路一致,通过固定路径前缀让Webpack能识别要打包的文件范围。
3. 直接传递字面量路径(封装性稍弱)
如果一定要传完整路径,必须确保传递的是字符串字面量,而不是变量,这样Webpack能直接解析:
const lazyLoader = (componentPath) => { return () => import(componentPath) } // 使用时直接传完整的字面量路径 const LazyAbstraction = lazyLoader('./components/LazyLoadMePlease.vue')
这种写法虽然能解决问题,但封装的意义不大,因为还是要写完整路径,不过胜在简单直接。
为什么基础写法没问题?
基础写法里require('./components/Other.vue')是固定的字符串字面量,Webpack在静态分析时能直接定位到这个文件,所以可以正常分割chunk;而你封装后的代码用了变量path,Webpack无法提前知道path的具体值,也就没法预打包对应的文件,从而触发警告。
内容的提问来源于stack exchange,提问作者user1037355

