Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack中的插件以及如何编写一个插件 #4

Open
SunShinewyf opened this issue May 2, 2017 · 0 comments
Open

webpack中的插件以及如何编写一个插件 #4

SunShinewyf opened this issue May 2, 2017 · 0 comments

Comments

@SunShinewyf
Copy link
Owner

SunShinewyf commented May 2, 2017

webpack中的插件

webpack中的插件主要是为webpack添加功能的,webpack中的每个插件都会在webpack启动时被安装一次,webpack主要是通过调用插件的apply方法来安装它们,插件可以完成更多loader不能完成的功能。
插件的使用一般是在webpack的配置信息plugins选项中指定。下面是一个简单的使用webpack插件的配置代码:

const webpack = require('webpack');
const extractTextPlugin = require('extract-text-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash')

module.exports = {
    entry: {
        'a': './a',
        'b': './b'
    },

    output:{
        filename:'[name]-[chunkhash].js'
    },
    module: {
        loaders: [
            {
                test: /\.css$/,
                loader: extractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
            },
            {
                test:  /\.(png|jpg)$/,
                loader:'url-loader?limit=1000&name=images/[name].[hash].[ext]'
            }
        ],
    },
    plugins: [
        new extractTextPlugin('[name].[contenthash:4].css'),
        new WebpackMd5Hash()
    ],
}

如上面的配置信息所示,该配置文件使用了extractTextpluginWebpackMd5Hash这两个插件。关于webpack的更多插件信息可以移步这里.

怎么样编写一个插件

关于如何开发一个新的webpack插件,通过搜索可以发现,基本上很少有这方面的资料。除了官方文档里面的寥寥数语就只有几篇博客稍微介绍了一下。原因是编写webpack插件需要首先去通读compile
compilation的源码,有一定的门槛。这里是官方的how to write a plugin的介绍。并且给出了一个插件的基本结构如下:

function HelloWorldPlugin(options) {
  // Setup the plugin instance with options...
}

HelloWorldPlugin.prototype.apply = function(compiler) {
  compiler.plugin('done', function() {
    console.log('Hello World!');
  });
};

module.exports = HelloWorldPlugin;

也就是需要定义一个含有apply的原型方法的对象并将其导出。原因是这个apply方法在安装插件时将被webpack编译器调用一次,apply方法提供了一个对应的编译器对象的引用,从而可以在回调函数中访问到
compile对象。但是这个文档也是写得很简单,所以笔者在接触和实践的时候还是花了很多时间去看已经有的webpack 插件的源码。
编写webpack插件的关键部分是要在compilecompilation对象的构建流程中进行提供回调函数来进行拓展处理。关于compilecompilation的回调和信息,以及一些重要的对象,可以参考这里
下面就根据下面这个例子来讲解:

function FileListPlugin(options) {}

FileListPlugin.prototype.apply = function(compiler) {
  compiler.plugin('emit', function(compilation, callback) {
    // Create a header string for the generated file:
    var filelist = 'In this build:\n\n';

    // Loop through all compiled assets,
    // adding a new line item for each filename.
    for (var filename in compilation.assets) {
      filelist += ('- '+ filename +'\n');
    }

    // Insert this list into the Webpack build as a new file asset:
    compilation.assets['filelist.md'] = {
      source: function() {
        return filelist;
      },
      size: function() {
        return filelist.length;
      }
    };

    callback();
  });
};

module.exports = FileListPlugin;

上面这个例子主要是将compilation生成的assets模块写进filelist.md这个文件中。上面是在compile对象的emit构建阶段提供来一个回调函数来进行拓展处理。查阅官方文档可以知道,emit流程时,
编译器开始输出生成资源。这里是插件向 c.assets 数组添加生成资源的最后机会,这样的话就会在指定目录中生成一个filelist.md文件,而不用自己去写fs.writeFileSync去生成该文件,而是借助于
webpack帮我们生成。

当然根据开发人员不同的业务需求,对插件的要求不一样,所以可以在compilecompilation的不同构建流程来提供一些拓展的回调函数,从而可以达到自己的业务需求。

下面是笔者通过阅读源码而总结的从命令行敲入命令后,webpack编译器执行的一系列流程:
image

参考资料:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant