Preface: the author study webpack knowledge from the foundation to the principle to write a series, in order to review. Hope to help more friends who are learning Webpack.

Webpack series learning – First experience

Webpack series learning – Basic Usage one

Webpack series learning – various loaders to use

Webpack series learning – hot update and compression

Webpack series learning – Using ESLint and publishing NPM packages

Webpack series learning – Building webPack configurations

Webpack series learning – detailed implementation of easy Webpack

Webpack series learning -loader writing

Plugin can only run in Webpack

The basic structure of the plug-in


// Basic structure
class MyPlugin {
  apply(compiler){
    compiler.hooks.done.tap('My Plugin'.(
    // hooks for the plug-in
    ) = > {
      // Plug-in processing logic}}})module.exports = MyPlugin

// Plugins use:
plugins: [new MyPlugin()]
Copy the code

Here’s an example:

  • 1. Write simple plugins

// plugins/my-plugin.js
module.exports = class MyPlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    console.log('my plugin is done');
    console.log('compiler'.this.options); }};Copy the code
  • 2. Introduce MyPlugin in webpack
// webpack.config.js
const path = require('path');
const MyPlugin = require('./plugins/my-plugin');
module.exports = {
  entry: './src/index.js'.output: {
    path: path.join(__dirname, 'dist'),
    filename: 'main.js',},mode: 'production'.plugins: [
    new MyPlugin({
      name: 'curry',})]};Copy the code
  • 3. Run NPM run build to print the result

Let’s take a look at a complex plug-in scenario:

How do you get passed parameters in a plug-in?

  • From the plug-in’s constructor

module.exports = class MyPlugin {
  constructor(options){
    this.options = options;
  }
  
  apply(){
    console.log('apply'.this.options)
  }
}
Copy the code

Error handling of plug-ins?

  • 1. During parameter verification, you can directly throw the parameters
throw new Error('error message')
Copy the code
  • 2. Receive warnings and errors from the Compilation object
compilation.warnings.push('warning')
compilation.errors.push('erros')
Copy the code

How do I read and write files

  • The compilation is used to read and write files, and files are written to webpack-Sources
const { RawSources } = require('webpack-sources')
module.exports = class MyPlugin {
  constructor(options){
    this.options = options;
  }
  
  apply(compiler){
    const { name } = this.options;
    compiler.hooks('emit'.(compilation, cb) = > {
      compilation.assets[name] = new RawSources('demo')
      cb()
    })
  }
}
Copy the code

The following practice: write a compressed build resources for zip package plug-in

Requirements:

  • 1. The generated ZIP file name can be imported through the plug-in
  • 2. You need to use specific hooks on the Compiler object for resource generation

Preparation: Compressed files into zip packages in NodeJS

  • Use: jszip www.npmjs.com/package/jsz…
  • Example:
var zip = new JSZip();
 
zip.file("Hello.txt"."Hello World\n");
 
var img = zip.folder("images");
img.file("smile.gif", imgData, {base64: true});
 
zip.generateAsync({type:"blob"}).then(function(content) {
    // see FileSaver.js
    saveAs(content, "example.zip");
});
Copy the code

File generation: Emit is required

  • The hooks on the Compiler responsible for file generation are emit, an asynchronous hook
  • During the emit generation phase, the compiler. assets object is read. You can set the zip resource bundle to the compiler. assets object

Start writing:

Configuration webpack

// webpack.config.js
const path = require('path');
const ZipPlugin = require('./plugins/zip-plugin');
module.exports = {
  entry: './src/index.js'.output: {
    path: path.join(__dirname, 'dist'),
    filename: 'main.js',},mode: 'production'.plugins: [
    new ZipPlugin({
      filename: 'offline',})]};Copy the code

Write the zip – the plugin


// plugins/zip-plugin.js
const JSZip = require('jszip');
const path = require('path');
const { RawSource } = require('webpack-sources');

const zip = new JSZip();

module.exports = class ZipPlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    compiler.hooks.emit.tapAsync('ZipPlugin'.(compilation, callback) = > {
      const folder = zip.folder(this.options.filename);
      for (let filename in compilation.assets) {
        const source = compilation.assets[filename].source();
        folder.file(filename, source);
      }
      zip
        .generateAsync({
          type: 'nodebuffer',
        })
        .then(content= > {
          const outpath = path.join(compilation.options.output.path, `The ${this.options.filename}.zip`);
          const outputRelativePath = path.relative(compilation.options.output.path, outpath);
          compilation.assets[outputRelativePath] = newRawSource(content); callback(); }); }); }};Copy the code

Run NPM run build to see the results