likes
comments
collection
share

关于 webpack,你了解多少呢?

作者站长头像
站长
· 阅读数 76

什么是webpack?为什么要使用它?

首先,让我们想象一下没有 webpack 的世界。

假设你正在开发一个 JavaScript 项目,你可能有很多 .js 文件,每个文件都执行不同的任务。

当你想在浏览器中运行你的代码时,你需要在 HTML 文件中逐一通过 script 标签引入所有的 .js 文件。但是这样做有几个问题:

1、文件的加载顺序很重要,因为一些文件可能依赖于其他文件。你需要手动管理这些依赖关系,这可能会变得非常复杂和容易出错。

2、每一个 script 标签都会导致一个 HTTP 请求。如果你有很多 .js 文件,那么就会有很多 HTTP 请求,这会影响页面的加载速度。

这就是 webpack 发挥作用的地方。

webpack 是一个模块打包器。在 webpack 的世界中,每个文件(不仅仅是 JavaScript 文件,还可以是 CSS、图片或其他任何类型的文件)都被视为一个模块。

每个模块都可以导入(import)其他模块,并导出(export)自己的功能供其他模块使用。这样,你就可以非常容易地管理模块之间的依赖关系。

当你运行 webpack 时,它会从一个或多个入口文件开始,找出所有的依赖模块,并将它们打包到一个或多个 bundle 中。

这个 bundle 是一个 JavaScript 文件,你可以在 HTML 文件中通过一个 script 标签引入它。这样,你就不需要逐一引入所有的 .js 文件了,而且由于所有的代码都在一个文件中,所以也不需要担心加载顺序的问题。

但是,webpack 的功能远不止于此。除了处理 JavaScript 文件,webpack 还可以通过所谓的加载器(loader)处理其他类型的文件。

例如,你可以使用 css-loader 和 style-loader 来处理 CSS 文件,这样你就可以在 JavaScript 文件中直接导入 CSS 文件。处理过程中,webpack 会将 CSS 代码转换为 JavaScript,然后将其插入到 HTML 页面中。

这意味着你可以在 JavaScript 中管理你的 CSS 代码。

webpack的工作原理

假设我们有一个简单的项目,结构如下:

/my-app
|-- index.html
|-- app.js
|-- content.js

其中,app.js 是我们的入口文件,它依赖于 content.js

// content.js
export default 'Hello, world!';

// app.js
import content from './content.js';
document.write(content);

index.html 是一个简单的 HTML 文件,它引入了 app.js

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
    <script src="app.js"></script>
</body>
</html>

现在,我们希望使用 webpack 来处理这个项目。首先,我们需要创建一个 webpack 的配置文件,通常叫做 webpack.config.js

// webpack.config.js
module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  }
};

这个配置文件告诉 webpack,我们的入口文件是 app.js,我们希望 webpack 把打包后的代码输出到 bundle.js

插一句,我们先得明白一个概念:chunk!

"chunk" 是一个中心概念。它可以被理解为一个代码块或者一个模块组,包含了一系列相互依赖的模块。

当我们运行 webpack 时,以下事情将会发生:

  1. 解析入口文件:Webpack 会读取 app.js,看看里面都做了些什么。
  2. 构建依赖图:Webpack 发现 app.js 导入了 content.js,于是它会去读取 content.js。这样,webpack 就知道了 app.js 依赖于 content.js。 等于找出其中的 import 或 require 语句,然后去加载这些被依赖的模块,构建出一个模块依赖图
  3. 生成 Chunk:模块依赖图分解成多个 chunk。每个 chunk 包含了一组相互依赖的模块。在这个过程中,Webpack 会尽可能地将公共的依赖模块分配到同一个 chunk 中,以便进行代码复用。
  4. 生成 Bundle:最后,Webpack 会将每个 Chunk 转换成一个或者多个 JavaScript 文件(在这个例子中,就是 bundle.js)。这个文件就是我们在 HTML 中需要引入的文件。

现在,我们只需要修改 index.html,将 script 标签的 src 属性改为 bundle.js

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
    <script src="bundle.js"></script>
</body>
</html>

这样,我们就完成了 webpack 的基本使用。你可以看到,通过 webpack,我们可以方便地管理和打包我们的代码。

加载器 Loaders

为什么这么重要呢?因为在一个现代的 web 项目中,我们并不只是处理 JavaScript。我们还需要处理样式(CSS, SCSS, Less等),图片,字体等各种类型的资源。

webpack 默认只能理解Javascript和JSON文件,如果项目中只有这两种文件,那就可以不使用任何加载器,不过在web项目中,这几乎是不可能的。

加载器的主要作用是帮助 Webpack 处理和转换特定类型的文件。

例如,我们通常会在 JavaScript 文件中导入 CSS 文件。但是,浏览器并不能理解这样的语法。因此,我们需要使用加载器来处理这些 CSS 文件,将它们转换成浏览器可以理解的 JavaScript 代码。

同样,如果我们想要使用较新的 JavaScript 语法(如 ES6, ES7),但是又想要保证我们的代码能在老版本的浏览器上运行,我们就需要使用 Babel 这样的工具来转换我们的代码。在这种情况下,我们就可以使用 babel-loader

