什么是 Webpack?【Webpack Book 翻译】

原文连接: https://survivejs.com/webpack...
翻译计划: https://segmentfault.com/a/11...

涉及到的未翻译单词javascript

  • input 输入
  • output 输出
  • entry 入口文件
  • bundle 包(打包结果)

Webpack 是模块打包器。它能够在打包的同时使用任务运行器。然而,因为社区开发的 webpack 插件,打包器和任务运行器之间的界限变得模糊。有时,这些插件甚至独立于 webpack 使用,例如清理构建目录或部署构建使用的插件。
(译者注:grunt 之类的任务运行器,就是自动帮你走一次如“组合两个 js 文件--压缩 js--压缩 css”这样流程的工具)css

Webpack 也能够在其余环境中的使用,例如 Ruby on Rails。尽管它的名字带有 web,但 webpack 并不只限于 web。它也能够打包其余东西,这点在 Build Targets 章节中会提到。java

T> 若是你想更详细地了解构建工具及其历史,请查看附录 Comparison of Build Toolsnode

Webpack 基于模块

使用 webpack 构建工程,至少包括 inputoutput。打包处理从用户定义的 entry 开始。entry 自己就是模块,它能够经过 import 指向其余模块。react

当你使用 webpack 打包项目时,它会遍历 import,构建项目的依赖关系图,而后根据配置文件中的设定生成 output。你还能够定义分割点,以在项目代码内拆分出单独的 bundle(包)。webpack

Webpack 支持开箱即用的 ES2015,CommonJS 和 AMD 模块标准。loader 机制也适用于 CSS,经过 css-loader 在 css 文件中使用 @importurl()。你还能够找到某些实现特定功能的插件,例如压缩,国际化,HMR等。git

T> 依赖图是描述节点如何相互关联的有向图。这个图是经过文件之间的引用(requireimport)构建的。Webpack 会在不执行资源的状况下静态遍历这些资源,并生成建立 bundle 所需的依赖图。github

Webpack 的执行流程

Webpack's execution process

Webpack 从 entry 开始运行。entry 一般是 JavaScript 模块,webpack 从这里开始遍历处理。在此过程当中,webpack 根据 loader 配置转换每一个匹配到的模块。web

模块解析

Entry 自己就是一个模块。当 webpack 遇到 entry,webpack 会在文件系统匹配相关文件。除了 node_modules 以外,webpack 还能够对特定目录执行查找。也能够调整 webpack 匹配文件扩展名的方式,也能够为目录定义 aliases(别名)。这方面在 Consuming Packages 章节有更详细的介绍。npm

若是 webpack 正确解析文件,对应 loader 会处理匹配的文件,不一样的 loader 对模块内容应用的转换各不相同。若是解析失败,webpack 会报运行时错误。

loader 能够经过多种方式匹配待处理文件,如文件类型和文件的位置。 Webpack 甚至可让你按 import 位置分类,不一样位置 import 的文件采用不一样的转换方法。

对 webpack loader 执行相同的解析过程。 你能够在选择 loader 时使用相同的逻辑。因为这个缘由,Loader 已经解析了本身的配置。若是 webpack 查找 loader 失败,则会引起运行时错误。

T> Webpack 的解释底层依赖于 enhanced-resolve 包。

Webpack 能够解析任何类型的文件

Webpack 将在构造依赖图时解析它遇到的每一个模块。若是 entry 包含依赖项,则将针对每一个依赖项递归执行该过程,直到遍历完成为止。 Webpack 能够针对任何文件类型执行此过程,这与 Babel 或 Sass 编译器等专用工具不一样。

Webpack 能够控制对不一样资源的处理方式。例如,能够把资源内联到 JavaScript 包以免过多的网络请求(译者注:例如图片转 base64)。Webpack 还容许你使用 CSS 模块等技术将样式与组件结合,并避免标准 CSS 样式问题。这种灵活性是 webpack 价值的体现。

尽管 webpack 主要用于打包 JavaScript,但它能够捕获图像或字体等资源,并为它们抽取为单独的文件。Entry 只是打包处理的起点。 webpack 生成的内容彻底取决于你配置它的方式。

处理流程

Webpack 会下到上、从右到左地(styleLoader(cssLoader('./main.css')))处理匹配成功的加载器,模块会依次经过 loader 的处理。最后,你将得到 webpack 输出的包。Loader Definitions 章节详细介绍了该主题。

若是全部 loader 都成功运行,则 webpack 会在最后一个包中包含源。 Plugins 能够在打包过程的不一样阶段拦截运行时事件

