2. Webpack的基础回顾以及Loader和Plugin的原理

20 阅读2分钟

Bundler - 打包工具

将浏览器不支持的模块进行编译,转换,合并最后生成的代码可以在浏览器端良好的运行的工具。

Loader
webpack.docschina.org/concepts/lo…
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load (加载)" 模块时预处理文件。

多个 Loader
module.rules 允许你在 webpack 配置中指定多个 loader。 这种方式是展示 loader 的一种简明方式,并且有助于使代码变得简洁和易于维护。

plugins
webpack.docschina.org/concepts/pl… 插件是 webpack 的支柱功能。webpack 自身也是构建于你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 无法实现的其他事。(我自己的理解,loader 解决的是各种不同资源的问题,plugins 更多解决的是项目整体的事情)

markdown 语法处理

const marked = require('marked')
const markdownLoader = (source) => {
  // source file content
  console.log(source)
  const html = marked(source)
  const code = `module.exports = ${JSON.stringify(html)}`
  return code
}

module.exports = markdownLoader

loader 获取参数

配置

{
  test: /.md$/,
  use: [
    { loader: './markdown-loader', options: { headerIds: false }}
  ]
}

读取配置

const marked = require('marked')
const utils = require('loader-utils') // 用来读取变量的
function markdownLoader(source) {
  const options = utils.getOptions(this)
  const html = marked(source, options)
  const code = `module.exports = ${JSON.stringify(html)}`
  return code
}

module.exports = markdownLoader

Plugins 的原理

Loaders 关注代码中的单个资源,Plugins 关注整体流程,可以接触到 webpack 构建流程中的各个阶段并劫持做一些代码处理。

官方的教程:webpack.js.org/contribute/…

插件的格式

  • 一个 JavaScript 函数或 JavaScript 类
  • 在它原型上定义的 apply 方法,会在安装插件时被调用,并被 webpack compiler 调用一次
  • 指定一个触及到 webpack 本身的事件钩子,即 hooks,用于特定时机处理额外的逻辑

Compiler Hooks 列表
webpack.js.org/api/compile…

class BundlesizeWebpackPlugin {
  constructor(options) {
    this.options = options
  }
  apply(compiler) {
    console.log('bundle size plugin')
    compiler.hooks.compile.tap('BundleSizePlugin', (compilationParams) => {
      console.log('compile', compilationParams)
    })
    compiler.hooks.done.tap('BundleSizePlugin', (stats) => {
      console.log('done', stats)
    })
  }
}
module.exports = BundlesizeWebpackPlugin

提示最终生成的文件大小是否符合要求
配置:

plugins: [
  new BundlesizeWebpackPlugin({ sizeLimit: 3 }),
  new webpack.ProgressPlugin(),
  new HtmlWebpackPlugin()
]

BundlesizeWebpackPlugin 代码:

compiler.hooks.done.tap('BundleSizePlugin', (stats) => {
    // get path and filename from outputOptions
    const { path, filename } = stats.compilation.outputOptions
    // generate a bundle path
    const bundlePath = resolve(path, filename)
    // get file size in Kb
    const { size } = statSync(bundlePath)
    const bundleSize = size / 1024
    if (bundleSize < sizeLimit) {
        console.log(
            "Safe:Bundle-Size",
            bundleSize,
            "\n SIZE LIMIT:",
            sizeLimit
        );
    } else {
        console.error(
            "Unsafe:Bundle-Size",
            bundleSize,
            "\n SIZE LIMIT:",
            sizeLimit
        );
    }
})