简单来说,加载器让我们可以在 JavaScript 中引入任何类型的文件,并将这些文件转换成浏览器可以理解的格式。

👇🏻 下面是一些常常会用到的加载器:

1、babel-loader:Babel 是一个 JavaScript 编译器,可以将 ES6 或者更高版本的 JavaScript 代码转化为 ES5 代码,以保证在旧版浏览器中也能正常运行。

2、css-loader:用于处理 .css 文件,让你可以在 JavaScript 中 import CSS 文件。

3、style-loader :用于将 CSS 添加到 DOM 中,将样式应用到你的元素。

4、url-loaderfile-loader:用于处理文件,如图片和字体。这两个加载器的作用是将你的文件移动到输出目录,并返回最终路径,你可以在你的代码中直接使用这个路径。

5、sass-loader:用于处理 .scss 文件,让你可以在 JavaScript 中 import SCSS 文件。

6、vue-loader:用于处理 .vue 文件,让你可以在 Vue 项目中使用单文件组件。

7、ts-loader:用于处理 .ts.tsx 文件,让你可以在项目中使用 TypeScript。

这里你可能会有一些疑问:为什么我们既要用到 css-loader 也要用到 style-loader呢?

  1. css-loader 使你能够使用类似 import './style.css' 的方式导入 CSS 文件,style-loader 会将 import 进来的样式添加到 DOM 中,使样式生效。这两个都是必要的,前者让 webpack 能够识别 CSS 文件,后者则将 CSS 应用到页面中。

插件 Plugins

插件的主要作用是在 Webpack 的构建过程中执行特定的任务。这些任务可能包括清理构建目录、压缩代码、拷贝文件、注入环境变量等。

例如,当我们每次构建项目时,我们可能希望先清理掉旧的构建文件,以确保构建目录的干净。在这种情况下,我们可以使用 clean-webpack-plugin

又例如,我们可能希望将我们的代码压缩,以减小文件大小,提高加载速度。在这种情况下,我们可以使用 uglifyjs-webpack-plugin

👇🏻 常用的插件如下:

  1. HtmlWebpackPlugin:基于一个模板,生成一个包含了输出 bundle 的新 HTML 文件。
  2. CleanWebpackPlugin:每次构建前清理 /dist 文件夹。
  3. MiniCssExtractPlugin:将 CSS 代码从 JavaScript bundle 中抽取出来,生成单独的 CSS 文件。
  4. UglifyJsPlugin:压缩 JavaScript 代码。
  5. DefinePlugin:允许创建一个在编译时可以配置的全局常量。
  6. HotModuleReplacementPlugin:开启模块热替换功能,主要用于开发环境。
  7. OptimizeCssAssetsWebpackPlugin:压缩和优化 CSS 资源。

总结

最后我们通过几个问题,来看看自己到底明白没有 webpack 是什么?

Q:请解释一下 webpack 是什么以及它的主要功能。

Webpack 是一个模块打包工具,主要用于前端资源的模块化管理和打包。它能够把各种资源,如 JavaScript、CSS、图片等,视为模块,通过加载器和插件,实现资源的编译、转换和打包。

Q:什么是 Loader 和 Plugin?它们的区别是什么?

Loader 是用来告诉 webpack 如何转换处理某一类型的文件,并将其转换成有效的模块,以供应用程序使用。比如 babel-loader 用于将 ES6 代码转换为浏览器可识别的 ES5 代码,css-loader 用于处理 CSS 文件。

Plugin 是用来扩展 webpack 功能的,它们会在整个构建流程中的特定时机,执行广泛的任务。比如 HtmlWebpackPlugin 会在构建完成后,自动生成一个 HTML 文件并引入打包后的所有资源。

简单来说,Loader 在模块加载时被调用,而 Plugin 在整个编译生命周期的特定时机被调用。

Q:什么是 Tree Shaking 和 Code Splitting?

Tree Shaking 是一种通过消除没有用到的代码,来减少最终打包文件大小的优化手段。它依赖于 ES6 模块系统的静态导入特性。

Code Splitting 是指将代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。Code Splitting 可以更有效地利用浏览器的缓存机制,减少用户首次访问的加载时间。

Q:如何配置一个基本的 webpack 配置文件?

一个基本的 webpack 配置文件包括入口(entry),输出(output),加载器(loaders),插件(plugins)。

其中,入口定义了 webpack 开始构建内部依赖图的起点,输出则定义了 webpack 如何输出、以及在哪里输出构建结果。加载器允许 webpack 处理那些非 JavaScript 的资源,而插件则用于执行范围更广的任务。

Q:如何优化 webpack 的构建速度和打包结果?

优化构建速度可以采用多进程/多实例构建,使用 DllPlugin 进行分包,减少文件搜索范围等手段。

优化打包结果可以通过 Tree Shaking、Code Splitting、利用缓存(例如通过 NamedChunksPluginNamedModulesPlugin)、压缩代码等方式实现。

转载自:https://juejin.cn/post/7234059013272977465
评论
请登录