webpack笔记:写一个loader和plugin

附件下载:自己实现一个loader和plugin.zip

在开始React或者Vue新项目时,我们一般使用脚手架快速的搭建一个工程,脚手架帮我们省去了很多繁琐的配置,但同时也让webpack成了一个迷。在我之前几年的工作经验中,很少真的去了解webpack,遇到问题了网上找点资料复制粘贴一下配置,解决了问题也就没有再去管它,相信很多人应该跟我一样的情况。

webpack这样一个在前端广泛使用的一个工具,还是有必要学习的。loader和plugins是两个重要的核心概念,本文通过实现和应用来了解它们的工作原理。如果想全面的学习或了解webpack,推荐阅读 webpack官网。

编写一个loader

loader用来对源码进行编译转换,比如把ES6编译为ES5,把less编译为css等。一个loader就是一个function,接收一个source参数,对source进行一些处理后返回。
在开发调试时我们会写一些console.log,在生产环境中建议删除。我们可以实现这样一个loader,打包编译时自动删除console.log。如下图,npm init后写一个简单的方法,这样就实现了我们要的功能。

// 目录结构
loader-demo
 ├─index.js
 └package.json
// index.js内容
module.exports = function(source) {
  console.log('----------- loader -----------');
  return source.replace(/console\.log\(.*?\)/, '');
}

使用这个loader

  • 发布loader
    可以用npm publish命令将loader-demo发布到npm仓库,为了方便测试,也可以使用npm link命令。进入loader-demo目录,执行npm link。
  • 在另一个工程使用
    我们新建一个npm+webpack工程,名为webpack-demo,在工程目录下执行npm link loader-demo。在配置文件里使用loader-demo如下,匹配js文件,使用loader-demo来处理,每个匹配的文件都会把源码传给我们的loader-demo方法进行处理。
// 目录结构
webpack-demo
 ├─package.json
 ├─webpack.config.js
 ├─src
   ├─index.js
   └print.js
// webpack.config.js内容
const path = require('path');
module.exports = {
  entry: './src/index',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'loader-demo'
      }
    ]
  }
}
  • 看一下效果
    使用loader-demo前,在打包后的文件里可以搜索到console.log,使用loader-demo后,在打包后的文件里搜索不到console.log,说明我们的loader起了效果。在本文的最开始处有附件,可以下载尝试。

编写一个plugin

插件能做的事情更多,这里实现一个简单的功能:在打包后的每个js文件头部加入版权信息。

// 目录结构
yo-plugin-demo
 ├─index.js
 └package.json
// index.js内容
module.exports = class PloginDemo {
  // 构造器,传入版权信息
  constructor(crInfo) {
    this.crInfo = crInfo;
  }
  // 必须,webpack运行时调用
  apply(compiler) {
    // webpack生命周期,生成资源到output目录之前执行
    // 具体可以查看 https://www.webpackjs.com/api/compiler-hooks
    compiler.hooks.emit.tap('YoPluginDemo', compilation => {
      console.log('----------- plugin -----------');
      // 遍历所有资源,以js结尾的文件,在头部加上版权信息
      for(const fileName in compilation.assets) {
        if(/\.js$/.test(fileName)) {
          const asset = compilation.assets[fileName];
          asset.source = () => {
            return `/** Copyright © ${this.crInfo} */\r\n${asset._value}`
          }
        }
      }
    });
  }
}

使用这个plugin

  • 发布plugin(跟前面讲的loader一样)
    npm link
  • 在另一个工程使用(使用前面说到的webpack-demo)
    npm link yo-plugin-demo
// webpack.config.js内容
const path = require('path');
const YoPluginDemo = require('yo-plugin-demo');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/index',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'loader-demo'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new YoPluginDemo('2020 朽木'),
  ]
}
  • 看一下效果
    在打包后的js文件头部可以看到/** Copyright © 2020 朽木 */,表示插件使用成功。

你可能感兴趣的:(webpack笔记:写一个loader和plugin)