四、应用编程接口、插件和加载器

应用编程接口 ( 应用编程接口)通常用于远程程序之间的接口,例如当公司通过移动应用提供对其网站功能的部分访问,作为集成系统的一部分时。

Webpack 寻求编译和优化本地化代码,因此了解本地化代码和外部 API 之间的区别对于操作软件至关重要。

插件和加载器是相似的。加载器本质上指导 Webpack 如何处理更不寻常的编程语言和捆绑中涉及的特定任务。加载器通常由用户社区开发,而不是由内部的 Webpack 开发人员开发。另一方面,插件提供了加载器目前不提供的一些过程,因此在操作上比加载器更通用。在本章的过程中,将对每个特性进行简明的解释,并提供详细的示例。

Webpack 5 为开发人员提供了丰富的插件界面。Webpack 中的大多数功能都使用这个插件接口,使得 Webpack 的使用非常灵活。

本章将探讨插件、加载器和应用编程接口,以及每一个的显著性,以及每一个特性如何在网络包的运行中发挥作用。

本章讨论的主题如下:

  • 装载机
  • 蜜蜂
  • 插件

装载机

加载器是 Webpack 的基础,其中许多支持更大的功能,尤其是使用非原生 ECMAScripts 的脚本和框架,如 JavaScript 和 JSON。

本章旨在向您概述可用的装载机以及您可能需要购买的一些装载机。当使用特定于您的项目的显著或唯一代码时,您应该搜索 Webpack 在线注册表以确保代码可以被传输。

特别是,本节将讨论以下加载程序:

  • cache-loader
  • coffee-loader
  • coffee-redux-loader
  • worker-loader
  • cover.js
  • i18n-loader
  • imports-loader
  • polymer-webpack-loader
  • script-loader
  • source-map-loader
  • less-loader

我们将在适当的地方讨论并给出每个加载器的例子,尽管有些可能不需要真正的阐述。让我们从cache-loader开始。

缓存加载程序

