知海

入口点(Entry)

webpackjsorg-main核心概念

入口点(Entry)

起步指南中提到过,webpack 配置中的 entry 属性有多种定义方式。本文将展示这些配置方式,并解释每种方式的使用场景。

简单来说,入口点(entry point)告诉 webpack 从哪里开始构建内部依赖图。webpack 会从这个文件出发,递归地追踪所有被导入的模块和资源,以此决定最终打包产物中应包含哪些内容。

这一过程的结果随后会根据 output 配置写入磁盘,output 决定了打包文件的输出位置和方式。

T> 当运行 webpack 而未提供配置文件时,entry 默认为 './src/index.js'。如果该文件不存在——即使 src/ 目录存在——webpack 也会抛出以下错误:
ERROR in Entry module not found: Error: Can't resolve './src'

错误信息中显示的是 './src' 而非 './src/index.js',这是因为 webpack 会先解析目录,然后在目录中查找 index.js。若要使用其他入口文件名,请按下文各节所示配置 entry 选项。

单个入口(简写)语法

用法:entry: string | [string]

  • string:单个入口文件
  • [string]:多个入口文件

webpack.config.js

js 复制代码
export default {
  entry: "./path/to/my/entry/file.js",
};

entry 属性的单个入口语法等价于:

webpack.config.js

js 复制代码
export default {
  entry: {
    main: "./path/to/my/entry/file.js",
  },
};

我们也可以向 entry 属性传入一个文件路径数组,这将创建所谓的 "多主入口"(multi-main entry)。当你希望将多个相互依赖的文件合并在一起,并将它们的依赖关系整合到同一个 "chunk" 中时,这种写法非常有用。

webpack.config.js

js 复制代码
export default {
  entry: ["./src/file_1.js", "./src/file_2.js"],
};

当入口点传入数组时,webpack 仍然只会创建一个单个入口 chunk。数组中的所有模块都会按给定顺序加载,并合并到同一个依赖图中。

这种模式常用于在主应用入口之前注入额外代码,例如 polyfill 或仅开发环境使用的工具,而无需在应用源码中手动引入它们。

示例:注入 polyfill

js 复制代码
export default {
  entry: {
    main: ["@babel/polyfill", "./src/index.js"],
  },
};

当你希望为只有一个入口点的应用或工具(例如库)快速搭建 webpack 配置时,单个入口语法是一个很好的选择。但这种语法在扩展和规模化配置方面的灵活性有限。

对象语法

用法:entry: { <entryChunkName> string | [string] } | {}

  • <entryChunkName>:入口 chunk 的名称
  • string:单个入口文件
  • [string]:多个入口文件
  • {}:空对象

webpack.config.js

js 复制代码
export default {
  entry: {
    app: "./src/app.js",
    adminApp: "./src/adminApp.js",
  },
};

对象语法虽然更冗长,但它是在应用中定义入口/多个入口时最具扩展性的方式。

T> **"可扩展的 webpack 配置"**是指能够被复用并与其他部分配置合并的配置。这是一种流行的技术,用于按环境、构建目标和运行时来分离关注点,然后借助 webpack-merge 等专用工具进行合并。

T> 当只有由插件生成的入口点时,可以向 entry 传入空对象 {}

EntryDescription 对象

这是一个描述入口点的对象,可以指定以下属性:

  • dependOn:当前入口点所依赖的其他入口点。在加载当前入口点之前,这些依赖项必须已加载完成。
  • filename:指定每个输出文件在磁盘上的名称。
  • import:启动时需要加载的模块。
  • library:指定 library 选项,以便从当前入口打包一个库。
  • runtime:运行时 chunk 的名称。设置后会创建一个新的运行时 chunk。自 webpack 5.43.0 起,可将其设置为 false 以避免创建新的运行时 chunk。
  • publicPath:当浏览器引用此入口的输出文件时,指定一个公共 URL 地址。另请参阅 output.publicPath

webpack.config.js

js 复制代码
export default {
  entry: {
    a2: "dependingfile.js",
    b2: {
      dependOn: "a2",
      import: "./src/app.js",
    },
  },
};

在单个入口上,runtimedependOn 不能同时使用。因此以下配置无效并会抛出错误:

webpack.config.js

js 复制代码
export default {
  entry: {
    a2: "./a",
    b2: {
      runtime: "x2",
      dependOn: "a2",
      import: "./b",
    },
  },
};

确保 runtime 不能指向已存在的入口点名称,例如以下配置会抛出错误:

js 复制代码
export default {
  entry: {
    a1: "./a",
    b1: {
      runtime: "a1",
      import: "./b",
    },
  },
};

同样,dependOn 不能形成循环依赖,以下示例同样会抛出错误:

js 复制代码
export default {
  entry: {
    a3: {
      import: "./a",
      dependOn: "b3",
    },
    b3: {
      import: "./b",
      dependOn: "a3",
    },
  },
};

场景示例

下面列出了一些入口配置及其实际应用场景:

分离应用与第三方库入口

webpack.config.js

js 复制代码
export default {
  entry: {
    main: "./src/app.js",
    vendor: "./src/vendor.js",
  },
};

production 模式下构建时:

webpack.prod.js

js 复制代码
export default {
  output: {
    filename: "[name].[contenthash].bundle.js", // 例如:main.abc123.bundle.js、vendor.abc123.bundle.js
  },
};

development 模式下构建时:

webpack.dev.js

js 复制代码
export default {
  output: {
    filename: "[name].bundle.js", // 例如:main.bundle.js、vendor.bundle.js
  },
};

这样做有什么效果? 我们是在告诉 webpack 需要两个独立的入口点(如上例所示)。

为什么? 通过这种方式,你可以将不会改动的库或文件(例如 Bootstrap、jQuery、图片等)引入 vendor.js,让它们打包到独立的 chunk 中。content hash 保持不变,浏览器可以单独缓存它们,从而减少加载时间。

T> 在 webpack 4 之前的版本中,通常会将第三方库作为单独的入口点来编译成独立文件(配合 CommonsChunkPlugin 使用)。

但在 webpack 4 中不推荐这样做。取而代之的是,optimization.splitChunks 选项负责分离第三方库和应用模块,并创建独立文件。不要为第三方库或其他并非执行起点的内容创建入口。

多页面应用

webpack.config.js

js 复制代码
export default {
  entry: {
    pageOne: "./src/pageOne/index.js",
    pageTwo: "./src/pageTwo/index.js",
    pageThree: "./src/pageThree/index.js",
  },
};

这样做有什么效果? 我们是在告诉 webpack 需要 3 个独立的依赖图(如上例所示)。

为什么? 在多页面应用中,服务器会为每次页面导航返回一个新的 HTML 文档。页面加载新文档时,所有资源都会被重新下载。但这给了我们独特的机会,例如使用 optimization.splitChunks 在每个页面之间创建共享应用代码的 bundle。当入口点数量增加时,在不同入口点之间大量复用代码/模块的多页面应用可以从中大大受益。

T> 经验法则:每个 HTML 文档只使用一个入口点。更多细节请参阅此处描述的问题

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。