按路由动态分包后为什么还是有重复代码?

南宫秋花 阅读 37

我在用Vue项目做路由动态分包时遇到问题,按路由拆分的包里总包含重复的axios代码。我试过在webpack的splitChunks里设置cacheGroups,但发现每个chunk里还是有axios的完整拷贝。

配置是这样写的:


optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      axios: {
        test: /[\/]node_modules[\/]axios[\/]/,
        name: 'vendors-axios',
        priority: 20
      }
    }
  }
},

打包后的chunks依然显示每个路由包里都有axios代码块,难道分包策略需要配合其他配置?或者我的路由懒加载方式有问题?

我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
Code°梓涵
问题在于你的 cacheGroups 没有设置 enforce: true,导致 webpack 可能仍然将 axios 重复打包进异步 chunk。改成这样:

cacheGroups: {
axios: {
test: /[/]node_modules[/]axios[/]/,
name: 'vendors-axios',
priority: 20,
chunks: 'all',
enforce: true
}
}


另外确保路由懒加载写法正确,用 import('xxx') 动态导入,不要在入口文件里直接引入 axios。
点赞 2
2026-02-12 08:06
轩辕青霞
你的问题确实挺典型的,按路由动态分包后出现重复代码的情况,很多时候是因为Webpack的分包策略没完全对齐,或者某些模块被意外地重复打包了。具体来说,咱们得从几个角度来排查和优化。

### 1. 为什么会出现重复代码?
在你的配置里,虽然设置了 cacheGroups 来单独提取 Axios,但有可能 Axios 被某个 chunk 的依赖树“劫持”了,导致它没有被正确地归到 vendors-axios 这个分组里。这种情况可能有以下原因:
- Axios 被直接引入到了某个组件或模块中,而这个模块没有被 Webpack 正确识别为共享依赖。
- 动态导入的模块路径不一致,比如有的地方写的是 'axios',有的地方写的是 '/node_modules/axios' 或其他形式,导致 Webpack 认为这是不同的模块。

### 2. 解决方案
咱们需要确保 Axios 被正确提取到一个独立的 chunk 里,并且其他 chunk 不再包含它的代码。以下是具体的调整步骤:

#### (1) 确保 Axios 只有一个入口
检查整个项目中 Axios 的引用方式。如果有的地方是这样写的:
import axios from 'axios';

而有的地方是这样写的:
import { get, post } from '/node_modules/axios/index.js';

那 Webpack 就会认为这是两个不同的模块。统一所有地方的引用方式,推荐直接用 import axios from 'axios';

#### (2) 修改 Webpack 配置
你现在的配置其实已经接近正确了,但可以稍微增强一下规则,确保 Axios 不会被误打包到其他 chunk 中。试试下面的配置:

optimization: {
splitChunks: {
chunks: 'all', // 对同步和异步代码都进行分割
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/, // 匹配所有 node_modules 里的模块
name: 'vendors',
priority: 10, // 优先级低于 Axios
chunks: 'all'
},
axios: {
test: /[\/]node_modules[\/]axios[\/]/, // 专门匹配 Axios
name: 'vendors-axios', // 提取到单独的 chunk
priority: 20, // 优先级高于 vendors
chunks: 'all'
}
}
}
},


重点解释下:
- vendors 分组:用来提取所有第三方库的代码。
- axios 分组:专门针对 Axios 设置更高的优先级,确保它不会被误打包到其他地方。

#### (3) 检查路由懒加载方式
如果你的路由懒加载代码是这样的:
const Home = () => import(/* webpackChunkName: "home" */ './views/Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './views/About.vue');

要确保每个路由模块里没有重复引入 Axios。如果某个组件里写了 import axios from 'axios';,那这个 Axios 很可能会被打包进对应的路由 chunk。最好的做法是通过全局注入的方式管理 Axios 实例,而不是在每个组件里单独引入。

举个例子,在 main.js 里创建一个全局 Axios 实例:
import axios from 'axios';

// 创建 Axios 实例并挂载到 Vue 原型上
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
});

Vue.prototype.$axios = instance;

new Vue({
router,
render: h => h(App)
}).$mount('#app');


然后在组件里直接用 this.$axios,就不用每次手动引入 Axios 了。

#### (4) 使用 DllPlugin(可选)
如果你发现即使调整了配置还是有重复代码,可以考虑使用 Webpack 的 DllPlugin 插件,提前把 Axios 和其他第三方库打包成一个独立的 DLL 文件。不过这种方式稍微复杂一点,适合大型项目。

### 3. 最后验证
完成以上调整后,重新运行打包命令 npm run build,然后检查生成的文件。可以通过以下命令查看打包分析:
npx webpack-bundle-analyzer dist/stats.json

确保 vendors-axios 是一个独立的 chunk,而且其他路由相关的 chunk 里不再包含 Axios 的代码。

---

好了,大致就这么回事。如果还有问题,可以贴一下具体的打包结果或者更详细的配置文件,我再帮你看看。这种重复代码的问题确实是挺让人头疼的,尤其是当你辛辛苦苦做了动态分包却发现还是臃肿的时候……反正我是深有体会 😅
点赞 10
2026-01-30 16:17