缓存是我们在上一章中提到的。cache-loader允许从加载程序创建缓存。我们可以按如下方式设置:

  1. 首先通过命令行界面 ( 命令行界面安装加载程序,如下所示:
npm install --save-dev cache-loader

请注意,在我们的配置中会执行其他加载器(参见下面的代码),并且会对加载器以cache-loader开头的任何结果输出进行缓存。默认情况下,这将在项目文件夹中进行,但也可以配置为在数据库的缓存中进行。

  1. 要进行配置,请使用webpack.config.js:
module.exports = {
 module: {
  rules: [
  {
    test: /\.ext$/,
    use: ['cache-loader', 'babel-loader'],
    include: path.resolve('src'),
   },
  ],
 },
};

Note that where cache-loader is placed in the configuration is where it should always be placed, ahead of other loaders.

解释cache-loader的安装和使用。我们将以同样的方式,从worker-loader开始,来看其他几台装载机。因为它需要首先声明,所以我们应该首先讨论它,即使它总是在链或序列中与其他加载器一起使用。

工人装载机

worker-loader本质上给了开发者一个让程序在后台处理大型计算任务的解决方案。要启动并运行加载程序,我们将采取以下步骤:

  1. 首先,使用命令行安装worker-loader:
npm install worker-loader --save-dev

或者,有一种从App.js文件导入worker-loader的内联方式。在这个存在于任何 Webpack 项目目录中的文件中,进行以下修改(如果尚未完成):

import Worker from 'worker-loader!./Worker.js';
  1. 导入加载器后,使用webpack.config.js进行配置:
{
 module: {
  rules: [
  {
   test: /\.worker\.js$/,
   use: { 
      loader: 'worker-loader' 
      }
    }
   ]
  }
 }

use指允许进入装载机所需的配置。

  1. App.js中写入以下代码,以允许该文件作为加载程序的导出位置:
import Worker from './file.worker.js';
const worker = new Worker();
worker.postMessage({ a: 1 });
worker.onmessage = function (event) {};
worker.addEventListener("message", function (event) {});

前面的代码还添加了一个event监听器,以便稍后在开发控制台中进行测试。

  1. 最后,通过您喜欢的方法运行 Webpack 来查看结果:
npm run build

如果您选择了该方法,您应该会看到从App.js安装和导入的worker-loader。这可以在控制台窗口或通过查看页面源来观察。

这为您提供了利用worker-loader的两个选择,或者通过命令行实用程序,或者通过App.js文件的配置。接下来,我们将讨论coffee-loader

咖啡装载机

CoffeeScript 是 JavaScript 的简化形式,但它并不完全是 JavaScript,因此必须使用加载器在 Webpack 中使用它。

让我们通过以下步骤来使用coffee-loader:

  1. 首先安装coffee-loader。要安装加载程序,请使用以下命令行:
npm install --save-dev coffee-loader
  1. 为了测试和使用literate键,请确保您使用的是装载机的推荐配置。要允许测试,加载coffee-loader并将literate键设置为trueliterate键将确保编译器解释加载程序的用法:
module.exports = {
    module: {
      rules: [
       {
          test: /\.coffee.md$/,
          use: [{
          loader: 'coffee-loader',
          options: {
            literate: true
         }
      }]
    }]
  }
}

前面示例中的代码显示了如何使用加载器以及新规则的设置。

  1. 如果您需要,我们将向您展示如何安装coffee-reduxRedux 是一个用于管理 JavaScript 应用状态的开源库。常用于ReactAngular等库。要安装它,请键入以下命令:
npm i -D coffee-redux-loader

前面的例子不仅可以帮助您理解在包中安装和使用 CoffeeScript 的过程,还可以帮助您理解这个过程对于这里没有提到的加载器是如何工作的,因为它们的工作方式基本相同。

但是,您会看到,设置命令行的速记安装和开发模式已经被使用了——分别是i-D。在大多数情况下,这是可行的,尽管您可能会发现,当您的命令行实用程序和您正在使用的 Webpack 版本之间存在兼容性问题时,现在会有一个响应。

这样做可以节省您的时间,但是如果有疑问,请使用本指南中演示的详细命令行约定。

现在,让我们继续讨论coverjs,它的工作原理有点不同。

覆盖

coverjs允许您的代码被检测。这实质上意味着它允许根据性能来度量或监控您的代码。

coverjs装载机不需要与mocha-loader组合,因为是独立的。reportHtml功能将附加到身体的输出。

在下面的例子中,webpackOptions.js是代码的主题。在第一组花括号({)中是与模块导出过程相关的选项。在双括号([{)中是绑定coverjs加载器和test:""语句(表示将测试每个文件)的代码:

webpack - dev - server "mocha!./cover-my-client-tests.js"--options webpackOptions.js
// webpackOptions.js
module.exports = {
    output: "bundle.js",
    publicPrefix: "/",
    debug: true,
    includeFilenames: true,
    watch: true,
    postLoaders: [{
       test: "",
       exclude: [
         "node_modules.chai",
         "node_modules.coverjs-loader",
         "node_modules.webpack.buildin"
    ],
    loader: "coverjs-loader"
 }]
}
// cover-my-client-tests.js
require("./my-client-tests");
after(function() {
   require("cover-loader").reportHtml();
});

正如您所看到的,这个特定的加载器通过本地文件设置其选项。对此的修改将与前一章中讨论的配置具有相同的效果。这应该是您在应用中启动并运行coverjs所需的全部内容。接下来是一个更复杂的话题,涉及国际语言的使用。

i18n 装载机

i18n-loader处理国际化(i18n),这是准备应用以使其支持本地语言和文化设置的过程。让我们通过以下步骤进行设置:

  1. 从命令行安装开始:
npm install i18n-loader
  1. 现在,让我们从使用 CSS 开始。我们将设置我们的样式表用于i18n 这是用我们通常的项目样式表css/styles.css完成的。如果您正在导入另一个样式表,这很好;只需在那里进行更改:
. / colors.json {
        "red": "red",
        "green": "green",
        "blue": "blue"
    }
    . / de - de.colors.json {
        "red": "rot",
        "green": "green"
    }

可以调用加载器,假设我们的区域设置是de-de-berlin(为了这个例子,是德语和区域设置)。

  1. 接下来,我们将使用index.js文件在i18n设置中本地化代码的配色方案:
var locale = require("i18n!./colors.json");

现在,等待状态就绪。这对于所有语言环境只需要一次,因为相同语言的所有语言环境被合并到一个模块块中:

locale(function() {
 console.log(locale.red); // prints red
 console.log(locale.blue); // prints blue
});

这通常都是在同一个文件中完成的。前面的代码将在console.log函数的locale变量中添加一个子节点,这将有助于测试。

  1. 现在,用webpack.config.js配置加载器,并使用可用的相关选项。由于这个加载器也有一些选项,如果您想加载一次然后同步使用它们,您应该告诉加载器您所有的语言环境:
{
    "i18n": {
        "locales": [
            "de",
            "de-de",
            "fr"
        ],
        // "bundleTogether": false
    }
}

请注意前面代码中的// "bundleTogether": false语句——这可以取消注释并设置为禁用区域设置绑定。

还有其他选择。下面的代码按区域选择正确的文件:

require("i18n/choose!./file.js"); 

但是,这不会合并对象。在下面的代码中,第一行将连接所有合适的区域设置,第二行将合并结果对象:

require("i18n/concat!./file.js"); 
require("i18n/merge!./file.js"); 

结果,在编译时执行前面代码块中的./file.js:

require("i18n!./file.json") ==
   require("i18n/merge!json!./file.json")

前面的代码块只是加强了正则表达式。它确保任何一个require语句都将加载相同的文件。

Don't forget to polyfill require if you want to use it in Node.js. See the Further reading section at the end of this chapter for the relevant Webpack documentation.

前面的代码块只是调整了您的项目,使其与讲德语的受众的德语区域兼容。接下来是imports-loader

进口-装载机

imports-loader允许您使用依赖于特定全局变量的模块。这对于可能依赖全局变量的第三方模块非常有用。imports-loader可以添加必要的require呼叫,使它们与 Webpack 一起工作。让我们通过以下步骤进行设置:

  1. 要在命令行中安装加载程序,请使用以下语句:
npm install imports-loader

假设您有example.js文件,这个加载器允许您使用 jQuery 将导入的脚本附加到图像标签,如下所示:

$("img").doSomeAwesomeJqueryPluginStuff();
  1. 通过配置imports-loader,可以将$变量注入到模块中,如下所示:
require("imports-loader?$=jquery!./example.js");

这只是在example.js前面加上var $ = require("jquery");。例如,如果您正在优化代码以在本地运行库,这可能会很有用。

使用polymer-loader类似地优化您的代码或自动化您的过程,以允许转换。这是我们讨论的下一个话题。

聚合物装载机

polymer-loader用于将 HTML 文件转换为 JavaScript 文件。要配置加载器,请使用以下带有webpack.config.js的代码:

{
  test: /\.html$/,
  include: Condition(s) (optional),
  exclude: Condition(s) (optional),
  options: {
    ignoreLinks: Condition(s) (optional),
    ignorePathReWrite: Condition(s) (optional),
    processStyleLinks: Boolean (optional),
    htmlLoader: Object (optional)
  },
  loader: 'polymer-webpack-loader'
},

polymer-webpack-loader短语允许开发人员在单个文档中将 HTML、CSS 和 JavaScript 代码作为聚合元素一起编写——例如,同时仍然能够使用完整的 Webpack 系统,包括模块捆绑和代码拆分。

脚本加载程序

script-loader本质上允许在单个实例中加载 JavaScript。这适用于整个项目的全局。让我们通过以下步骤进行设置:

  1. 要安装script-loader,请在命令行中键入以下内容:
npm install --save-dev script-loader

Note that this doesn't work in Node.js.

  1. 使用webpack.config.js配置网络包,网络包将从'script.exec.js';.导出exec:
module.exports = {
    module: {
        rules: [{
            test: /\.exec\.js$/,
            use: ['script-loader']
        }]
    }
}

还有一种内联方式,如下所示:

import exec from 'script-loader!./script.js';

这应该是你在你的网络包应用中使用script-loader所需要的全部。接下来是source-map-loader

源地图加载器

source-map-loader从项目中的所有 JavaScript 条目中提取现有的源地图。这包括内联源映射和外部加载的源映射。所有源地图数据都是根据所选的源地图样式进行处理的,您可以使用webpack.config.js中的devtool选项进行指定。以下代码显示了该配置:

module.exports = {
     module: {
     rules: [
     {
       test: /\.script\.js$/,
       use: [
   {
     loader: 'script-loader',
     options: {
           sourceMap: true,
              },
   },
        ]
    }
         ]
    }
 }

当使用具有源映射的第三方库时,这个加载器非常有用。如果没有提取并处理到包的源地图中,浏览器可能会错误地解释源地图数据。该加载器允许跨库和框架维护源地图数据的连续性,以确保易于调试。

加载器将从任何 JavaScript 文件中提取,包括node_modules目录中的那些文件。设置includeexclude规则条件时应注意优化捆绑性能。

少装载机

less-loader 加载 LESS (一种 CSS 脚本。您应该使用命令行以通常的方式安装它,例如,npm i less-loader。对于不熟悉的人来说,LESS 是一种更简洁的 CSS 形式,有助于向后兼容。

您应该使用css-loaderstyle-loader链接less-loader,以立即将所有样式应用到文档。要进行配置,请使用以下示例代码,使用webpack.config.js文件:

module.exports = {
    module: {
        rules: [{
            test: /\.less$/,
            use: [{
                    loader: 'style-loader', // creates style nodes 
                                               from JS strings

                },
                {
                    loader: 'css-loader', // translates CSS 
                                              into  CommonJS
                },
                {
                    loader: 'less-loader', // compiles Less to CSS
                },
            ],
        }, 
      ],
    },
 };

您可以通过加载器选项将任何不太特定的选项传递给less-loader。由于这些选项是作为程序的一部分传递给 LESS 的,因此需要在camelCase中传递; webpack.config.js 中的以下例子说明了这是如何做到的:

module.exports = {
    module: {
        rules: [{
            test: /\.less$/,
            use: [{
                    loader: 'style-loader',
                },
                {
                    loader: 'css-loader',
                },
                {
                    loader: 'less-loader',
                    options: {
                        strictMath: true,
                        noIeCompat: true,
                    },
                },
            ],
         },
       ],
    },
 };

请注意,LESS 不会将所有选项单独映射到camelCase。建议您检查相关的可执行文件并搜索dash-case选项。

在生产模式下,通常建议您使用MiniCssExtractPlugin将样式表提取到专用文件中。这样,您的风格就不依赖于 JavaScript 了(稍后将详细介绍)。

在本节中,我们深入讨论了加载器,并详细研究了一些更有用的加载器。大多数加载器遵循相同的安装和配置逻辑,由 Webpack 社区构建,而不是由 Webpack 本身构建。我们将在本书的最后一章更详细地讨论定制加载器。

这里有太多其他加载器需要提及,但这为您以各种富有想象力的方式使用它们提供了非常坚实的基础。与加载程序倾向于处理的非原生脚本相关的事情是对 Webpack 使用 API。我们将在下一节对此进行研究。

蜜蜂

API 对于充分利用网络包至关重要。简单来说,应用和网站之间的通信需要 API。当涉及到像 Webpack 这样的 JavaScript 捆绑器时,这包括数据库和后端连接。

在使用 JavaScript 时,有大量的 API 可用,但是我们不能在这里一一列举;然而,在使用 Webpack 编程时,有一些更有用的通用但也很复杂的 API 经常被用作工具。

这些工具是特定于 Webpack 的,允许在 Webpack 中使用广泛或通用的功能,而不仅仅是简单地访问外部代码。这些工具中最值得注意的是 Babel 和 Node.js。因此,让我们以这些工具为例,在接下来的小节中学习它们的用法,从 Babel 开始。

巴别塔及其装载机制造商

如果您不知道,Babel 是一个工具链,它主要将 ECMAScript 2015 和前面的代码转换为 JavaScript 的回归版本,该版本与当前和旧版本的浏览器或环境兼容。作为开发人员,巴贝尔可以为您做的主要事情如下:

  • 转换语法
  • 使用@babel/polyfill多填充目标环境中缺少的特征
  • 执行源代码转换,称为代码模块

Webpack 为巴别尔接口使用了一个应用编程接口。如果您尝试使用命令行安装它,您应该会收到以下消息:

The Node.js API for babel has been moved to babel-core.

如果您收到此消息,这意味着您已经安装了巴贝尔安装的npm包,并且它正在使用 Webpack 配置文件中加载程序的缩写(从 Webpack 版本 2 及更高版本开始,该缩写不再有效)。

webpack.config.js中,您可能会看到以下脚本:

  {
    test: /\.m?js$/,
    loader: 'babel',
  }

安装 Babel 的结果是,Webpack 试图加载babel包,而不是babel-loader

为了解决这个问题,应该安装npm包巴别塔,因为它在巴别塔版本 6 中被否决了。如果你使用的是巴贝尔版本 6,那么你应该安装@babel/cli或者@babel/core。如果您的一个依赖项正在安装 Babel,并且您不能自己卸载它,请在webpack.config.js中使用加载程序的完整名称:

  {
    test: /\.m?js$/,
    loader: 'babel-loader',
  }

到目前为止,您所遵循的示例应该对您使用巴别塔有很大帮助,但是巴别塔的一个关键用途是定制的加载器。这是本书最后一章中更广泛涉及的主题,但是我们现在将讨论巴别尔如何使用定制的加载器,尤其是因为您可能不会使用自己定制的加载器。

babel-loader公开了一个loader-builder实用程序,允许用户为它处理的每个文件添加巴贝尔配置的自定义处理。

.custom短语接受一个回调,这个回调将被加载器的巴别塔实例调用。这是为了使工具能够确保它使用与加载器本身相同的@babel/core实例。

在您想要自定义但实际上没有文件可以调用.custom的情况下,您也可以通过指向导出您的自定义回调函数的文件的字符串来传递customize选项。

可能学习这是如何工作的最好方法是通过一个实际的例子;让我们在下面的练习中完成一个。

这个例子的目的是演示如何使用babel-loader来构建定制的加载器。

这个例子首先使用一个自定义文件名。这可以是你想要的任何东西,但是为了这个练习,我们选择的名字是./my-custom-loader.js。您可以从该位置或任何您想要的地方导出:

  1. 首先使用./my-custom-loader.js中的以下代码创建一个自定义文件:
module.exports = require("babel-loader").custom(babel => {
 function myPlugin() {
 return {
 visitor: {},
 };
 }

在前面的代码块中,我们可以看到一个require语句。这使用babel-loader,我们将需要它来创建自定义加载器。

  1. 现在,我们需要配置我们的项目来设置加载器的传递,如图所示:
return {
    customOptions({
        opt1,
        opt2,
        ...loader
    }) {
        return {
            custom: {
                opt1,
                opt2
            },
            loader,
        };
    },

注意custom:是指拉出加载程序可能有的任何自定义选项。另外,请注意两个选项后的loader参考。这将把两个custom选项移除后的选项传递回去。

  1. 然后,我们传递巴别塔的PartialConfig对象,将正常配置设置为return cfg.options:
config(cfg) {
    if (cfg.hasFilesystemConfig()) {
        return cfg.options;
    }

    return {
        ...cfg.options,
        plugins: [
            ...(cfg.options.plugins || []),
            testPlugin,
        ],
    };
},

在前面的代码中,在testPlugin语句的地方,我们可以看到包含了一个自定义插件,它将作为一个选项提供。

  1. 现在,让我们制作占位符文本来测试自定义加载器。前面的代码应该生成如下内容:
result(result) {
return {
    ...result,
    code: result.code + "\n// Generated by this custom loader",
    };
    },
    };
});

此代码块显示自定义加载程序正在生成代码。

  1. 确保您的配置正确无误。请注意,您应该始终将__dirnamecustom-loader替换为您选择的名称。在 Webpack 配置模块中,键入以下内容:
.exports = {
    module: {
        rules: [{
            loader: path.join(__dirname, 'custom-loader.js'),
        }]
    }
};
customOptions(options: Object): {
    custom: Object,
    loader: Object
}

上一个模块向您展示了如何设置和配置customOptions

  1. 给定加载器选项,将自定义选项从babel-loader选项中分离出来:
config(cfg: PartialConfig): Object
  1. 给定巴别塔的PartialConfig对象,返回应该传递给babel.transformoptions对象:
result(result: Result): Result

前面的两个代码块都引用了我们构建的定制文件的内容,在这个例子中是./my-custom-loader.js

请注意,巴贝尔的result对象将允许加载器对其进行额外的调整。

这应该是让自定义加载器与巴贝尔一起工作所需的全部内容。阅读本书关于创作和定制加载器的最后一章,了解更多信息。网络包项目中经常使用的另一个关键应用编程接口是 Node.js 应用编程接口。

节点应用编程接口

当使用自定义开发过程时,Node.js 应用编程接口非常有用。这是因为所有报告和错误处理都是手动完成的。在这种情况下,Webpack 只是处理编译过程。注意stats配置选项在使用 Node.js API 时不会有任何影响。

每当您安装 Webpack 5 时,都会安装此 API 如果你不按顺序阅读这一节,你可以参考第一章。让我们通过以下步骤设置这个应用编程接口:

  1. 首先将webpack模块包含到 Node.js 脚本中。这是使用webpack.config.js文件完成的:
const webpack = require('webpack');

webpack({
  // Configuration Object
}, (some, stats) => { // Stats Object
  if (some || stats.hasErrors()) {
    // Handle errors here
  }
  // Done processing
});

在前面的例子中,提供了一个回调函数——webpack()——运行编译器。代码提出了几个条件。这只是一个例子,当然应该用你的代码来代替。此外,some术语同样应该替换为与您的项目相关联的正确对象名称。

注意some对象不会包含编译错误,只包含具体与 Webpack 相关的问题,比如配置错误。相反,这些错误是使用stats.hasErrors()功能处理的。

  1. 接下来,确保编译器实例的传递是正确的。

如果 Webpack 函数没有回调,它将返回一个compiler实例。compiler实例可以手动触发webpack()功能,或者确保它在构建过程中观察变化(使用.run(callback).watch(watchOptions, handler),或者甚至运行构建本身而不需要命令行界面。

compiler实例允许使用子编译器,并将所有捆绑、编写和加载工作委托给注册的插件。

有一个叫做hook的属性,它是compiler实例的一部分。它的目的是在编译器的生命周期中将任何插件注册到任何钩子事件。您可以使用WebpackOptionsDefaulterWebpackOptions Apply实用程序配置该编译器。

构建运行完成后,将执行前面提到的回调函数。任何错误或统计数据的最终记录都是通过这个函数完成的。

The Node.js API will only support a single compilation once. Concurrent watches or builds can corrupt the output bundle.

使用应用编程接口调用运行类似于使用compiler实例。

  1. 我们现在应该使用webpack.config.js运行一个编译:
const webpack = require('webpack');

const compiler = webpack({
 // Configuration Object
});

compiler.run((some, stats) => { // Stats Object
});
  1. 从这里,我们还可以触发watch会话。当webpack()功能检测到变化时,它将再次运行并返回一个watching实例:
watch(watchOptions, callback);
const webpack = require('webpack');

const compiler = webpack({
 // Configuration Object
});

const watching = compiler.watch({
 // Example watchOptions
 aggregateTimeout: 300,
 poll: undefined
}, (some, stats) => { // Stats Object
 // Print watch/build result here...
 console.log(stats);
});

由于如果检测到更改,文件系统的不准确性会触发多次构建,因此对于任何一次修改,前一个代码块中的console.log语句都可能导致多次触发。检查stats.hash可以帮助您查看文件是否有变化。

  1. 以这种方式使用watch方法将返回一个watching实例和一个.close(callback)方法。调用此方法将结束watching会话:
watching.close(() => {
 console.log('Watching Ended.');
});

注意,使用invalidate观察功能将允许手动无效当前编译,而不停止watch过程。这很有用,因为一次只允许运行一次:

watching.invalidate();

由于多个同时编译受到限制,网络包提供了一些叫做MultiCompiler的东西来加速你的项目开发。它是一个模块,允许 Webpack 在单独的编译器中运行多个配置。如果您的options参数是一个数组,Webpack 将应用单独的编译器,并在所有编译器完成其过程后执行任何回调:

var webpack = require('webpack');
webpack([
 { entry: './index1.js', output: { filename: 'bundle1.js' } },
 { entry: './index2.js', output: { filename: 'bundle2.js' } }
], (some, stats) => { // Stats Object
 process.stdout.write(stats.toString() + '\n');
})

前面的代码块向您展示了如何在webpack.config.js中配置您的项目以允许这个过程。

如前所述,试图并行运行这些编译将产生不正确的输出。如果这是偶然发生的,错误管理就会出现。

通常,错误处理包含三种类型的错误——致命的 Webpack 错误(如错误配置)、编译错误(如缺少资产)和编译警告。

下面的代码块向您展示了如何配置您的项目——在本例中,使用webpack.config.js——来处理这些错误:

const webpack = require('webpack');

webpack({
 // Configuration Object
}, (some, stats) => {
 if (some) {
   console.error(some.stack || some);
 if (some.details) {
   console.error(some.details);
 }
 return;
 }
const info = stats.toJson();
if (stats.hasErrors()) {
  console.error(info.errors);
 }
if (stats.hasWarnings()) {
  console.warn(info.warnings);
 }
// Log results...
});

在前面的块中,some元素将这些错误表示为变量。我们可以在控制台日志中看到记录这些错误的各种情况。

我们已经给你上了一堂关于 API 如何与 Webpack 一起工作的速成课,所以如果你活了下来,你现在就是编程技能的铁杆专家了。干得好!

既然我们已经探索了各种各样的加载器和 API(包括 Babel 和 Node.js),现在是时候看一下本章中涉及的最后一个特性——插件了。

插件

插件的目的是做加载程序做不到的事情。加载程序经常帮助运行非 Webpack 原生的代码,插件也是如此;然而,加载器通常是由社区构建的,而插件是由 Webpack 的内部开发人员构建的。

据说插件是网络包的支柱。该软件建立在您在网络包配置中使用的相同插件系统上。

Webpack 有一个丰富的插件接口,Webpack 本身的大部分功能都使用它。以下是本节将详细介绍的可用插件的项目列表。每个名称旁边是插件的简短描述:

  • BabelMinifyWebpackPlugin:用babel-minify缩小
  • CommonsChunkPlugin:提取组块之间共享的公共模块
  • ContextReplacementPlugin:覆盖 require 表达式的推断上下文
  • HotModuleReplacementPlugin:启用热模块更换 ( HMR )(稍后将详细介绍)
  • HtmlWebpackPlugin:轻松创建 HTML 文件,为您的包提供服务
  • LimitChunkCountPlugin:设置分块的最小/最大限制,以更好地控制过程
  • ProgressPlugin:报告编译进度
  • ProvidePlugin:无需使用import / require即可使用模块
  • TerserPlugin:在您的项目中启用对 Terser 版本的控制

在 Webpack 社区页面上有更多可用的插件;然而,前面的列表说明了更突出和有用的。接下来,我们将详细解释每一个。

We won't go over the final three plugins as they only need to be installed in the usual fashion.

每个插件的安装遵循与加载器相同的过程:

  1. 首先,使用命令行安装插件,然后更改配置文件以要求插件,类似于以下示例:
npm install full-name-of-plugin-goes-here-and-should-be-hyphenated-and-not-camelcase --save-dev

记住,这是一个通用的例子;你必须添加你的插件名称。以下配置也是如此,它遵循与大多数 Webpack 项目相同的过程,以及我们之前使用的相同配置文件webpack.config.js

  1. 我们现在应该准备好配置文件:
const MinifyPlugin = require("full-name-of-plugin-goes-here-and-should-be-hyphenated-not-camelcase");
module.exports = {
 entry: //...,
 output: //...,
 plugins: [
 new MinifyPlugin(minifyOpts, pluginOpts)
 ]
}

以上就是你对插件的一般性介绍。我们采取了一种通用的方法来防止过度复杂化。现在,我们可以继续讨论网络包中各种插件的一些有趣的方面。在下一小节中,我们将讨论以下内容:

  • BabelMinifyWebpackPlugin
  • CommonsChunkPlugin
  • ContextReplacementPlugin
  • HtmlWebpackPlugin
  • LimitChunkCountPlugin

大多数插件是由 Webpack 内部开发的,填补了加载程序还不能填补的开发空白。这些是一些更有趣的。先说BabelMinifyWebpackPlugin

BabelMinifyWebpackPlugin

在本小节中,我们将安装BabelMinifyWebpackPlugin。这个插件旨在缩小巴别塔脚本。如前所述,缩小是指删除错误或多余的代码来压缩应用的大小。要使用babel-loader并包含minify作为预设,请使用babel-minify。使用这个插件的babel-loader将会更快,并且可以处理更小的文件。

Webpack 中的加载器对单个文件进行操作,minify的预置将在浏览器的全局范围内直接执行每个文件;这是默认情况下完成的。顶级范围内的一些东西不会被优化。使用以下代码和minifyOptions可以优化文件的topLevel范围:

mangle: {
topLevel: true
}

node_modles被排除在通过babel-loader的运行之外时,minify 优化不会应用于被排除的文件,因为没有任何东西通过minifer

使用babel-loader时,生成的代码不经过加载器,没有优化。

一个插件可以对整个块或包输出进行操作,可以优化整个包,在缩小的输出中可以看到一些差异;然而,在这种情况下,文件大小将是巨大的。

巴贝尔插件在使用网络包时非常有用,它可以跨多个平台工作。我们将讨论的下一个插件是CommonsChunkPlugin,它被设计成与多个模块块一起工作——同样,这是 Webpack 非常固有的东西。

CommonsChunkPlugin

CommonsChunkPlugin是一个可选特征,它创建了一个单独的特征,称为块。组块由多个入口点之间共享的公共模块组成。

This plugin has been removed in Webpack 4 (Legato).

查看SplitChunkPlugin将向您展示更多关于 Legato 如何处理组块的信息。

生成的分块文件最初可以通过分离形成包的公共模块来加载一次。这将存储在缓存中供以后使用。

以这种方式使用缓存将允许浏览器更快地加载页面,而不是强制它加载更大的包。

在您的配置中使用以下声明来使用此插件:

new webpack.optimize.CommonsChunkPlugin(options);

一个简短的安装,但值得介绍。接下来,让我们一起来看看ContextReplacementPlugin

contcontexteployment 外挂程式

ContextReplacementPlugin是指带有扩展名的require语句,例如:

require('./locale/' + name + '.json')

当你遇到这样的表达式时,插件会推断出./local/的目录和一个正则表达式。如果编译时没有包含名称,那么每个文件都将作为一个模块包含在包中。这个插件将允许推断的信息被覆盖。

接下来要讨论的插件是HtmlWebpackPlugin

html webpackkplugin

HtmlWebpackPlugin简化 HTML 文件的创建以服务于捆绑包。这对于在文件名中包含哈希的包尤其有用,它会改变每次编译。

当使用这种方法时,我们有三种选择——使用带有lodash模板的模板,使用你的加载器,或者让插件生成一个 HTML 文件。该模板只是一个 HTML 模板,您可以使用lodash自动加载以提高速度。加载程序或插件可以生成它的 HTML 文件。这一切都加快了任何自动化过程。

当使用多个入口点时,它们将被包含在生成的 HTML 中的<script>标签中。

如果你在网络包的输出中有任何 CSS 资产,那么这些将被包含在生成的 HTML 的<head>元素中的<link>标签中。一个例子是如果 CSS 是用MiniCssExtractPlugin提取的。

回到大块的工作。下一个插件是一个处理限制块计数的插件。

LimitChunkCountPlugin

LimitChunkCountPlugin在按需加载时使用,因为可以使用许多代码拆分。编译时,您可能会注意到一些块非常小,这会产生更大的 HTTP 开销。LimitChunkCountPlugin可以通过合并对组块进行后处理。

可以通过使用大于或等于1的值来限制最大块数。使用1可防止添加额外的块作为主块或入口点块:

[/plugins/min-chunk-size-plugin]

将块大小保持在指定的限制之上不是您在 Webpack 5 中可以找到的功能;在这种情况下,应该使用MinChuckSizePlugin

以上就是我们对插件和本章的介绍。插件允许 Webpack 以多种方式工作,Webpack 使开发人员能够构建加载器并填补功能问题中的空白。当在需要自动化的大规模项目或复杂项目中工作时,它们是不可或缺的。

我们关于 API 的部分向您展示了,有时,我们并不总是想使用本地代码,并为您提供了一个很好的向库的过渡,我们将在下一章中讨论。

摘要

本章向您深入介绍了加载器及其在网络包中的使用方式。加载器是网络包的基础,但是插件是核心和支柱。本章将带您了解这些主题的主要功能,演示每个主题的最佳用途以及何时是在它们之间切换的好时机。

然后我们探索了插件以及它们是如何使用的,包括巴别塔、定制插件和加载器。我们还研究了应用编程接口及其使用,特别是在网络包中促进更广泛功能的应用编程接口,如巴贝尔和节点应用编程接口。

在下一章中,我们将讨论库和框架。我们对插件、API 和加载器的研究表明,有时,我们不想使用远程代码,比如库,但有时我们会使用。Webpack 通常处理本地托管的代码,但有时我们可能希望使用库。这为这个话题提供了一个很好的过渡。

问题

  1. 什么是i18n装载机?
  2. Webpack 通常用来转换 ECMA 脚本的工具链是什么?
  3. 巴别塔主要用于什么?
  4. 哪个加载程序允许用户添加巴贝尔配置的自定义处理?
  5. polymer-webpack-loader是做什么的?
  6. polymer-webpack-loader给开发者提供了什么?
  7. 使用 Node.js API 时,提供的回调函数会运行什么?