webpack常用loader和plugin

2020-04-11  本文已影响0人  指尖跳动

webpack是一个模块打包器(module bundler),提供了一个核心,核心提供了很多开箱即用的功能,同时它可以用loader和plugin来扩展。webpack本身结构精巧,基于tapable的插件架构,扩展性强,众多的loader或者plugin让webpack显得很复杂。

webpack常用配置包括:devtool、entry、 output、module、resolve、plugins、externals等,本文主要介绍下webpack常用的loader和plugin

webpack允许我们使用loader来处理文件,loader是一个导出为function的node模块。可以将匹配到的文件进行一次转换,同时loader可以链式传递。

loader的使用方式

一般loader的使用方式分为三种:

  1. 在配置文件webpack.config.js中配置
module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: 'raw-loader'
      }
    ]
  }
}
  1. 通过命令行参数方式
webpack --module-bind 'txt=raw-loader'
  1. 通过内联使用
import txt from 'raw-loader!./file.txt';

webpack常用的loader

比如下面配置,可以匹配.scss的文件,分别经过sass-loader、css-loader、style-loader的处理。

sass-loader转化sass为css文件,并且包一层module.exports成为一个js module。style-loader将创建一个style标签将css文件嵌入到html中。css-loader则处理其中的@import和url()。

module.exports = {
  module: {
    rules: [
        {
          test: /\.scss$/,
          use:[
              {loader:'style-loader'},
              {loader:'css-loader',options:{sourceMap:true,modules:true}},
              {loader:'sass-loader',options:{sourceMap:true}}
          ],
          exclude:/node_modules/
      }
    ]
  }
}

如何写一个loader:官网介绍how to write a loader

下面是一个简单的raw-loader,它可以将文本类文件转成字符串到js文件中。其中this.cacheable、this.value等是loader的api,分别是将结果标记为可缓存和把值传递给下一个loader。

module.exports = function(content) {
  this.cacheable && this.cacheable();
  this.value = content;
  return "module.exports = " + JSON.stringify(content);
}

webpack的plugin比loader强大,通过钩子可以涉及整个构建流程,可以做一些在构建范围内的事情。

webpack常用的plugin

 new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object")
})
    const os = require('os');
    let HappyPack = require('happypack');
    let happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length});
    exports.plugins = [
      new HappyPack({
        id: 'jsx',
        threadPool: happyThreadPool,
        loaders: [ 'babel-loader' ]
      }),

      new HappyPack({
        id: 'coffeescripts',
        threadPool: happyThreadPool,
        loaders: [ 'coffee-loader' ]
      })
    ];

    exports.module.loaders = [
      {
        test: /\.js$/,
        loaders: [ 'happypack/loader?id=jsx' ]
      },
      {
        test: /\.coffee$/,
        loaders: [ 'happypack/loader?id=coffeescripts' ]
      },
    ]

写一个webpack插件:

官网介绍:how to write a plugin

主要的步骤如下:

编写插件之前要理解compiler和compilation两个对象,以及webpack生命周期的各个阶段和钩子,plugin比loader强大,通过plugin你可以访问compliler和compilation过程,通过钩子拦截webpack的执行。

比如我们可以在构建生成文件时,将所有生成的文件名生成到filelist.md的文件中

webpack会将compilation.assets的内容生成文件,所以可以在构建中利用它生成我们想要的文件。

function FileListPlugin(options) {}
FileListPlugin.prototype.apply = function(compiler) {
  compiler.plugin('emit', function(compilation, callback) {
    var filelist = 'In this build:\n\n';
    for (var filename in compilation.assets) {
      filelist += ('- '+ filename +'\n');
    }
    compilation.assets['filelist.md'] = {
      source: function() {
        return filelist;
      },
      size: function() {
        return filelist.length;
      }
    };
    callback();
  });
};

module.exports = FileListPlugin;

比如我们可以在html-webpack-plugin生成文件后刷新页面,完成热更新效果。

var webpack = require('webpack')
var webpackConfig = require('./webpack.config')
var compiler = webpack(webpackConfig)
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  log: () => {}
})
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

比如我们可以在构建完成后,打开一个提示窗口。

class Notifier {
  apply(compiler) {
    compiler.plugin("done", (stats) => {
      const pkg = require("./package.json");
      const notifier = require("node-notifier");
      const time = ((stats.endTime - stats.startTime) / 1000).toFixed(2);

      notifier.notify({
        title: pkg.name,
        message: `WebPack is done!\n${stats.compilation.errors.length} errors in ${time}s`,
        contentImage: "https://path/to/your/logo.png",
      });
    });
  }
}

module.exports = Notifier;
上一篇 下一篇

猜你喜欢

热点阅读