3、核心概念-Entry:单入口与多入口配置、entry的多种写法

Entry,说白了就是 Webpack 打包的起点。

你告诉它:「从这儿开始,把所有依赖都给我找出来。」

它就会顺着你的代码,一路追踪 import 和 require,最后打包成一个或多个文件。

我个人习惯把 Entry 理解为「项目的入口文件」。但别小看这个配置,它其实有很多种玩法。

3.1 单入口配置:最基础的写法

单入口,就是整个项目只有一个起点。

大部分简单项目、单页应用(SPA)都用这种模式。

// webpack.config.js
module.exports = {
  entry: './src/index.js'
};

嗯,就这么简单。一个字符串,指向你的主文件。

我在项目中遇到过不少新手,直接把 entry 写成绝对路径:

// ❌ 错误示范
entry: '/Users/me/project/src/index.js'

千万别这么干。一旦项目换个目录,或者别人拉下来跑,直接就崩了。

用相对路径,或者配合 path.resolve 会更稳妥。

小技巧: 我习惯用 path.resolve(__dirname, 'src/index.js'),这样不管在哪个目录执行,路径都不会出错。

3.2 多入口配置:一个项目,多个起点

多入口,说白了就是你的项目有多个独立的页面。

比如一个后台管理系统,有「登录页」、「仪表盘」、「用户管理」三个页面。每个页面都有自己的 JS 逻辑,互不干扰。

这时候,单入口就不够用了。

// webpack.config.js
module.exports = {
  entry: {
    login: './src/login.js',
    dashboard: './src/dashboard.js',
    user: './src/user.js'
  }
};

每个 key 对应一个 chunk 名称。Webpack 会分别打包出三个文件。

我曾经接手过一个老项目,所有页面都挤在一个入口文件里,光加载就要好几秒。后来拆成多入口,每个页面只加载自己的代码,速度直接翻倍。

注意: 多入口模式下,output 的 filename 必须用占位符,比如 [name].bundle.js,否则会报错。因为 Webpack 不知道该怎么命名多个输出文件。

3.3 entry 的多种写法

entry 不止能写字符串和对象。它还有几种「变体」,我一个个说。

3.3.1 字符串写法

entry: './src/index.js'

最简单,最直接。适合单入口项目。

3.3.2 数组写法

entry: ['./src/polyfill.js', './src/index.js']

数组里的文件会按顺序打包,最终合并成一个 chunk。

你想想看,什么时候会用这种写法?

比如你需要先加载 polyfill,再加载业务代码。或者你想把多个库合并成一个文件。

我在项目中遇到过需要兼容 IE 的情况,就用数组把 polyfill 和主文件放在一起:

entry: ['@babel/polyfill', './src/index.js']

这样打包出来,polyfill 会先执行,业务代码后执行,完美。

3.3.3 对象写法

entry: {
  app: './src/app.js',
  admin: './src/admin.js'
}

对象写法最灵活。每个 key 就是一个 chunk 名称,适合多入口场景。

你还可以在对象里嵌套数组:

entry: {
  app: ['@babel/polyfill', './src/app.js'],
  admin: './src/admin.js'
}

这样 app 入口会先加载 polyfill,再加载业务代码。而 admin 入口只加载自己的逻辑。

核心区别:
  • 字符串:单入口,最简单
  • 数组:多文件合并成一个入口,适合前置依赖
  • 对象:多入口,每个 key 独立打包

3.4 动态入口:运行时决定入口文件

动态入口,说白了就是入口文件不是写死的,而是根据某些条件动态生成。

什么时候会用?

比如你有一个多页面的项目,页面数量不固定,每次新增页面都要手动改 webpack 配置,太麻烦了。

这时候,动态入口就派上用场了。

// webpack.config.js
const fs = require('fs');
const path = require('path');

// 自动扫描 pages 目录下的所有入口文件
const pagesDir = path.resolve(__dirname, 'pages');
const entries = {};

fs.readdirSync(pagesDir).forEach(dir => {
  const entryPath = path.join(pagesDir, dir, 'index.js');
  if (fs.existsSync(entryPath)) {
    entries[dir] = entryPath;
  }
});

module.exports = {
  entry: entries
};

这样,只要在 pages 目录下新建一个文件夹,里面放上 index.js,Webpack 就会自动把它当成一个入口。

我曾经维护过一个大型 CMS 系统,有几十个页面。每次新增页面都要改 webpack 配置,烦得要死。后来改成动态入口,新增页面只需要建文件夹、写代码,配置完全不用动。

避坑指南: 动态入口虽然方便,但要注意性能。如果 pages 目录下有大量无关文件,扫描会变慢。我建议只扫描特定命名规则的文件夹,比如只扫描以 page- 开头的目录。

3.5 总结一下

Entry 是 Webpack 的起点,但它的配置方式很灵活:

  • 单入口:字符串或数组,适合简单项目
  • 多入口:对象,适合多页面应用
  • 动态入口:运行时生成,适合大型项目

我个人建议:

  • 小项目用字符串,简单直接
  • 多页面用对象,清晰明了
  • 大型项目用动态入口,省心省力

嗯,Entry 就讲到这里。下一章我们聊聊 Output,看看打包出来的文件该怎么命名、放哪儿。