虽然 loader 能够作不少事情,但它们不能为高级任务提供足够的动力。Plugins 能够拦截 webpack 提供的运行时事件。一个很好的例子是由 MiniCssExtractPlugin 执行的包提取,当与 loader 一块儿使用时,从包中提取 CSS 文件并将其提取到单独的文件中。若是没有这一步,CSS 将在生成的 JavaScript 中内联,由于 webpack 默认将全部代码视为 JavaScript。CSS 提取将在 Separating CSS 一章中讨论。

完成

每一个模块都通过处理以后,webpack 生成 output。output 包括一个引导脚本,其中包含一个指引浏览器执行该项目的 manifest 文件。能够将 manifest 提取到单独的文件中,本书后面会有相关介绍。output 会根据你使用的 build target 而有所不一样(Web 不是惟一选择)。

这并非打包过程的所有内容。例如,你能够作代码拆分,webpack 会在程序运行到所需功能时才加载的单独包。这个话题会在 Code Splitting 章节中讨论。

配置驱动的 Webpack

webpack 的核心依赖于配置。如下是根据官方 webpack 教程改编的配置示例证实:

webpack.config.js

const webpack = require("webpack");

module.exports = {
  // Where to start bundling
  entry: {
    app: "./entry.js",
  },

  // Where to output
  output: {
    // Output to the same directory
    path: __dirname,

    // Capture name from the entry using a pattern
    filename: "[name].js",
  },

  // How to resolve encountered imports
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.js$/,
        use: "babel-loader",
        exclude: /node_modules/,
      },
    ],
  },

  // What extra processing to perform
  plugins: [
    new webpack.DefinePlugin({ ... }),
  ],

  // Adjust module resolution algorithm
  resolve: {
    alias: { ... },
  },
};

Webpack 的配置模型有时候会让人感受雾里看花,由于配置文件太庞大,属性太多。除非你理解每个属性的意义,不然很难理解 webpack 在作什么。让你彻底理解 webpack 配置的使用,是本书存在的主要目的之一。

资源哈希编码

使用 webpack 能够为每一个包的名称注入一个哈希值(例如,app.d587bbd6.js),以便在版本更新后使客户端上旧版本的包无效(从新下载)。包(bundle)拆分可让客户端在理想状况下仅从新加载一小部分数据。

热模块更换(HMR)

你可能使用过 LiveReloadBrowserSync 等工具。这些工具会在你进行更改时自动刷新浏览器。热模块更换(HMR)则更先进,在使用 React 的状况下,应用程序能够在不强制刷新页面的状况下更新应用。虽然这听起来没什么特别,但它能够在实践中大有不一样。

HMR 不是webpack独有的功能,经过 livereactload 也能够在 Browserify 中使用 HMR。

代码拆分

Webpack 能够以多种方式拆分代码。你甚至能够在应用程序执行时动态加载代码。由于依赖能够根据须要即时加载,因此延迟加载特别适用于体积庞大的应用。

即便是小型应用也能够得益于代码拆分,由于它容许用户更快地得到可用的东西。毕竟,性能是评价一个应用的重要标准,了解这项技术是值得的。

结论

Webpack 学习曲线比较陡峭。可是有了它,项目的长期维护能够节省多少时间和精力,因此这是一个很是值得学习的工具。为了更好地了解 Webpack 与其余工具的比较,请查看官网上与其余工具的比较

Webpack 不是万能的。但它确实很好地解决了打包问题。在开发过程当中须要担忧的问题又少了一件。活用 package.json 和 webpack,走遍天下都不怕。

总结一下:

  • Webpack 是模块打包器,但你也可使用它运行任务(译者注:也就是顺序运行一系列操做)。
  • Webpack 底层基于依赖图。Webpack 遍历源文件构建依赖图,并以依赖图和配置为基础生成 bundle。
  • Webpack 依赖于 loaderplugin。loader 在模块级别上运行,而 plugin 依赖于 webpack 提供的钩子,而且能够很好地访问其执行过程。
  • Webpack 的配置描述了如何转换“依赖图”中的资源以及它应该生成什么样的输出。若是要使用代码拆分等功能,则能够将拆分指令写在源代码中。
  • Webpack 如此受人喜好的缘由之一是热模块更换(HMR)。这个功能能够不刷新整页而更新应用代码,开发体验极好。
  • Webpack 能够为文件名生成哈希值,在内容更改时,能够做废浏览器缓存中上个版本的包。

在本书的下一部分中,你将学习使用 webpack 构建开发配置,同时了解更多相关概念。

T> 若是你对 webpack 仍有疑问或者不明白咱们为何须要一个打包器,请阅读Why would I use a Webpack?

相关文章
相关标签/搜索