返回 登录
1

Webpack的精彩世界

阅读2920

Webpack是一个JavaScript模块打包工具,如官网宣传的那样。它有一个贴切的名字。但在本文中,我想完成的是详述Webpack真正强大的地方。

本文不会介绍如何使用Webpack,而是解析使它比一般打包工具变得更为特殊的原因。

Webpack仍是一种打包工具

像Webpack此类工具产生的最主要原因之一,便是解决依赖问题。该依赖问题是JavaScript(尤其是Node.js中的模块所导致的。

Node.js允许你使用模块化代码。代码的模块化导致了依赖问题。循环依赖( Cyclic dependencies )可能会产生,例如, A->B->A的引用关系。像Webpack这样的工具,可以构建模块引用的完整依赖图。通过这个图,分析器可以帮助减轻依赖图的压力。

Webpack在代码中置入多个入口,并有一个输出,该输出已完成将依赖图与一个或多个文件进行捆绑。

Webpack可以做得更多

对于我来说,Webpack如此特殊,缘于它提供的优秀的扩展。

Loaders

Loader是我喜欢提及的mini-transpiler。它适用于任何类型的文件,如TypeScript、CoffeeScript、JSON等,之后产生的JavaScript代码添加至Webpack正构建的依赖图中。

Loader的魅力在于,它们是源源不断的。Loader是一个扩展,你可以创建自己的Loader,目前已有100个默认和大量第三方的Loader。

例如,如果想把静态类型语言,如C#,编译成Webpack可以理解的JavaScript,有没有这样一个Loader?

Loader具有无限可能,具有可组装、可配置、基于文件类型进行过滤等特点。

一个普通的例子

正如Webpack文档中解释的那样,一个Loader只是一个可以输出funtion的Node.js模块。一个Loader与输出function的Node.js模块同样简单:

 module.exports = function(src) {
        return src + '\n'
            + 'window.onload = function() { \n'
            + ' console.log("This is from the loader!"); \n'
            + '}';
    };

这是解释Loader是什么的一个小例子。这个Loader正在添加一个function,该function的功能是在当前的浏览器会话中,当Window加载时,在控制台上进行输出。

记住这一点,我们就不难理解:无论源是任何类型的语言,都可以按我们的想法进行解释。重新回答我们刚才的例子中,我们可以把C#作为输入,创建一个解析器,将它转换为Webpack可以接受的自然JavaScript。

将C#转换成JavaScript的编译器,虽有点牵强附会,说实在的有些无意义,但我希望你可以领导会我们是如何利用Loader,让Webpack不再仅仅是一个bundler。

Plugins

相比于Loader,插件让Webpack可进行的定制化服务更加广泛。在插件中,你可以在Webpack中增加额外的功能。例如,你可以添加实现缩小功能的插件,从输出(如CSS)中提取某些文本,利用插件进行压缩等。

插件通过自行访问Webpack编译器完成工作。它们能访问可能产生的所有编译步骤,并可以修改所有的步骤。这意味着一个插件可以修改文件已经生成的内容,可以修改文件引入的内容等。

下面是插件的一个小例子:

 file: './my-custom-plugin.js'

function MyCustomPlugin() {}

MyCustomPlugin.prototype.apply = function(compiler) {
    compiler.plugin('emit', displayCurrentDate);
    compiler.plugin('after-emit', displayCurrentDate)
}

function displayCurrentDate(compilation, callback) {
    console.log(Date());

    callback();
}

module.exports = MyCustomPlugin;

该例子中,我们在Webpack编译器中,为两个event hook分别添加了事件处理器。其结果是在asset被输出到结果目录之前,在控制台打印一个日期,在asset已被输出后再打印一个日期。

该插件也可以应用到Webpack的配置中:

 var MyCustomPlugin = require('my-custom-plugin');

var webpackConfig = {
    ...
    plugins: [
        new MyCustomPlugin()
    ]
}

现在这个插件可以在编译过程中的emit和after-emit两个阶段运行。Webpack网站上有一个很好的 compiler event hook列表可以使用。

重申一遍,插件的重要性在于它们是扩展。Webpack允许用户完全扩展它的内核。已有很多插件可供选择,很多来自第三方。

请记住这一点,插件可以获取你请求的Asset,并通过一定的算法对他们进行压缩。事实上,现在已经有插件可以完成这件事了。

总结

Webpack是一个模块打包工具。它可以产生依赖图,输出浏览器可读的格式。

然而,Webpack还可以做得更多。

假设我们可以将C#代码编译成JavaScript会怎样呢?假设我们获得一个图片,想自动完成裁剪与使用灰度来表示会怎样呢?

我想如果你把Webpack看成一个编译器,而不仅仅是一个打包工具,那你将看到它真正的强大之处。

原文链接:The Wonderful World of Webpack
作者: Jack Histon

评论