Webpack 打包未使用组件的原因

在项目开发过程中,近期对项目进行了双页面配置,针对两个不同页面分别单独配置了路由。然而,在单独启动新页面(该页面模块数量较少)时,却发现启动耗时较长。经过深入排查,最终确定是以下这行代码导致了该问题:

js 复制代码
return () => import(`@/pages/PRD/views/${realPath}`);

Webpack 在遇到import()语法时,会依据给定路径将所有符合条件的模块进行打包。由于上述导入代码的最后一个部分是变量,对于 Webpack 而言,这等同于@/pages/PRD/views/**/*,因此 Webpack 会将 views 目录下的所有模块及其相关依赖一同打包。

为深入探究 Webpack 对import的处理机制,我创建了一个项目,并针对不同情况进行打包测试,最终得出以下结论:

js 复制代码
// `import`的参数不能是完全动态的语句,例如`import(util)`是不被允许的,至少需要包含部分模块路径信息,以便Webpack确定打包范围。
const component = () => {
  const path = "xxx";
  return import(path); 
}
// 这种导入方式会将xxx目录下的所有组件和js文件都进行打包。
const componentB = (name) => {
  const component = "component" + name;
  return import(`./xxx/${component}`); 
}
// 这种导入方式会将xxx目录下以component开头的文件进行打包。
// 如果xxx目录下存在/component*/这样的文件夹,那么文件夹内的所有组件都会被打包。
const componentC = (name) => {
  const component = 
  return import(`./xxx/component${name}`); 
}
// 较为合适的动态引入方式
const componentD = (name) => {
  const component = 
  return import(`./xxx/component${name}.vue`); 
}

Webpack 解析 import 注释指令

在 Webpack 中,import()函数的注释指令是一种特殊语法,用于控制 Webpack 对动态导入模块的处理方式,主要包含以下几种:

webpackChunkName

  • 功能:该指令用于手动指定 Webpack 拆分代码时生成的代码块(chunk)名称。合理命名代码块,有助于在打包结果中清晰区分不同功能模块的代码块,对缓存管理、调试以及性能分析等工作都非常有利。
  • 示例

    js 复制代码
    import(/* webpackChunkName: "user - module - chunk" */ './userModule.js');

    在上述代码中,Webpack 会将./userModule.js及其依赖模块打包到名为user - module - chunk的代码块中。从 Webpack 2.6.0 版本开始,还支持使用占位符,例如(index)会使代码块名称以递增数字进行命名,(request)则会使用实际解析的文件名。示例如下:

    js 复制代码
    // 假设导入多个模块,会生成类似userModule1、userModule2等命名的代码块
    import(/* webpackChunkName: "userModule(index)" */ './userModule.js'); 

webpackMode

  • 功能:该指令用于指定 Webpack 解析动态导入的模式。在不同模式下,Webpack 对动态导入模块的处理逻辑以及生成代码块的方式会有所不同。
  • 模式类型及示例
  • lazy:这是默认模式。在这种模式下,Webpack 会为每个import()调用单独生成可延迟加载的代码块。也就是说,每次遇到import(),Webpack 都会创建一个新的独立代码块,在运行时按需加载。例如:

    js 复制代码
    import(/* webpackMode: "lazy" */ './module1.js');
    import(/* webpackMode: "lazy" */ './module2.js');

    上述代码会分别生成两个独立的代码块,用于加载module1.js和module2.js。

  • lazy - once:此模式下,Webpack 会生成单个可延迟加载的代码块,该代码块能够满足多个import()调用的需求。适用于一些动态导入语句,比如import(./locales/${language}.json),可能会根据不同的language值请求多个模块路径的情况。首次调用import()时获取代码块,后续调用则复用该代码块。示例如下:

    js 复制代码
    // 多个动态导入可能共用一个代码块
    import(/* webpackMode: "lazy - once" */ `./locales/${language}.json`); 
    import(/* webpackMode: "lazy - once" */ `./locales/${anotherLanguage}.json`); 
  • eager:在该模式下,Webpack 不会生成额外的代码块,而是将被导入的模块直接引入当前代码块,并返回已解析状态的Promise。与静态导入不同的是,在import()调用完成前,模块不会执行。例如:

    js 复制代码
    import(/* webpackMode: "eager" */ './eagerModule.js').then((module) => {
      module.someFunction();
    });
相关推荐
二川bro3 小时前
深度解析 Vue 项目 Webpack 分包与合包 一文读懂
前端·vue.js·webpack
魔云连洲18 小时前
用Webpack 基础配置快速搭建项目开发环境
前端·webpack·node.js
ak啊21 小时前
Webpack Source Map 生成流程深度解析
前端·webpack·源码
A-Kamen1 天前
Webpack vs Vite:深度对比与实战示例,如何选择最佳构建工具?
前端·webpack·node.js
coding随想2 天前
解决前端项目中无法识别 .node 文件的依赖安装问题
前端·webpack·vite
DJA_CR2 天前
Webpack 及 Vue CLI 中环境变量配置详解
前端·javascript·webpack
ak啊2 天前
Webpack 的动态导入(Dynamic Import)
前端·webpack·源码
john_Asura2 天前
Webpack与Vite构建工具对比分析
前端·webpack·node.js
Moment3 天前
拆包的艺术:Webpack SplitChunksPlugin 执行流程全流程揭秘 🤩🤩🤩
前端·javascript·webpack