2.核心概念—入口—下-灵析社区

懒人学前端

二、Entry 和 Context

配置入口context和entry

webpack 在构建打包时,通过 context 和 entry 这两个配置来找到打包入口路径。在配置入口时其实做了两件事:

  • 确认入口文件位置,告诉 webpack 从哪个文件开始打包
  • 描述 chunk name。如果传入一个字符串或字符串数组,那么默认的 chunk name 为 “main”,如果传入的是一个对象,则每个属性的 key 会是 chunk 的名称,该属性的值描述了 chunk 的入口点

context

context 可以理解为配置资源入口的基础目录,在配置时要求必须使用绝对路径。如:现有的目录结构入口为 /src/script/index.js,则我们可以通过下面的配置来指定入口目录

const path = require('path');
module.exports = {
  context: path.resolve(__dirname, './src/script'),
  entry: './index.js'
};
module.exports = {
  context: path.resolve(__dirname, './src'),
  entry: './script/index.js'
};

这样配置后,命令行执行打包,发现依然成功的找到了入口并顺利打包(我们使用 hello world 的那个 demo 来执行现有配置)

配置 context 的目的可以使 entry 的写法更加简洁,尤其是在多入口文件的情况下。不过 context 是可以省略的,默认值为当前工程的根目录。

entry

在 webpack 配置中有多种方式定义 entry 属性,如:字符串、数组、对象、函数,接下来我们展示下每种类型如何配置

字符串类型

直接定义入口名称

module.exports = {
  entry: './src/script/index.js',
};
// entry 单入口语法,是下面的简写
module.exports = {
  entry: {
    main: './src/script/index.js',
  },
};

数组类型

传入一个数组的作用是将多个文件预先合并,最终将多个依赖的内容绘制在一个 chunk 中,在打包时 webpack 会将数组中的最后一个元素作为实际的入口路径,其余文件会预先构建到入口文件。

module.exports = {
  entry: ['lodash', './src/script/index.js'],
};

这种配置和下面是等效的

// index.js
import * from 'lodash'
// webpack.config.js
module.exports = {
  entry: './src/script/index.js',
}

这种写法会将 lodash 打包到我们的 bundle.js 中。这种写法类似于在 index.js 中引入 lodash,在控制台执行打包命令我们来看下生成的文件,从下面两张图可以看到在 index 中我们没有引入 lodash,但打包的文件中已经引入了 lodash

对象类型

如果要定义多入口文件则需要使用对象的形式,通过这种方式可以自定义 chunk name,其中对象的key即为 chunk name,对象的 value 为入口路径。在使用对象描述入口时,我们可以使用以下属性

  • dependOn: 当前入口所依赖的入口。它们必须在该入口被加载前被加载
  • filename: 指定要输出的文件名称
  • import: 启动时需加载的模块
  • library: 指定 library 选项,为当前 entry 构建一个 library
  • runtime: 运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。在 webpack 5.43.0 之后可将其设为 false 以避免一个新的运行时 chunk
  • publicPath: 当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址

多入口配置本质上打包后生成多个js文件

module.exports = {
  entry: {
    index: ['lodash', './src/script/index.js'],
    vendor: './vendor'
  }
}

函数类型

使用函数类型定义入口时,只要返回上面介绍的几种形式即可,如

// 返回字符串
module.exports = {
  entry: () => './src/script/index.js'
}
// 返回对象
module.exports = {
  entry: () => ({
    index: ['lodash', './src/script/index.js'],
    vendor: './vendor'
  })
}

传入函数的优点是我们可以通过函数中增加一些逻辑来动态改变打包入口

总结

本章我们梳理了 webpack 入口配置的几种方式,包括字符串、对象、数组、函数几种

三、Entry 配置实例

entry 配置实例

webpack 的 entry 配置在实际的应用中可以分几个场景。

  • 单页应用
  • 多页应用
  • 分离应用程序和第三方库

下面我们来介绍下这几种应用

单页应用

对于单页应用,我们一般来定义单一入口即可

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

通过单一入口打包文件,可以将所有入口文件依赖的 框架、引入的工具库、各个页面内容打包到一起。这样的好处是将所有内容都打包成一个 js 文件,依赖关系清晰。但是这种方式也有个弊端,即所有模块都打到一个包中,当应用规模上升到一定程度后导致打包资源体积过大,导致页面首次加载速度变慢

多页应用

对于多页应用的场景,为了尽可能减少打包资源的体积,我们希望每个页面都只加载各自必要的逻辑,而不是将所有内容都打包到一个 bundle 中,我们来看下多应用的配置

const path = require('path');
module.exports = {
  entry: {
    index: './src/index.js',
    hello: './src/hello.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist')
  }
};

打包后的文件如下,可以看到打包的内容中包含了 index.js 和 hello.js 两个文件。

分离应用程序和第三方库

在一个应用中,我们使用的框架、库、第三方依赖等往往很少会有改动,如果我们将所有内容都打包到一个 bundle 文件,一旦业务代码有一点点变更,那用户就要重新下载整个资源,这对于页面的性能是很不友好的。为了解决这个问题,我们可以使用应用程序和第三方库分离的方式来打包文件。也就是将业务代码和不频繁变更的第三方依赖分 bundle 打包,示例如下

webpack.config.js
module.exports = {
  mode: 'development',
  entry: {
    index: './src/index.js',
    vendor: ['lodash']
  }
};

index.js

import * as _ from 'lodash'

在上面的配置中,index.js 仍然和之前一样不做任何处理,只是我们新添加了一个 chunk name 为 vendor 的入口,并通过数组的形式将第三方依赖添加进去,执行打包命令我们看到输出了两个打包文件。

其实上面的代码虽然打包成功了,也成功提取了 vender 文件,但是打开打包后的 dist/index.js 我们发现 lodash 还是被打到文件中了,对于这种情况我们可以配合使用 optimization.splitChunks,将 vender 和 index 中的公共代码提取出来,这个方法我们后面的文章在详细介绍。

通过上面的配置,我们可以业务依赖的第三方模块抽取成一个独立的 bundle,由于这个 bundle 不经常变动,因此可以有效的利用客户端缓存,在用户后续请求页面时加快整体渲染速度。

阅读量:2014

点赞量:0

收藏量:0